Skip to main content

Getting started with Navigation

|

The Navigation module provides comprehensive turn-by-turn navigation capabilities, enabling real-time guidance along calculated routes. It includes features such as voice instructions, automatic route recalculation, lane guidance, and speed limit warnings.

Starting navigation

To start navigation, you first need a calculated route:

import { NavigationService, RoutingService, Coordinates } from '@magiclane/maps-sdk';

async function startNavigation() {
//If we have already computed routes shown on the map, we can take them from there. See RoutingService.calculateRoute how a route can be calculated
const routesMap = map.preferences.routes;
if (!routesMap.mainRoute) {
showMessage('No main route available');
return;
}
// Start Navigation on the main route
navigationHandler = NavigationService.startNavigation(routesMap.mainRoute, undefined, {
onNavigationInstruction: (
instruction: NavigationInstruction,
events: NavigationEventType[]
) => {
isNavigationActive = true;
currentInstruction = instruction;
updateUI();
},
onError: (error: GemError) => {
isNavigationActive = false;
cancelRoute();
if (error !== GemError.cancel) stopNavigation();
updateUI();
},
});
map.startFollowingPosition();
updateUI();
}

Listen to navigation events to update your UI:

import { NavigationService, NavigationEvent } from '@magiclane/maps-sdk';

function setupNavigationListeners() {
const navigationService = NavigationService.getInstance();

// Listen for navigation instructions
navigationService.on('instruction', (instruction) => {
console.log(`Next instruction: ${instruction.text}`);
console.log(`Distance to instruction: ${instruction.distance}m`);
console.log(`Time to instruction: ${instruction.time}s`);

// Update UI with instruction
updateNavigationUI(instruction);
});

// Listen for position updates along the route
navigationService.on('positionUpdate', (position) => {
console.log(`Current position: ${position.coordinates.latitude}, ${position.coordinates.longitude}`);
console.log(`Distance remaining: ${position.remainingDistance / 1000}km`);
console.log(`Time remaining: ${position.remainingTime / 60}min`);
});

// Listen for route deviation
navigationService.on('routeDeviation', () => {
console.log('User deviated from route');
// Automatic rerouting will trigger if enabled
});

// Listen for arrival
navigationService.on('arrival', (destination) => {
console.log('Arrived at destination!');
showArrivalNotification();
});

// Listen for waypoint reached
navigationService.on('waypointReached', (waypoint) => {
console.log(`Reached waypoint: ${waypoint.name}`);
});
}

Simulation mode

For testing navigation without actual GPS movement:

function startSimulation(route: Route) {
const navigationService = NavigationService.getInstance();

navigationService.startNavigation(route, {
simulationMode: true,
simulationSpeed: 50, // km/h
voiceGuidance: false
});

// Control simulation
navigationService.pauseSimulation();
navigationService.resumeSimulation();
navigationService.setSimulationSpeed(100); // Change speed to 100 km/h
}

Voice guidance

Configure voice guidance for navigation:

import { VoiceGuidance } from '@magiclane/maps-sdk';

function configureVoiceGuidance() {
const voiceGuidance = VoiceGuidance.getInstance();

// Enable voice guidance
voiceGuidance.setEnabled(true);

// Set language
voiceGuidance.setLanguage('en-US');

// Set volume (0.0 to 1.0)
voiceGuidance.setVolume(0.8);

// Configure instruction types
voiceGuidance.setInstructionTypes({
turnInstructions: true,
distanceAnnouncements: true,
speedWarnings: true,
arrivalAnnouncements: true
});
}

Auto rerouting

The SDK automatically recalculates the route when you deviate from the planned path:

function configureAutoReroute() {
const navigationService = NavigationService.getInstance();

// Configure auto-reroute settings
navigationService.setAutoRerouteEnabled(true);
navigationService.setRerouteThreshold(50); // Reroute after 50m deviation

// Listen for reroute events
navigationService.on('rerouteStarted', () => {
console.log('Calculating new route...');
showRerouteIndicator();
});

navigationService.on('rerouteCompleted', (newRoute) => {
console.log('New route calculated');
hideRerouteIndicator();
});

navigationService.on('rerouteFailed', (error) => {
console.error('Reroute failed:', error);
showRerouteError();
});
}

Lane guidance

Display lane information for upcoming maneuvers:

navigationService.on('laneGuidance', (laneInfo) => {
console.log(`Total lanes: ${laneInfo.totalLanes}`);
console.log(`Recommended lanes: ${laneInfo.recommendedLanes.join(', ')}`);

// Display lane guidance UI
displayLaneGuidance(laneInfo);
});

Speed limit warnings

Get notifications about speed limits:

navigationService.on('speedLimitUpdate', (speedLimit) => {
console.log(`Current speed limit: ${speedLimit} km/h`);
updateSpeedLimitDisplay(speedLimit);
});

navigationService.on('speedingWarning', (currentSpeed, speedLimit) => {
console.log(`Warning: Speeding! ${currentSpeed} km/h in ${speedLimit} km/h zone`);
showSpeedingWarning();
});

Example of integrating navigation with a map view:

import { GemMap, NavigationService } from '@magiclane/maps-sdk';

function setupNavigationUI(gemMap: GemMap, route: Route) {
const navigationService = NavigationService.getInstance();

// Start navigation
navigationService.startNavigation(route, {
voiceGuidance: true,
autoReroute: true
});

// Follow user position
gemMap.setFollowPositionMode(true);

// Update camera for navigation
gemMap.setCameraMode('navigation'); // Tilted view for navigation

// Update UI on instructions
navigationService.on('instruction', (instruction) => {
// Update instruction panel
document.getElementById('instruction-text').textContent = instruction.text;
document.getElementById('instruction-distance').textContent =
`${instruction.distance}m`;

// Update maneuver icon
updateManeuverIcon(instruction.type);
});

// Update distance and time
navigationService.on('positionUpdate', (position) => {
const distanceKm = (position.remainingDistance / 1000).toFixed(1);
const timeMin = Math.round(position.remainingTime / 60);

document.getElementById('distance-remaining').textContent = `${distanceKm} km`;
document.getElementById('time-remaining').textContent = `${timeMin} min`;
});
}

Stopping navigation

When navigation is complete or cancelled:

function stopNavigation() {
const navigationService = NavigationService.getInstance();

navigationService.stopNavigation();

// Reset map view
gemMap.setFollowPositionMode(false);
gemMap.setCameraMode('default');

console.log('Navigation stopped');
}

Complete navigation example

import { 
GemKit,
GemMap,
RoutingService,
NavigationService,
Coordinates
} from '@magiclane/maps-sdk';

class NavigationExample {
private gemMap: GemMap;
private navigationService: NavigationService;

constructor(gemMap: GemMap) {
this.gemMap = gemMap;
this.navigationService = NavigationService.getInstance();
this.setupListeners();
}

async startNavigationTo(destination: Coordinates) {
try {
// Get current position
const currentPosition = await this.getCurrentPosition();

// Calculate route
const routes = await calculateRouteAsync(
[currentPosition, destination],
new RoutePreferences({
transportMode: TransportMode.Car,
routeType: RouteType.Fastest,
considerTraffic: true
})
);

if (routes.length === 0) {
throw new Error('No route found');
}

// Start navigation
this.navigationService.startNavigation(routes[0], {
voiceGuidance: true,
autoReroute: true,
simulationMode: false
});

// Configure map for navigation
this.gemMap.setFollowPositionMode(true);
this.gemMap.setCameraMode('navigation');

} catch (error) {
console.error('Navigation error:', error);
}
}

private setupListeners() {
this.navigationService.on('instruction', (instruction) => {
this.updateInstructionUI(instruction);
});

this.navigationService.on('arrival', () => {
this.handleArrival();
});

this.navigationService.on('rerouteCompleted', (newRoute) => {
console.log('Route updated due to deviation');
});
}

private updateInstructionUI(instruction: any) {
// Update your UI components
}

private handleArrival() {
this.navigationService.stopNavigation();
this.gemMap.setFollowPositionMode(false);
console.log('Navigation complete!');
}

private async getCurrentPosition(): Promise<Coordinates> {
// Get current position from PositionService
const positionService = PositionService.getInstance();
const position = await positionService.getCurrentPosition();
return position.coordinates;
}
}

Next Steps

Now that you understand navigation basics, you can explore:

  • Custom voice guidance configuration
  • Advanced navigation UI customization
  • Better route detection and alternatives
  • Integration with traffic and incident data