Skip to main content

ETA for a delivery or pickup

In the SWAT system, estimated times are critical for managing expectations for both drivers and end-customers. There are three primary types of timestamps available for nodes

(pickups/drop-offs):

  • Planned Schedule (scheduled_ts): Calculated during the initial optimization. This is the baseline plan.
  • Realistic ETA (estimated_scheduled_ts): The most accurate real-time prediction. It considers current vehicle location, service times of previous stops, and route constraints.
  • Optimistic ETA (estimated_earliest_arrival_ts): Represents the physically earliest possible arrival if the vehicle drove non-stop, ignoring some service buffers.

ETA Calculation Logic

The estimated_scheduled_ts is the recommended field for consuming applications. It is dynamically updated and calculated as follows:

Estimated time logic
# It cannot be earlier than the 'earliest physical arrival'
# AND it cannot be earlier than the node's scheduled open time (earliness constraint)
estimated_scheduled_ts = max(estimated_earliest_arrival_ts, node.open_time_ts)
info

If a vehicle arrives early (before open_time_ts), it must wait. This waiting time is implicitly included in the estimated_scheduled_ts.

Update Frequency

  • Trigger: Updates happen approximately every 5 minutes per simulation.
  • Scope: Only vehicles with assigned nodes are updated.
  • Conditions: The vehicle must be online (sending GPS) or have a valid start time.

Event Lifecycle Example

To understand how ETA evolves, let's look at a lifecycle of a delivery node "B".

Scenario:

  • Node A: Start/Pickup (Service time: 5m)
  • Node B: Drop-off (Time window: 10:00 AM - 11:00 AM)
  • Travel A -> B: 10 minutes.

1. Optimization Phase

The route is planned.

  • scheduled_ts: 10:00 AM (Planned arrival).
  • estimated_scheduled_ts: 10:00 AM.

2. Execution Phase (On Time)

Vehicle departs A at 9:45 AM.

  • estimated_earliest_arrival_ts: 9:45 AM + 10m drive = 9:55 AM.
  • estimated_scheduled_ts: max(9:55 AM, 10:00 AM open window) = 10:00 AM.
  • vehicle waits 5 minutes at location

3. Execution Phase (Delayed)

Traffic occurs. Vehicle departs A at 9:55 AM.

  • estimated_earliest_arrival_ts: 9:55 AM + 15m drive (traffic) = 10:10 AM.
  • estimated_scheduled_ts: max(10:10 AM, 10:00 AM) = 10:10 AM.
  • The system now predicts a 10-minute delay compared to the original schedule.

Node Data Fields

FieldDescription
scheduled_tsBaseline. The planned arrival time from the optimization engine.
estimated_scheduled_tsBest ETA. The most realistic expected arrival time. Recalculated ~5 mins.
estimated_earliest_arrival_tsOptimistic ETA. Earliest physical arrival ignoring some constraints.
arrived_to_location_tsActual. Timestamp when the driver marked "Arrived".
completed_service_atActual. Timestamp when the node was marked "Completed".
failed_to_deliver_at_tsActual. Timestamp if the delivery failed (e.g., customer not home).
slackThe amount of time the vehicle expects to wait at this location before service can start.
service_timeDuration required to service this node (e.g., loading/unloading).

Retrieving ETA

There are three methods to access ETA data, depending on your latency requirements.

For a broader integration context on orders and delivery tracking, refer to the Integration of Orders and POD guide.

1. Polling Node Data

You can query a specific node to get its latest status and timestamps.

GET /api/v2/node/{node_id}

View JSON Response
{
"id": 50801567,
"node_type": "dropoff",
"status": "assigned",
"scheduled_ts": "2024-10-08T06:36:39+00:00",
"estimated_scheduled_ts": "2024-10-08T06:36:39+00:00",
"estimated_earliest_arrival_ts": "2024-10-08T06:32:00+00:00",
"arrived_to_location_ts": null,
"completed_service_at": null,
"slack": 238.8,
"service_time": 180,
"booking": "/api/v2/booking/23286180"
}

For real-time updates, subscribe to vehicle_arrival events. This pushes updates for all vehicles in the simulation.

  • Agent Type: vehicle_group
  • Message Type: vehicle_arrival
Vehicle Arrival Event
{
"simulation_id": 123,
"agent_type": "vehicle_group",
"message_type": "vehicle_arrival",
"data": {
"vehicle_id": 101,
"booking_id": 5002,
"booking_uid": "uuid-1234",
"node_id": 9001,
"estimated_earliest_arrival_ts": "2025-04-01T12:00:00+00:00",
"estimated_scheduled_ts": "2025-04-01T12:05:00+00:00",
"scheduled_ts": "2025-04-01T12:00:00+00:00"
},
"current_sim_ts": "2025-04-01T11:55:00+00:00"
}

See Webhooks Documentation for configuration details.

3. Client-Side Calculation (Routing API)

If you need ETA on-demand and cannot wait for the 5-minute update cycle (e.g., for a smooth driver app UI), you can calculate it using the Routing API + Vehicle Position.

  1. Get vehicle's next assigned nodes: GET /api/v2/vehicle/<vehicle_id>/assigned_nodes
  2. Get route from current GPS to the next node: GET /vehicle_route_proxy/<vehicle_id>/<current_gps_lat,lon>;<node_lat,lon>
View Route Response
{
"code": "Ok",
"routes": [
{
"duration": 149.6,
"distance": 832.1,
"legs": [
{ "duration": 133.7, "distance": 771.4 }
]
}
],
"waypoints": [
{ "location": [100.516, 13.690] },
{ "location": [100.518, 13.692] }
]
}

Calculation: ETA = CurrentTime + route.duration