The Bixby viv.navigation
library capsule enables your capsule to launch Google Maps with a provided destination for turn-by-turn directions.
The Navigation library provides two punchout actions, NavigatePunchout
and NavigateStringAndCoordinatesPunchout
, that both output a Navigate
concept. That concept matches a view provided by the library, and that view contains an app-launch
to launch Google Maps.
NavigatePunchout
requires a navigation.Destination
concept as input, which has the role of geo.NamedPoint
.NavigateStringAndCoordinatesPunchout
requires a text string (such as an address) and a latitude/longitude coordinate to use as the center of the search area as inputs. Depending on your capsule's functionality, this might provide a better display in the map card than solely using Bixby's built-in reverse address lookup functionality.In your capsule, you can create a concept that takes on the role-of
the Navigate
concept:
structure (MyNavigate) {
role-of (navigation.Navigate)
}
To use one of the Navigation library's punchout actions, your capsule should include an action that constructs a navigation.Destination
concept or a navigation.Navigate
concept. Those constructors should work with the inputs available in your capsule, which could be a search term or could be another concept with location information.
If your capsule uses geo.SearchTerm
for training, your constructor action can simply take a NamedPoint
.
action (ConstructDestination) {
type (Constructor)
collect {
input (namedPoint) {
type (geo.NamedPoint)
min (Required) max (One)
}
}
output (navigation.Destination) {
evaluate {
$expr (namedPoint)
}
}
}
A training example for this could be as follows:
[g:MyNavigate] Give me directions to (Costco)[v:geo.SearchTerm]
Instead of using SearchTerm
directly, your capsule might provide a "Get Directions" button on a card that displays business information from a Business
concept. In that case, your constructor will need to take the Business
concept as its input.
action (ConstructDestination) {
type (Constructor)
description (Make a NamedPoint from a Business.)
collect {
input (business) {
type (Business)
min (Required) max (One)
}
}
output (navigation.Destination)
}
Assume the Business
concept has an address
property, and that property has the role of geo.Address
. The JavaScript implementation for constructDestination
can use that to return a NamedPoint
.
export function constructDestination(input) {
const { business } = input
const businessGeoPoint = business.address.centroid
return {
name: business.name,
address: business.address,
point: {
latitude: businessGeoPoint.latitude,
longitude: businessGeoPoint.longitude,
},
}
}
The name
key is optional. If provided, the name will be sent to Google Maps as well.
The training example given for SearchTerm
can be replicated with a Business
concept:
[g:Navigate] Get me directions to (Hanabi Sushi)[v:BusinessName]
However, you'll get more flexibility by using SearchTerm
in that use case.
To use NavigateStringAndCoordinatesPunchout
, you can construct a Navigate
concept, which has two properties described earlier: the destinationString
(a text search string, for example, an address) and destinationPoint
(a GeoPoint
to use as the search's center reference point). Your capsule can use evaluate
to construct a Navigate
concept from destinationString
and destinationPoint
inputs. Those inputs could be taken from the name and point properties of a geo.NamedPoint
.
In this example, the GasStation
concept has a name
text property and a coordinates
GeoPoint property. The action uses default-init
to set destinationString
and destinationPoint
from the GasStation
input, and outputs a Navigate
concept.
action (ConstructNavigate) {
type (Constructor)
description (Construct a Navigate concept)
collect {
input (gasStation) {
type (GasStation)
min (Required) max (One)
}
input (destinationString) {
type (viv.core.Text)
min (Optional) max (One)
default-init {
intent {
goal: viv.core.Text
value: $expr(gasStation.name)
}
}
}
input (destinationPoint) {
type (viv.geo.GeoPoint)
min (Required) max (One)
default-init {
intent {
goal: viv.geo.GeoPoint
value: $expr(gasStation.coordinates)
}
}
}
input (navigate) {
type (navigation.Navigate)
min (Required) max (One)
default-init {
intent {
goal: navigation.Navigate
value: $expr(destinationString)
value: $expr(destinationPoint)
}
}
}
}
output (navigation.Navigate) {
evaluate {
navigation.Navigate {
punchoutString: $expr(navigate.punchoutString)
}
}
}
}
Training examples for this would use your constructor action as the goal.
In the example of using a Business concept to navigate to, you might want to allow the user to give a voice command like "Navigate there" when Bixby is displaying the Business. To handle this, you can train a continuation.
A continuation needs a Flag
of Route
that points to your Constructor function. In our example, this would be r:ConstructDestination
:
[g:MyNavigate:continue:Business,r:ConstructDestination] Navigate there
Here are some suggested phrases to train as a continuation.
When using a concept for input, you'll need to supply your capsule with a dialog for the outer query. This will be used when more than one destination is matched by the input term.
dialog (Selection) {
match: Business {
to-input: ConstructDestination
}
template("Which one do you want to go to?")
}
If you are using SearchTerm
, you do not need to supply this; it will be handled for you.
Destination
: a geo.NamedPoint
specifying the destination.
Origin
: a geo.NamedPoint
specifying the origin. In many cases, you won't need to provide an Origin
; if none is given, Google Maps will use the user's current location. If you do provide an Origin
, it will be passed to Google Maps as the starting point for directions.
Navigate
: The model output by the NavigatePunchout
action. This is matched by a view in viv.navigation
which contains an app-launch
to launch Google Maps.
Currently, viv.navigation
does not let you specify a travel mode (such as driving, walking, or public transit). The user can, however, change their travel mode within Google Maps.