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 thereHere 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.