Most planning stacks split one decision over many tools: a route optimiser, a driving-time check, an ADR spreadsheet, a load planner, a dock booking screen, an empties desk, a carrier portal and an intermodal planner. Each one is right on its own, and the combined plan still fails at the dock, at the terminal or at the trailer door.
Transportial decides all of it together, in one search, so the plan it hands over can actually run. The same engine plans inside the product (the optimizer and map planning) and on the API (POST /vrp/solve).
This page lists what that one search decides, which rule guards each decision, and where you set it on the platform and in the API. The request fields are in the Multi-Modal VRP example.
A refrigerated consignment leaves Venlo at 06:00. The tractor is in Venlo, the only free reefer trailer stands in Tilburg, and the driver who is free has already driven 41 hours this week. One option is a carrier who serves Venlo to Lyon, but only if the order is in before 14:00.
What the planner decides. Each tour gets a vehicle, a driver and, when it needs one, a trailer or other equipment. Instead of your own fleet, a tour can also run on a carrier's capacity contract.
- Drivers. Each driver has one EU 561/2006 driving-time clock across all their tours. The clock starts from what they have already driven, so breaks, daily and weekly rests and weekly limits are planned over the whole plan, not per tour. Availability, ADR certificate, licence, tacho card, certificates, bans and languages count as well.
- Trailers. A trailer is picked from the pool by type, attributes, temperature and room, and the tour fetches it from where it stands. The drive to it counts in the tour's time and cost.
- Carriers. A capacity contract is priced with your own pricing modules. It is limited by its lanes, service areas, operating hours, lead time and order cut-off, and by the goods it accepts.
| Rule codes | Default (API / platform) |
|---|---|
availability, operational, driving_time, chauffeur_ban, chauffeur_attribute | block / block |
adr_chauffeur, certificate, licence | block / warn |
equipment_type, temperature, vehicle_type, vehicle_attribute | block / block |
contract_lane, contract_validity, contract_capability, carrier_is_customer | block / block |
Where you set it. On the platform, these come from your vehicles, chauffeurs, transport equipment and capacity contracts, and their rule policy from the planning settings (planningSettings.optimizerRules). On the API, send vehicles, chauffeurs, transportEquipments and capacityContracts. See Add drivers, Add trailers and equipment and Add capacity contracts.
Forty containers must go from Rotterdam to Milan by Thursday. A train leaves Rotterdam on Tuesday at 18:00 with 28 free slots and a cut-off three hours before departure. Trucks can do the whole distance, or bring the containers to the terminal and collect them in Milan.
What the planner decides. Road, rail, inland waterway, sea and air are planned in one plan. A consignment can also ride a scheduled service door to door: by truck to the terminal, by train, barge, ship or aircraft, and by truck to the door. Cut-offs and capacity per departure count. The road legs at both ends follow the same rules as every other tour.
| Rule | Default |
|---|---|
| Transport mode of the vehicle and the location | always enforced |
| Cut-off and capacity per departure | always enforced |
Where you set it. On the platform, the optimizer plans over your stored schedule routes (useScheduleRoutes, on by default). On the API, send scheduleRoutes, or set options.chains.useStoredScheduleRoutes. See Add scheduled services.
A reefer leaves the depot with frozen fish in the front and chilled dairy at the rear. A drum of pesticide (ADR class 6.1) is on the same order list for the same customer.
What the planner decides.
- Load plans. Every proposed trip gets a 3D load plan that the planner can open before saving, in the optimizer and in map planning, whatever engine planned the trip. It shows the stop-by-stop loading order. When the trip is saved, the plan stays with it.
- Compartments. Multi-temperature reefers, tank compartments and food-grade holds are modelled. A consignment only goes into a compartment that fits its temperature, its dangerous goods and its foodstuff status. Each compartment's capacity is checked against what is on board at the same moment. In the 3D load plan, a bulkhead is a wall.
- ADR. ADR 1.1.3.6 points add up per tour, over everything on board at the same moment. Incompatible classes are kept apart. Foodstuffs never share a compartment with toxic or infectious classes (6.1 and 6.2 by default; ADR 7.5.4).
| Rule codes | Default (API / platform) |
|---|---|
compartment | block / block |
adr_vehicle, adr_equipment, adr_mixed_loading | block / warn |
| 3D packing | set by load planning: off, verify or enforce |
Where you set it. On the platform, compartments are set on vehicles and transport equipment. Foodstuff and the required temperature are set on the goods. The Load planning setting (Off, Verify, Enforce) needs the stacking module. On the API, send vehicles[].compartments, transportEquipments[].compartments, consignments[].foodstuff, rules.adr and options.loadPlanning. See Add compartments, Add dangerous goods and Calculating a 3D Load Plan.
A distribution centre has two loading docks. Between 07:00 and 08:30 one of them is booked by a supplier's timeslot, and three of your trucks are planned to arrive around 07:30.
What the planner decides. Docks, ramps, berths and rail sidings have a capacity. The planner never plans more vehicles at once than a site can handle. Other trips already at the site and booked dock timeslots count as well. A vehicle that finds every dock taken waits for a free one, and that wait is real waiting time: it counts in the tour time and in the driver's day. When a tour with slack can wait at less cost, it gives way to a tour that cannot. The method is after Bombelli & Fazi (2022), see Research it builds on.
| Rule code | Default (API / platform) |
|---|---|
dock_capacity | block / block |
Where you set it. On the platform, the capacity of a location is the sum of maxConcurrentOperations over its operational loading docks. Stops of other trips and requested or confirmed timeslot bookings count. The optimizer response shows each wait in dockWaitByStop. On the API, send locations[].docks and read dockWaitSeconds and dockStart per stop. See Add docks and berths.
An import container is delivered to a warehouse in Tilburg and is empty once unloaded. Ten kilometres away, an exporter in Waalwijk needs an empty container of the same type that afternoon. The nearest container depot is in Moerdijk.
What the planner decides. Empty containers, swap bodies and pool trailers are shared by all tours. A consignment can need a unit at its pickup, as an export needs an empty container. It can also free one after its delivery, as an import's container is empty once unloaded.
- Sources. The planner reuses a freed unit on the same tour (a street-turn), or takes one from stock or a depot. A fetch from stock or a depot is priced as a detour on the leg into the pickup.
- Stock. Stock is tracked over time across all tours, and is never planned below zero.
- Method. The method is after Fazi, Choudhary & Dong (2023), see Research it builds on.
| Rule code | Default (API / platform) |
|---|---|
equipment_stock | block / block |
Where you set it. On the platform, a location's equipment stock is set in its site details. A consignment's need or release is its equipmentFlow. The optimizer response shows each source in equipmentByTrip and the stock over time in equipmentStock. On the API, send the top-level equipmentStock and consignments[].equipmentFlow. See Add empty containers and pools.
One planner wants every consignment planned first, then the fewest tours, and only then the lowest cost. Another weighs CO2e and cost together, because a customer pays for the lower emissions.
What the planner decides. You set a custom objective: a weight on each of distance, driving time, tour time, waiting time, money, CO2e, tours, resources, lateness and unplanned consignments. Priority levels can rank them, for example first plan everything, then the fewest tours, then cost. A higher level always outweighs everything below it. The named objectives (distance, time, CO2, cost, fewest assets) are presets of the same weights.
The result explains itself: the objective per component, per tour and in total.
Where you set it. On the platform, choose Custom as the optimisation objective in the optimizer settings and set the default weights. A run can override them in the optimizer. The response holds objective and objectiveByTrip. On the API, send options.objective: "custom" with options.objectiveWeights and options.objectivePriorities, and read routes[].objective and objective. See Choose what "best" means.
A planner sees that one consignment stayed unplanned and wants to know why. A tenant that has not entered all driver licences yet still wants a plan.
What the planner decides.
- Every rule can be
block,warnoroff. - A warned rule costs something in the plan, and each tour lists what it breaks in
softViolations. - Every consignment left out gets a
reason, anddetailscounts how many resources each rule refused.
Where you set it. On the platform, set the policy per rule in the planning settings (planningSettings.optimizerRules). On the API, send rules.policy and rules.softWeights. See How strict each rule is.
Every rule below can be set to block (a violation makes the plan infeasible), warn (it costs a penalty and is reported on the tour) or off. The platform defaults to warn for data that most tenants have not filled in yet, so an upgrade never empties a plan.
| Rule code | Default API | Default platform |
|---|---|---|
operational | block | block |
availability | block | block |
adr_chauffeur | block | warn |
adr_vehicle | block | warn |
adr_equipment | block | warn |
adr_mixed_loading | block | warn |
certificate | block | warn |
licence | block | warn |
chauffeur_ban | block | block |
chauffeur_attribute | block | block |
vehicle_attribute | block | block |
vehicle_type | block | block |
fuel_type | block | block |
emission_standard | block | block |
equipment_type | block | block |
location_access | block | warn |
contract_lane | block | block |
contract_validity | block | block |
contract_capability | block | block |
carrier_is_customer | block | block |
driving_time | block | block |
tour_limit | block | block |
temperature | block | block |
compartment | block | block |
equipment_stock | block | block |
dock_capacity | block | block |
capacity, trip_status and existing_trip always block and cannot be set. The API rejects them as policy keys, and the platform settings ignore them.
| Where | What it does |
|---|---|
Optimizer (POST /trip/optimizer) | Plans your consignments with your vehicles, chauffeurs, equipment and contracts from the platform. It proposes trips and saves nothing, unless planningSettings.autoApplyOptimizerPlans is on. See Trips & Planning. |
| Map planning | Plans from the map with the same engine. Each proposed trip has a Load plan button. |
POST /vrp/solve | Takes a complete problem in the request and stores nothing. Nothing in it has to exist in Transportial. Permission calculate:vrp. See Multi-Modal VRP. |
POST /vrp/solve/async | The same request as a job, for searches of up to 120 seconds. Poll GET /worker-job/{id}. |
Everything on this page is decided by the built-in Transportial engine. When your platform uses another optimizer engine, that engine plans the routes, and its proposals still get load plans.
Two parts of the planner build on published research. The results below are the papers' own, from their experiments, not measurements of Transportial.
- Docks. A. Bombelli & S. Fazi (2022), "The ground handler dock capacitated pickup and delivery problem with time windows: A collaborative framework for air cargo operations", Transportation Research Part E 159, 102603. In the paper's experiments, uncoordinated plans queued for docks up to about 3 hours, and some became infeasible. Coordination cut travel time by 2–19%. Our adaptation keeps every plan the search holds dock-feasible. Instead of the paper's penalised overbooking, a tour waits, or the tour that can shift gives way.
- Empties. S. Fazi, S.K. Choudhary & J.X. Dong (2023), "The multi-trip container drayage problem with synchronization for efficient empty containers re-usage", European Journal of Operational Research 310(1), 343–359. In the paper's real cases near Tilburg and 's-Hertogenbosch, its plans were 25–43% cheaper than the planners' own, with fewer trips. Our adaptation:
- runs inside our large neighbourhood search instead of branch-and-price;
- checks stock only when a unit is taken (the paper's "critical times");
- prices depot fetches as detours ("bypass").
- A consignment is not split over vehicles. It travels on one vehicle, or on one chain of legs.
- Compartment lengths are fixed. There is no movable bulkhead yet.
/vrp/solvechecks that every consignment has a matching compartment, but does not report which compartment it got. A load plan reports it per unit inplacements[].compartmentId.- Separate loading and unloading docks are not modelled. All operational docks of a site count together.
- Equipment types match exactly. There is no equivalence between ISO size-type groups.
- Yard capacity is not modelled. A return is never refused because a yard is full.
- Stock and depot visits do not become explicit stops on a saved trip. They count in the trip's times and distance only.
equipmentStockandscheduleRoutescannot be combined in one request.- A trailer from the pool stays with one vehicle for the whole plan. Handing it over to another vehicle is not modelled, and neither is a chassis pool shared between vehicles.
- Without your own distance matrix, distances are straight-line estimates, and
warningssays so.