Skip to content

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.

1

Basic Route

Simple point-to-point route

typescript
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
// }
2

Route with Options

Customize route calculation and display

typescript
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 routing
  • driving-traffic - Traffic-aware routing (recommended)
  • walking - Pedestrian routing
  • cycling - Bicycle routing

Route Modes:

  • fastest - Minimize time (default)
  • shortest - Minimize distance
  • balanced - Balance time and distance

Animation Types:

  • solid - Static line
  • flow - Flowing animation
  • dots - Dotted animation
  • dash - Dashed line
3

Multi-waypoint Route

Route with intermediate stops

typescript
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 sequence

Route Components

Build routes step-by-step using individual components.

setRouteOrigin()

Set the starting point of a route.

1

Set Origin

Define route starting point

typescript
await controls.setRouteOrigin(
  { lng: -74.0060, lat: 40.7128 },
  {
    label: 'Warehouse',
    sublabel: '123 Main St',
    markerColor: 'green',
    draggable: false
  }
)

Parameters:

typescript
{
  coordinates: Location
  options?: {
    label?: string
    sublabel?: string
    markerColor?: string
    draggable?: boolean
    icon?: string
  }
}

setRouteDestination()

Set the ending point of a route.

2

Set Destination

Define route ending point

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

3

Add Waypoint

Add stop along the route

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

typescript
await controls.updateRouteWaypoint(waypointId, {
  coordinates: { lng: -73.9900, lat: 40.7500 },
  label: 'Updated Pickup',
  markerColor: 'orange'
})

removeRouteWaypoint()

Remove a waypoint from the route.

typescript
await controls.removeRouteWaypoint(waypointId)

Route Utilities

fitRouteBounds()

Adjust viewport to show the entire route.

typescript
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).

typescript
await controls.fitRoutesBounds(['route-1', 'route-2', 'route-3'], {
  padding: 50,
  animate: true
})

getRouteDetails()

Get detailed information about the current route.

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

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

typescript
await controls.clearRoute()

Waypoint Captions

Add labels and information to waypoints.

setWaypointCaption()

Add a caption to a waypoint.

1

Add Caption

Label waypoints with details

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

typescript
await controls.updateWaypointCaption(waypointId, {
  status: 'completed',
  color: '#10b981',
  completedAt: new Date().toISOString()
})

removeWaypointCaption()

Remove caption from waypoint.

typescript
await controls.removeWaypointCaption(waypointId)

Custom Caption Styling

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

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

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

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

typescript
// 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.

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

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

typescript
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

typescript
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

typescript
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

typescript
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'
}

Next Steps