MSI Route Management
Create, manage, and optimize routes with comprehensive routing capabilities.
Route Management Overview
The MSI Controls API provides powerful routing features:
- Traffic-aware route calculation
- Multi-waypoint support
- Route optimization
- Alternative routes
- Animated route visualization
- Turn-by-turn directions
Complete Route Creation
setRoute()
Create a complete route from origin to destination with optional waypoints.
Basic Route
Simple point-to-point route
const route = await controls.setRoute({
origin: { lng: -74.0060, lat: 40.7128 },
destination: { lng: -73.9855, lat: 40.7580 }
})
console.log('Route created:', route)
// {
// distance: 5420, // meters
// duration: 960, // seconds
// geometry: [...], // route coordinates
// steps: [...] // turn-by-turn directions
// }Route with Options
Customize route calculation and display
const route = await controls.setRoute({
origin: { lng: -74.0060, lat: 40.7128 },
destination: { lng: -73.9855, lat: 40.7580 },
// Route calculation options
options: {
profile: 'driving-traffic', // Routing profile
mode: 'fastest', // Route preference
avoidTolls: false, // Avoid toll roads
avoidHighways: false, // Avoid highways
avoidFerries: true, // Avoid ferries
alternatives: 3 // Number of alternative routes
},
// Visual options
animation: {
type: 'flow', // Animation type
color: '#0ea5e9', // Route color
width: 6, // Line width
opacity: 0.8 // Line opacity
},
// Auto-fit viewport
fitBounds: true,
fitBoundsPadding: 50
})Route Profiles:
driving- Standard car routingdriving-traffic- Traffic-aware routing (recommended)walking- Pedestrian routingcycling- Bicycle routing
Route Modes:
fastest- Minimize time (default)shortest- Minimize distancebalanced- Balance time and distance
Animation Types:
solid- Static lineflow- Flowing animationdots- Dotted animationdash- Dashed line
Multi-waypoint Route
Route with intermediate stops
const route = await controls.setRoute({
origin: { lng: -74.0060, lat: 40.7128 },
waypoints: [
{ lng: -73.9951, lat: 40.7489 }, // Stop 1
{ lng: -73.9844, lat: 40.7614 }, // Stop 2
{ lng: -73.9712, lat: 40.7831 } // Stop 3
],
destination: { lng: -73.9855, lat: 40.7580 },
options: {
profile: 'driving-traffic',
optimizeWaypoints: true // Auto-optimize waypoint order
}
})
console.log('Optimized order:', route.waypointOrder)
// [0, 2, 1] - Optimal visit sequenceRoute Components
Build routes step-by-step using individual components.
setRouteOrigin()
Set the starting point of a route.
Set Origin
Define route starting point
await controls.setRouteOrigin(
{ lng: -74.0060, lat: 40.7128 },
{
label: 'Warehouse',
sublabel: '123 Main St',
markerColor: 'green',
draggable: false
}
)Parameters:
{
coordinates: Location
options?: {
label?: string
sublabel?: string
markerColor?: string
draggable?: boolean
icon?: string
}
}setRouteDestination()
Set the ending point of a route.
Set Destination
Define route ending point
await controls.setRouteDestination(
{ lng: -73.9855, lat: 40.7580 },
{
label: 'Customer',
sublabel: '456 Oak Ave',
markerColor: 'red',
draggable: true,
onDragEnd: async (newLocation) => {
// Recalculate route when marker is dragged
await recalculateRoute(newLocation)
}
}
)addRouteWaypoint()
Add an intermediate stop to the route.
Add Waypoint
Add stop along the route
const waypointId = await controls.addRouteWaypoint(
{ lng: -73.9951, lat: 40.7489 },
{
label: 'Pickup Point',
order: 1, // Position in route
markerColor: 'blue',
draggable: true
}
)
console.log('Waypoint added:', waypointId)Returns: Promise<string> - Waypoint ID for later reference
updateRouteWaypoint()
Modify an existing waypoint.
await controls.updateRouteWaypoint(waypointId, {
coordinates: { lng: -73.9900, lat: 40.7500 },
label: 'Updated Pickup',
markerColor: 'orange'
})removeRouteWaypoint()
Remove a waypoint from the route.
await controls.removeRouteWaypoint(waypointId)Route Utilities
fitRouteBounds()
Adjust viewport to show the entire route.
await controls.fitRouteBounds({
padding: 100, // Padding in pixels
maxZoom: 16, // Maximum zoom level
animate: true, // Smooth animation
duration: 1000 // Animation duration
})fitRoutesBounds()
Show multiple routes in viewport (for comparing alternatives).
await controls.fitRoutesBounds(['route-1', 'route-2', 'route-3'], {
padding: 50,
animate: true
})getRouteDetails()
Get detailed information about the current route.
const details = await controls.getRouteDetails()
console.log('Route details:', details)
// {
// distance: 5420, // Total distance (meters)
// duration: 960, // Total duration (seconds)
// durationInTraffic: 1200, // Duration with traffic
// bounds: {...}, // Route bounding box
// steps: [...], // Turn-by-turn steps
// waypoints: [...], // Ordered waypoints
// geometry: [...], // Route coordinates
// legs: [...] // Route segments
// }getAlternativeRoutes()
Get alternative route options.
const alternatives = await controls.getAlternativeRoutes()
alternatives.forEach((route, index) => {
console.log(`Route ${index + 1}:`)
console.log(` Distance: ${route.distance}m`)
console.log(` Duration: ${route.duration}s`)
console.log(` Traffic: ${route.durationInTraffic}s`)
})
// Select alternative route
await controls.selectRoute(alternatives[1].id)clearRoute()
Remove the current route from the map.
await controls.clearRoute()Waypoint Captions
Add labels and information to waypoints.
setWaypointCaption()
Add a caption to a waypoint.
Add Caption
Label waypoints with details
await controls.setWaypointCaption(waypointId, {
title: 'Customer Pickup',
subtitle: '123 Main Street',
description: 'Ring doorbell - apartment 2B',
eta: '10:30 AM',
status: 'pending',
color: '#0ea5e9'
})updateWaypointCaption()
Modify waypoint caption content.
await controls.updateWaypointCaption(waypointId, {
status: 'completed',
color: '#10b981',
completedAt: new Date().toISOString()
})removeWaypointCaption()
Remove caption from waypoint.
await controls.removeWaypointCaption(waypointId)Custom Caption Styling
await controls.setWaypointCaption(waypointId, {
title: 'Delivery Stop',
style: {
backgroundColor: '#1e293b',
textColor: '#ffffff',
borderColor: '#0ea5e9',
borderWidth: 2,
padding: 12,
borderRadius: 8,
fontSize: 14,
fontWeight: 600
}
})Route Optimization
Optimize Waypoint Order
Automatically reorder waypoints for the most efficient route.
const optimizedRoute = await controls.optimizeRoute({
origin: { lng: -74.0060, lat: 40.7128 },
waypoints: [
{ lng: -73.9951, lat: 40.7489, id: 'stop-1' },
{ lng: -73.9844, lat: 40.7614, id: 'stop-2' },
{ lng: -73.9712, lat: 40.7831, id: 'stop-3' },
{ lng: -73.9855, lat: 40.7580, id: 'stop-4' }
],
destination: { lng: -74.0000, lat: 40.7200 },
options: {
profile: 'driving-traffic',
optimizationCriteria: 'duration', // or 'distance'
timeWindows: {
'stop-2': {
start: '14:00',
end: '16:00'
}
}
}
})
console.log('Optimized order:', optimizedRoute.waypointOrder)
console.log('Time saved:', optimizedRoute.timeSaved, 'seconds')Route with Time Windows
Create routes respecting delivery time windows.
const route = await controls.setRoute({
origin: warehouse,
waypoints: deliveryStops.map(stop => ({
...stop.coordinates,
timeWindow: {
earliest: stop.deliveryWindow.start,
latest: stop.deliveryWindow.end
}
})),
destination: warehouse,
options: {
profile: 'driving-traffic',
departureTime: new Date().toISOString(),
respectTimeWindows: true
}
})
// Check feasibility
if (!route.feasible) {
console.warn('Cannot meet all time windows')
console.log('Violations:', route.violations)
}Traffic-Aware Routing
Real-time Traffic
Get routes that consider current traffic conditions.
const route = await controls.setRoute({
origin: pickup,
destination: dropoff,
options: {
profile: 'driving-traffic',
departureTime: 'now',
trafficModel: 'best_guess' // 'best_guess', 'pessimistic', 'optimistic'
}
})
console.log('Normal duration:', route.duration, 'seconds')
console.log('With traffic:', route.durationInTraffic, 'seconds')
console.log('Delay:', route.durationInTraffic - route.duration, 'seconds')Departure Time Planning
Calculate routes for specific departure times.
// Route departing in 30 minutes
const futureRoute = await controls.setRoute({
origin: pickup,
destination: dropoff,
options: {
profile: 'driving-traffic',
departureTime: new Date(Date.now() + 30 * 60 * 1000).toISOString()
}
})
// Route departing at specific time
const scheduledRoute = await controls.setRoute({
origin: pickup,
destination: dropoff,
options: {
profile: 'driving-traffic',
departureTime: '2024-03-15T14:30:00Z'
}
})Advanced Route Features
Route Events
Listen to route-related events.
controls.on('route:created', (route) => {
console.log('New route created:', route)
})
controls.on('route:updated', (route) => {
console.log('Route updated:', route)
})
controls.on('route:cleared', () => {
console.log('Route removed')
})
controls.on('waypoint:added', (waypoint) => {
console.log('Waypoint added:', waypoint)
})
controls.on('waypoint:dragged', (waypoint) => {
console.log('Waypoint moved:', waypoint)
})Route Comparison
Compare multiple route options.
async function compareRoutes() {
const routes = await controls.getAlternativeRoutes()
const comparison = routes.map(route => ({
id: route.id,
distance: route.distance,
duration: route.duration,
traffic: route.durationInTraffic,
delay: route.durationInTraffic - route.duration,
tollFees: route.tollFees,
score: calculateRouteScore(route)
}))
// Sort by best score
comparison.sort((a, b) => b.score - a.score)
return comparison
}
function calculateRouteScore(route) {
const distanceScore = 1 / route.distance
const timeScore = 1 / route.durationInTraffic
const tollPenalty = route.tollFees * 0.1
return (distanceScore + timeScore) - tollPenalty
}Dynamic Route Updates
Update route when conditions change.
class RouteManager {
private currentRoute: any
private updateInterval: any
async startMonitoring() {
// Update route every 5 minutes
this.updateInterval = setInterval(async () => {
const updatedRoute = await controls.setRoute({
origin: this.currentRoute.origin,
destination: this.currentRoute.destination,
waypoints: this.currentRoute.waypoints,
options: {
profile: 'driving-traffic',
departureTime: 'now'
}
})
// Check if route changed significantly
const timeDiff = Math.abs(
updatedRoute.durationInTraffic -
this.currentRoute.durationInTraffic
)
if (timeDiff > 300) { // 5 minutes
console.log('Significant traffic change detected')
this.notifyDriver(updatedRoute)
}
this.currentRoute = updatedRoute
}, 5 * 60 * 1000)
}
stopMonitoring() {
clearInterval(this.updateInterval)
}
}Complete Examples
Multi-stop Delivery Route
import De from '@de./sdk'
const msi = new De.MSI({
element: 'map',
accessToken: token
})
const { controls } = await msi.load()
// Warehouse location
const warehouse = { lng: -74.0060, lat: 40.7128 }
// Delivery stops
const deliveries = [
{
id: 'order-1',
address: '123 Main St',
coordinates: { lng: -73.9951, lat: 40.7489 },
timeWindow: { start: '09:00', end: '12:00' }
},
{
id: 'order-2',
address: '456 Oak Ave',
coordinates: { lng: -73.9844, lat: 40.7614 },
timeWindow: { start: '10:00', end: '14:00' }
},
{
id: 'order-3',
address: '789 Pine Rd',
coordinates: { lng: -73.9712, lat: 40.7831 },
timeWindow: { start: '13:00', end: '17:00' }
}
]
// Create optimized route
const route = await controls.setRoute({
origin: warehouse,
waypoints: deliveries.map(d => ({
...d.coordinates,
id: d.id,
timeWindow: d.timeWindow
})),
destination: warehouse,
options: {
profile: 'driving-traffic',
optimizeWaypoints: true,
respectTimeWindows: true,
departureTime: '08:00'
},
animation: {
type: 'flow',
color: '#0ea5e9'
},
fitBounds: true
})
// Add captions to each stop
deliveries.forEach(async (delivery, index) => {
const waypointId = route.waypoints[index].id
await controls.setWaypointCaption(waypointId, {
title: `Stop ${index + 1}`,
subtitle: delivery.address,
eta: route.legs[index].arrivalTime,
status: 'pending'
})
})
console.log('Route created:')
console.log('Total distance:', route.distance, 'meters')
console.log('Total duration:', route.duration, 'seconds')
console.log('Optimized order:', route.waypointOrder)Route with Live Traffic Updates
class LiveRouteTracker {
private controls: MSIControls
private route: any
private trafficCheckInterval: any
constructor(controls: MSIControls) {
this.controls = controls
}
async startRoute(origin: Location, destination: Location) {
// Create initial route
this.route = await this.controls.setRoute({
origin,
destination,
options: {
profile: 'driving-traffic',
departureTime: 'now',
alternatives: 2
}
})
// Check traffic every 2 minutes
this.trafficCheckInterval = setInterval(
() => this.updateTraffic(),
2 * 60 * 1000
)
}
async updateTraffic() {
const alternatives = await this.controls.getAlternativeRoutes()
// Find faster route
const fasterRoute = alternatives.find(
route => route.durationInTraffic < this.route.durationInTraffic - 300
)
if (fasterRoute) {
console.log('Faster route found!')
console.log('Time saved:',
(this.route.durationInTraffic - fasterRoute.durationInTraffic) / 60,
'minutes'
)
// Switch to faster route
await this.controls.selectRoute(fasterRoute.id)
this.route = fasterRoute
// Notify driver
this.notifyDriver('New faster route available')
}
}
stop() {
clearInterval(this.trafficCheckInterval)
}
}
// Usage
const tracker = new LiveRouteTracker(controls)
await tracker.startRoute(pickup, delivery)
// Stop tracking when delivery complete
tracker.stop()Type Definitions
interface Route {
id: string
distance: number // meters
duration: number // seconds
durationInTraffic: number // seconds
origin: Location
destination: Location
waypoints: Waypoint[]
waypointOrder?: number[]
geometry: Location[]
bounds: Bounds
legs: RouteLeg[]
steps: RouteStep[]
feasible: boolean
violations?: TimeWindowViolation[]
}
interface Waypoint {
id: string
coordinates: Location
label?: string
sublabel?: string
order: number
timeWindow?: TimeWindow
eta?: string
}
interface RouteLeg {
distance: number
duration: number
durationInTraffic: number
steps: RouteStep[]
departureTime: string
arrivalTime: string
}
interface RouteStep {
instruction: string
distance: number
duration: number
geometry: Location[]
maneuver: {
type: string
modifier?: string
location: Location
}
}
interface RouteOptions {
profile?: 'driving' | 'driving-traffic' | 'walking' | 'cycling'
mode?: 'fastest' | 'shortest' | 'balanced'
avoidTolls?: boolean
avoidHighways?: boolean
avoidFerries?: boolean
alternatives?: number
optimizeWaypoints?: boolean
respectTimeWindows?: boolean
departureTime?: string | 'now'
trafficModel?: 'best_guess' | 'pessimistic' | 'optimistic'
}
