Свойства транспортных средств

Доставка заказов в Яндекс Маршрутизации может выполняться как обычными автомобилями, так и курьерами, передвигающимися пешком или на общественном транспорте. Автомобиль и курьер имеют общий набор свойств.

Для определения автомобиля или курьера используется поле запроса vehicles.

Идентификатор автомобиля или курьера

Обязательным атрибутом автомобиля или курьера является уникальный числовой или строковый идентификатор, который задается в поле id. Идентификатор должен быть уникальным в пределах одного запроса к сервису. При экспорте в Мониторинг этот идентификатор будет использоваться как логин курьера.

Дополнительно вы можете указать числовой или строковый идентификатор автомобиля или курьера из вашей учетной системы в поле ref, а также номер мобильного телефона курьера в поле phone для связи с ним из Мониторинга.

Вместимость автомобиля или курьера

Маршрутизация поддерживает определение вместимости автомобиля для определения максимального веса или количества груза, которое автомобиль/курьер может перевезти за один маршрут.

Чтобы определить вместимость автомобиля или курьера, используйте поле capacity (достаточно указать один из вариантов):

  • capacity.units — количество мест (паллет, коробок, кег).

  • capacity.weight_kg — вес в килограммах или объемный вес.

  • capacity.volume — объем, который измеряется в кубометрах и задается как произведение измерений:

    • capacity.volume.width_m — ширина в метрах.

    • capacity.volume.depth_m — глубина в метрах.

    • capacity.volume.height_m — высота в метрах.

    Если измерения неизвестны, используйте capacity.volume_cbm.

  • capacity.volume_cbm — объем, заданный в кубометрах.

Если у автомобиля заданы и метрические размеры, и объем, то capacity.volume определяет габариты, а capacity.volume_cbm — вместимость.

Более подробно с определением веса вы можете ознакомиться в главе Вес и объем.

Примечание

Обратите внимание, если вес заказов задан в килограммах или как объемный вес, вместимость автомобиля должна быть задана в таких же единицах. Аналогично, если вес заказов задан в виде количества мест, определение вместимости автомобиля должно содержать максимальное количество мест в каждом автомобиле.

Дополнительно, возможно определение максимальной загрузки автомобиля в процентах от заданной грузоподъемности. Для этого используется поле запроса limits:

  • limits.volume_perc — процентное значение от заданного в capacity.volume.width_m * capacity.volume.depth_mcapacity.volume.height_m.

  • limits.weight_perc — процентное значение от заданного в capacity.weight_kg.

  • limits.unit_perc — процентное значение от заданного в capacity.units.

Чтобы указать возможность перегруза относительно заданного значения, укажите значение больше 100. Чтобы оставить запас грузоподъемности, например под возможные неточности в оценке габаритов заказа, укажите значение меньше 100. Например, значение 110 позволяет 10% перегруза, а значение 90 — максимальную загрузку в 90% от указанной грузоподъемности.

Вместимость автомобиля (с учетом limits) — жесткое ограничение, которое не будет нарушено. При этом при расчете загруженности автомобиля учитываются заказы на прием и доставку. Подробнее в разделе Прием и доставка.

Примечание

Через вместимость автомобиля можно косвенно управлять количеством заказов, которые должны в него попасть. Например, если указать объем каждого заказа в 1 юнит (независимо от реальных размеров заказа), а вместимость автомобиля – 10 юнитов, то при планировании в каждый автомобиль попадет не более 10 заказов.

Пример

Дано два автомобиля грузоподъемностью 1,5 тонны (Автомобиль 1) и 3 тонны (Автомобиль 2), а также три заказа для доставки весом 1 тонна, 1,2 тонны и 1,4 тонны.

При оптимизации маршрутов, заказ весом 1,2 тонны будет размещен в Автомобиль 1, и два заказа весом 1 и 1,4 тонны в Автомобиль 2.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пользовательские единицы вместимости

Пользовательская единица ограничивает вместимость автомобиля по пользовательской единице измерения, указанной для заказов.

Можно задать несколько пользовательских единиц вместимости автомобиля, каждая из них должна иметь свой порядковый номер N (нумерация начинается с 0). Каждая единица описывается двумя параметрами:

  • capacity.custom.N.name — имя пользовательской единицы;

  • capacity.custom.N.size — вместимость автомобиля по пользовательской единице.

По умолчанию вместимость по параметру capacity.custom.N.size не ограничена.

Внимание

Название пользовательской единицы вместимости автомобиля должно совпадать с указанным для заказа.

Если пользовательские единицы измерения вместимости указаны для заказов или явно заданы у одних автомобилей, но не заданы у других, то для автомобилей, где они не заданы, вместимость по пользовательским единицам измерения считается неограниченной.

Пример заполнения листов файла Excel для пользовательского параметра price (стоимость заказа):

Стоимость заказа

shipment_size.custom.0.name

shipment_size.custom.0.size

price

100

Суммарная стоимость заказов

capacity.custom.0.name

capacity.custom.0.size

price

1000

Пример 1.1

4 автомобиля выполняют 16 заказов. Для автомобилей указаны вес, объем и грузоподъемность (количество грузовых мест). С помощью пользовательских единиц для заказов указана стоимость location.shipment_size.custom.0, а для автомобилей — ограничение по суммарной стоимости перевозимых заказов vehicle.capacity.custom.0.

Есть 2 автомобиля, которые везут по 1 заказу, хотя утилизация по весу, объему и количеству мест у них небольшая – это обусловлено тем, что стоимость этих заказов находится близко к установленному для автомобиля ограничению.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 1.2

То же, что в примере 1.1, но дополнительно указано максимальное количество заказов, которое может перевезти автомобиль. Ограничение задано с помощью параметров location.shipment_size.custom.1 и vehicle.capacity.custom.1. Каждый автомобиль теперь может везти не более 5 заказов.

Количество заказов в трех автомобилях изменилось. Теперь 1 заказ везет только 1 автомобиль, в который нельзя больше добавить заказы из-за ограничения по суммарной стоимости. По остальным достигнута максимальная утилизация по суммарной стоимости в каждом автомобиле, но удалось выдержать ограничение по количеству заказов.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Два автомобиля выполняют 20 заказов. Заказы имеют разную длину, эта характеристика описывается двумя пользовательскими единицами:

  • единица Length5 (location.shipment_size.custom.0) равна 1 для заказов длиной 5 метров (это заказы с 10 по 15) и 0 для остальных заказов;
  • единица Length6 (location.shipment_size.custom.1) равна 1 для заказов длиной 6 метров (это заказы с 16 по 20) и 0 для остальных заказов. Заказы с 1 по 9 имеют длину менее 5 метров, для них обе пользовательские единицы Length5 и Length6 равны 0.

Автомобили имеют одинаковую грузоподъемность, но разную длину кузова:

  • у Vehicle6 длина кузова 6 метров, он может перевозить любые заказы. Для него vehicle.capacity.custom.0 и vehicle.capacity.custom.1 равны 10 (с учетом веса заказов и грузоподъемности автомобиля);
  • у Vehicle5 длина кузова 5 метров, он не может перевозить заказы длиной 6 метров. Для него vehicle.capacity.custom.0 = 10, а vehicle.capacity.custom.1 = 0.

В спланированном решении автомобиль Vehicle5 перевозит заказы длиной 5 метров и менее 5 метров, а Vehicle6 — заказы длиной 6 метров, 5 метров и менее 5 метров.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Характеристики транспортного средства

Характеристики транспортного средства можно задать в поле vehicle.specs. В нем могут быть указаны следующие параметры:

  • width — ширина транспортного средства в метрах;

  • height — высота транспортного средства в метрах;

  • length — длина транспортного средства в метрах;

  • max_weight — максимальный вес транспортного средства в тоннах;

  • max_weight_kg — максимальный вес транспортного средства в килограммах (округляется до тонн в большую сторону при решении задачи планирования).

Примечание

Если в задаче планирования одновременно заданы параметры vehicle.specs.max_weight и vehicle.specs.max_weight_kg, то в решении будет использован vehicle.specs.max_weight.

Для всех перечисленных характеристик минимальное значение равно 0.

Внимание

Эти параметры можно указывать только для грузовых автомобилей (routing_mode = truck).

Для расчета вместимости грузового автомобиля используется 21 класс, см. спецификацию. Алгоритм учитывает габариты и грузоподъемность каждого автомобиля и подбирает по спецификации ближайший класс, у которого все характеристики равны или превышают характеристики автомобиля. Если хотя бы одна из характеристик автомобиля превышает максимально определенные значения, ему присваивается класс truck_N21. В решении могут использоваться не более 5 классов. Если при планировании их больше, то меньшие классы равномерно убираются из решения, а автомобили получают ближайший больший класс из оставшихся.

Посмотреть, какие классы использовались в решении, можно в массиве matrix_statistics ответа API.

Спецификация классов

Класс

Высота ТС, м

Ширина ТС, м

Длина ТС, м

Максимальный вес ТС, т

truck_N1

0

0

0

0

truck_N2

1.5

0

0

0

truck_N3

2

0

0

0

truck_N4

2

2

3.2

3.5

truck_N5

2.2

2.1

4

0

truck_N6

2.2

2.1

4

3.5

truck_N7

2.4

2.6

4

5

truck_N8

2.4

2.6

8

8

truck_N9

2.5

0

0

0

truck_N10

2.5

2.2

6.5

3.5

truck_N11

2.7

2.6

8

10

truck_N12

2.7

2.6

8

14.5

truck_N13

3

2.6

8

10

truck_N14

3

2.6

8

14.5

truck_N15

3

2.6

10

20

truck_N16

3.2

2.6

9

12

truck_N17

3.9

2.6

10

22

truck_N18

3.9

2.6

10

25

truck_N19

4

2.6

15

30

truck_N20

4

2.6

20

35

truck_N21

4

2.6

20

40

Учет характеристик транспортных средств включается опцией options.enable_vehicle_classes. По умолчанию enable_vehicle_classes = true — в этом случае алгоритм классифицирует транспортные средства на основе их характеристик. Учет характеристик можно отключить, установив enable_vehicle_classes = false.

Пример 1.1

Два автомобиля, грузовик и легковой автомобиль, развозят 10 заказов. 2 адреса расположены рядом с Черкизовской переправой, у которой ограничение по высоте для проезжающего транспорта — 2,5 метра. Самый короткий путь между этими адресами проходит через нее.

Алгоритм построит 2 маршрута, так как грузовик слишком высокий для переправы. Заказы, расположенные рядом с ней, повезет легковой автомобиль без ограничивающих характеристик. Поскольку у грузовика задана высота specs.height = 3, согласно спецификации ему присвоен класс truck_N13.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 1.2

В планировании участвуют те же заказы и автомобили, что в примере 1.1, но характеристики грузовика vehicle.specs не заданы, поэтому класс грузовику не присвоен.

Алгоритм не находит ограничений на проезд и планирует путь грузовика через переправу.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2.1

Курьер должен развезти 2 заказа, которые находятся за МКАДом. Точки заказов диаметрально противоположны. У автомобиля не указан максимальный вес  specs.max_weight, поэтому алгоритм без ограничений рассчитывает движение по МКАД. Из-за отсутствия характеристик vehicle.specs класс грузовику не присвоен.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2.2

То же, что и в примере 2.1, но в этот раз у автомобиля указан specs.max_weight = 12. Согласно спецификации, грузовику присвоен класс truck_N12. Алгоритм спланировал пробег в 3,5 раза больше, потому что автомобиль не может двигаться по МКАД.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2.3

То же, что и в примере 2.2, но вместо max_weight использован параметр max_weight_kg, и значение указано в кг. Грузовику присвоен тот же класс truck_N12. Алгоритм также спланировал маршрут в объезд, потому что автомобиль не может двигаться по МКАД.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Сервисное время погрузки на складе

Время загрузки или разгрузки на складе может зависеть как от заказов, так и от свойств автомобиля (например, габариты или оборудование).

Чтобы указать количество дополнительного времени, необходимого для загрузки на складе, используйте параметр vehicle.depot_extra_service_duration_s. Время указывается в секундах.

Примечание

Время, которое назначается в параметре vehicle.depot_extra_service_duration_s, суммируется с временем обслуживания склада.

Пример

2 автомобиля с одинаковой грузоподъемностью выполняют доставку 13 крупногабаритных заказов. Сервисное время на складе depot.service_duration_s составляет 5 минут (300 секунд). Для погрузки заказов в автомобиль на складе задано дополнительное время vehicle.depot_extra_service_duration_s — 30 минут (1800 секунд). В результате планирования каждый автомобиль проведет на складе 35 минут перед началом движения по маршруту.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Старт автомобиля не со склада

По умолчанию автомобили и курьеры стартуют со склада, но иногда нужно начинать маршрут из другой точки (например, из дома или с места парковки). Как правило, эта задача подходит для планирования маршрутов торговых представителей, сервисных инженеров и прочих специалистов, которые не развозят товары, а оказывают услуги.

Это требование можно реализовать с помощью свойства vehicle.start_at. В этом случае курьер или автомобиль начнет маршрут из указанной точки с типом garage, а не со склада.

Посещение склада перед началом рабочего дня

При начале рабочего дня не со склада курьерам может понадобиться посетить склад, чтобы получить там заказы. Для этого используйте свойство vehicle.visit_depot_at_start. Если указано true, то перед началом выполнения заказов курьер или автомобиль обязаны посетить склад (это поведение по умолчанию). В противном случае они могут сразу начать выполнять заказы. Подробнее см. в разделе Старт или окончание маршрута в произвольной точке.

Если курьеры стартуют из точки типа garage, но часть заказов нужно забрать на складе, включите опцию Может посещать склад в начале маршрута (can_visit_depot_at_start в API, по умолчанию false). Опция работает только для тех курьеров, у кого указан параметр visit_depot_at_start = false. У заказов, которые нужно забрать на складе, укажите один из следующих параметров:

depot_id, чтобы привязать заказ к складу;

depot_ready_timeвремя готовности заказа на складе;

depot_expiring_timeкрайнее время получения заказа на складе.

Также можно неявно разрешить заезд на склад в начале маршрута при выключенной опции can_visit_depot_at_start, если явно указать склад в planned_route, зафиксированной части маршрута или при допланировании.

Пример 1

Доставку выполняют три автомобиля. Первый начинает доставку со склада. Второй начинает и заканчивает маршрут без посещения склада. При этом точка старта для курьера — заказ 6, который имеет тип garage. Третий начинает маршрут не со склада, а с заказа 4 (тип garage), но обязан посетить склад до начала выполнения заказов.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Доставку выполняют три автомобиля. Первый начинает доставку со склада. Второй и третий начинают и заканчивают маршрут без посещения склада. Заказы 1 и 7 имеют тип pickup, и алгоритм выбирает их первыми точками маршрутов.

В результате запланированы три отдельных маршрута из-за наличия приоритетов у заказов.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Доставку выполняют два автомобиля (visit_depot_at_start = false и can_visit_depot_at_start = true). Первый стартует с точки типа garage и в начале пути заезжает на склад за заказом 1. Маршрут второго не предполагает заезд на склад, он сразу едет на доставку.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Старт с одного из нескольких складов

Курьер может стартовать с одного из нескольких складов. Эти склады нужно перечислить в поле depot_id (склады, которые может посещать курьер) или starting_depot_id (склады, с которых курьер может начинать маршрут). Эти списки могут пересекаться. Если складов несколько, алгоритм выберет оптимальный склад для старта. Если поля depot_id и starting_depot_id для курьера не заполнены, то он стартует с первого склада из списка depots.

Внимание

В полях vehicle.depot_id и vehicle.starting_depot_id нельзя одновременно указывать и обычные склады, и кросс-доки. В одном маршруте курьер может посещать или только обычные склады, или только кросс-доки.

Если использовать функциональность доставки с одного из нескольких складов, курьер сможет забирать заказы с любого из складов, которые он может посещать.

Дополнительно для курьера можно задать параметры allow_different_depots_in_route и max_middle_depots. Подробнее см. в разделе Выбор оптимального склада для старта.

Дозагрузка на промежуточном складе

Чтобы у курьера была возможность посещать во время движения по маршруту дополнительные склады для дозагрузки заказов, установите параметр allow_different_depots_in_route = true. Склады для дозагрузки необходимо указать в поле depot_id (склады, которые может посещать курьер) или middle_depot_id (склады для дозагрузки). Списки складов могут пересекаться. Если заказы есть на нескольких складах, то алгоритм выберет оптимальный склад для дополнительной загрузки.

Внимание

В полях vehicle.depot_id и vehicle.middle_depot_id нельзя одновременно указывать и обычные склады, и кросс-доки. В одном маршруте курьер может посещать или только обычные склады, или только кросс-доки.

Если курьер может заезжать на промежуточные склады для дозагрузки только в начале маршрута (до посещения первого заказа), установите параметр depots_only_at_run_beginning = true (по умолчанию false).

Дополнительно для курьера можно задать параметр max_middle_depots. Подробнее см. в разделе Заезд на дополнительный склад.

Возврат на склад в конце маршрута или рейса

По умолчанию курьер завершает маршрут на складе, с которого стартовал. Чтобы разрешить курьеру посещать несколько складов на маршруте, устанавливают параметр allow_different_depots_in_route = true. В этом случае курьер может завершать маршрут на складе, отличном от начального.

Склады, где курьер может завершить маршрут, указывают в поле depot_id (склады, которые может посещать курьер) или ending_depot_id (склады, где курьер может завершать маршрут). Эти списки могут пересекаться. Если складов несколько, алгоритм выберет оптимальный склад для возврата.

Внимание

В полях vehicle.depot_id и vehicle.ending_depot_id нельзя одновременно указывать и обычные склады, и кросс-доки. В одном маршруте курьер может посещать или только обычные склады, или только кросс-доки.

Чтобы курьер завершал маршрут на том же складе, откуда выехал, используйте параметр finish_route_in_starting_depot = true (по умолчанию false). Если при этом курьер начинает маршрут не со склада (visit_depot_at_start = false), он должен будет вернуться на тот склад, откуда выехал на второй рейс маршрута.

Чтобы курьер завершал каждый рейс на том же складе, откуда этот рейс был начат, используйте параметр finish_run_in_starting_depot = true (по умолчанию false). Чтобы курьер между рейсами мог переехать с одного склада на другой, задайте параметр can_change_depot_between_runs = true, см. Старт нового рейса с другого склада.

Примечание

Параметры finish_route_in_starting_depot = true и finish_run_in_starting_depot = true имеют смысл, только если allow_different_depots_in_route = true.

Если курьер не должен возвращаться на склад после выполнения всех заказов, используйте опцию return_to_depot = false.

Пример 1.1

Два курьера должны доставить два заказа: один заказ delivery нужно забрать со Склада 1, второй заказ pickup нужно доставить на Склад 2. Оба курьера могут сделать только по 1 рейсу, выехать с любого склада и завершить маршрут на любом складе. Обоим курьерам разрешено посещать разные склады в одном рейсе, но заезжать на промежуточные склады курьеры не могут.

В решении используется только один курьер: он выезжает со Склада 1, забрав заказ delivery, доставляет его, забирает заказ pickup и доставляет его на Склад 2, где и завершает маршрут.

Запрос API (JSON)Ответ APIОткрыть на карте

Пример 1.2

То же, что в примере 1.1, но курьеры должны завершить маршрут на том же складе, откуда выехали (finish_route_in_starting_depot = true).

В решении используются оба курьера. Курьер 1 выезжает со Склада 1, забрав заказ delivery, доставляет его и возвращается на Склад 1. Второй курьер выезжает со Склада 2, забирает заказ pickup и возвращается с ним на Склад 2.

Запрос API (JSON)Ответ APIОткрыть на карте

Возврат на произвольную точку в конце маршрута

Если в вашем сценарии работы необходимо учитывать удаленность последнего заказа от места парковки курьера или, например, домашнего адреса, вы можете это учесть следующим образом:

  • Создайте точку с типом garage (поле location.type). Эта точка будет использоваться только для окончания маршрутов.

  • Для курьера, которому необходимо вернуться в конце работы «домой» или «на парковку», укажите идентификатор этой точки в поле vehicle.finish_at.

При решении задачи все автомобили или курьеры, у которых указано свойство finish_at, вернутся на указанную точку. Если включена опция возврата на склад (vehicle.return_to_depot = true), то в маршруте сначала будет посещен склад, а затем проложен путь до места парковки.

Пример

В примере ниже используется два автомобиля с разной грузоподъемностью и четыре заказа с различным весом. Оба автомобиля участвуют в доставке из-за весовых ограничений. Автомобиль 2 не должен возвращаться на склад после доставки последнего заказа.

Примечание

Обратите внимание, что в ответе Маршрутизации автомобиль 2 завершает маршрут на последнем заказе.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Начало или окончание маршрута как можно ближе к складу

Для курьера можно запланировать маршрут так, чтобы он начинал или заканчивал движение на заказе, который находится ближе всего к складу, или наоборот, дальше всего от склада. Например, можно начинать маршрут с наиболее близких к складу заказов, если с утра могут появиться дополнительные заказы, за которыми нужно вернуться на склад. Также иногда удобно начинать маршрут с самого дальнего заказа, чтобы к вечеру оказаться недалеко от склада.

Если вы не применяете расширенные настройки стоимости, используйте следующие параметры:

  • first_edges_penalty_factor — штраф за расстояние от склада до первого заказа, по умолчанию 0. Если значение больше 0, алгоритм минимизирует это расстояние, а если меньше 0 — максимально увеличивает.

  • last_edges_penalty_factor — штраф за расстояние от склада до последнего заказа, по умолчанию 0. Если значение больше 0, алгоритм минимизирует это расстояние, а если меньше 0 — максимально увеличивает.

Штрафы рассчитываются по аналогии с длительностью и длиной отрезков на маршруте, см. группу Движение между точками на маршруте в разделе Расширенные настройки стоимости.

При больших значениях штрафов маршруты могут получиться неоптимальными по пробегу. При маленьких значениях штрафов требование по выбору первого или последнего заказа на маршруте может нарушаться, если это значительно экономит пробег.

Если вы применяете расширенные настройки стоимости, используйте ключевые слова из группы Движение от склада или к складу.

Пример

В примере ниже 1 курьер и 10 заказов. Заданы 2 штрафа: first_edges_penalty_factor = 2 и last_edges_penalty_factor = -2. В результате планирования маршрут начинается с самого близкого к складу заказа и заканчивается самым дальним.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Смены работы автомобиля или курьера

Для автомобиля можно определить одну или несколько смен работы. Для определения смен используется поле vehicle.shifts.

Смена представляет собой диапазон времени, в который разрешена работа автомобиля. Время смены включает в себя время нахождения на складе при загрузке, а также время в движении, сервисное время на заказах и время разгрузки на складе (если автомобиль возвращается на склад).

Для использования одной или более смен в Excel необходимо определить следующие поля:

  • shifts.0.time_windowмягкое временное окно, соответствующее времени работы автомобиля.

  • shifts.0.hard_windowфлаг жесткого временного окна. Если окно жесткое, алгоритм не может выйти за рамки заданного интервала.

  • shifts.0.service_duration_s — время между сменами (в секундах). Например, время на замену водителя, обмен документами и т.д.

Также можно ограничить максимальную продолжительность смены (shifts.N.max_duration_s и shifts.N.hard_max_duration_s).

В случае определения мягкого временного окна можно дополнительно задать штрафы:

  • за нарушение временного окна:

    • shifts.0.penalty.out_of_time.fixed — штраф за факт нарушения временного окна смены.
    • shifts.0.penalty.out_of_time.minute — штраф за минуту нарушения временного окна смены.
  • за ранний выезд:

    • shifts.0.penalty.early.fixed — штраф за факт начала работы раньше временного окна смены.
    • shifts.0.penalty.early.minute — штраф за минуту начала работы раньше временного окна смены.
  • за опоздание:

    • shifts.0.penalty.late.fixed — штраф за факт завершения работы позже временного окна смены.
    • shifts.0.penalty.late.minute — штраф за минуту завершения работы позже временного окна смены.

Чтобы ограничить допустимые нарушения временного окна смены, можно задать жесткое окно вокруг мягкого.

Начало, окончание и продолжительность смены

Пусть задано временное окно смены time_window с 9:00 до 18:00. Используются признак жесткости временного окна hard_window, максимальная продолжительность смены max_duration_s и признак гибкого времени старта со склада depot.flexible_start_time.

Как нужно запланировать работу курьера

Параметры

Выбрать интервал работы желательно не больше 6 часов строго между 9 и 18 часами

hard_window = true

max_duration_s = 6 часов (меньше окна смены)

flexible_start_time = true

Начать работу строго в 9 часов, желательно завершить работу до 15 часов, при необходимости можно работать до 18 часов, строго не позже (это сочетание параметров аналогично условию time_window = 9:00 - 15:00, hard_time_window = 9:00 - 18:00, flexible_start_time = false)

hard_window = true

max_duration_s = 6 часов (меньше окна смены)

flexible_start_time = false

Выбрать интервал работы желательно не больше 6 часов желательно между 9 и 18 часами

hard_window = false

max_duration_s = 6 часов (меньше окна смены)

flexible_start_time = true

Начать работу строго в 9 часов, желательно завершить работу до 15 часов, при необходимости можно работать до 18 часов, желательно не позже (это сочетание параметров аналогично условию time_window = 9:00 - 15:00, max_duration_s = 9 часов)

hard_window = false

max_duration_s = 6 часов (меньше окна смены)

flexible_start_time = false

Начать работу можно позднее 9 часов, желательно закончить работу до 18 часов, желательно работать не более 10 часов

hard_window = false

max_duration_s = 10 часов (больше окна смены)

flexible_start_time = true

Начать работу строго в 9  часов, желательно завершить работу до 18 часов, но желательно не позже 19 часов (это сочетание параметров аналогично условию time_window = 9:00 - 19:00, max_duration_s = 9 часов)

hard_window = false

max_duration_s = 10 часов (больше окна смены)

flexible_start_time = false

Такое сочетание параметров не позволит запланировать решение

hard_window = true

max_duration_s = 10 часов (больше окна смены)

flexible_start_time = true или flexible_start_time = false

Примечание

Обратите внимание, что для определения нескольких смен необходимо несколько полей в Excel с увеличивающимся числовым индексом.

Например shifts.0.time_window относится к первой смене, а shifts.1.time_window — ко второй смене.

Пример

В запросе к Маршрутизации задан 1 автомобиль с 3 сменами (утренняя, дневная, вечерняя), а также 3 заказа, из которых 1 имеет время доставки утром, и 2 вечером.

Примечание

Обратите внимание, что в ответе Маршрутизации будут использованы только утренняя и вечерняя смена, так как на дневную смену нет ни одного заказа на доставку.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Несколько рейсов курьера в день

По умолчанию курьер начинает и завершает маршрут на складе, то есть выполняет ровно один маршрут в течение рабочего дня (смены).

Если курьер может возвращаться на склад в любое время рабочей смены для дозагрузки дополнительных заказов, количество рейсов можно ограничить с помощью одного из параметров:

  • vehicle.shifts.N.max_runs — максимальное количество рейсов для данной смены. По умолчанию равно 1.

  • vehicle.max_runs — максимальное количество рейсов для всех смен курьера в сумме (например, курьер может выполнить все рейсы в одну смену). Количество рейсов курьера может быть меньше, чем количество смен. По умолчанию равно 1.

  • если ни один из параметров не задан, курьер может делать столько рейсов, сколько у него смен — в каждой смене по одному рейсу.

Примечание

В задаче планирования можно использовать либо vehicle.max_runs, либо vehicle.shifts.N.max_runs, но не оба параметра одновременно.

Для курьера должна быть задана хотя бы одна смена.

Пример

В примере ниже используется один автомобиль с ограниченной вместимостью в 2 тонны и три заказа с весом в 0,8 тонн. Автомобилю разрешено два рейса, то есть автомобиль может вернуться на склад после выполнения двух заказов для загрузки и доставки еще одного заказа.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Ограничение количества остановок в смене

При планировании маршрута можно указать минимальное и максимальное количество остановок в маршруте. Это может быть полезно, например, чтобы ограничить максимальную нагрузку на курьера в день или, наоборот, обязательно вывести курьера на маршрут с каким-то количеством остановок.

В Маршрутизации для этого используются параметры смены minimal_stops и maximal_stops. Для каждого курьера можно задать свое количество остановок.

Ограничение не является строгим и может быть нарушено. При нарушении ограничения по минимальному количеству остановок начисляется штраф, указанный в полях смены penalty.stop_lack.fixed (за  факт остановок меньше минимального количества) и penalty.stop_lack.per_stop (за каждую остановку меньше минимального количества).

Соответственно, при нарушении ограничения по максимальному количеству остановок начисляются штрафы, указанные в полях смены в полях смены penalty.stop_excess.fixed (за факт остановок больше максимального количества) и penalty.stop_excess.per_stop (за каждую остановку больше максимального количества).

Примечание

Как правило, использование ограничений на количество остановок приводит к ухудшению метрик решения, поскольку решение смещается в сторону выполнения ограничений в ущерб оптимальности маршрута.

Уникальные остановки

При использовании параметра minimal_stops заказы с совпадающими координатами считаются различными остановками, если в маршруте они расположены не подряд. Поэтому чтобы выполнить условие minimal_stops, алгоритм может спланировать маршрут так, что курьеру придется несколько раз приезжать на один и тот же адрес.

Чтобы избежать повторных приездов, вместо minimal_stops используйте параметр minimal_unique_stops и штрафы penalty.unique_stop_lack.fixed и penalty.unique_stop_lack.per_stop.

Параметр minimal_unique_stops учитывает только заказы с уникальными координатами, поэтому курьеру не будут запланированы повторные приезды. Однако заказы по одному и тому же адресу могут быть распределены на разных курьеров, поскольку в этом случае они считаются разными остановками, и алгоритм может использовать это для выполнения ограничения minimal_unique_stops.

Ограничение minimal_unique_stops имеет смысл использовать, если в маршруте много мультизаказов.

Остановки у неиспользуемых курьеров

По умолчанию ограничения количества минимальных остановок minimal_stops и minimal_unique_stops работают для всех заданных курьеров. Если курьеров задано больше чем необходимо, и значение штрафов penalty.stop_lack или penalty.unique_stop_lack слишком высокое, это может приводить к неоптимальному результату планирования.

Использовать ограничение минимального количества остановок в смене и в то же время построить эффективный маршрут позволяет опция ignore_min_stops_for_unused, см. раздел Учет минимального количества остановок только для используемых ТС.

Пример 1

В примере маршрут строится для 3 курьеров, выполняющих доставку по 15 точкам. Поскольку на маршруте не указано никаких ограничений, маршрут строится обычным образом.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

В примере указаны те же условия, что и в примере 1, но указано ограничение на 4 минимальных остановки для каждого курьера. В результате маршруты изменились так, чтобы каждый курьер посетил хотя бы 4 точки доставки.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

В примере указаны те же условия, что и в примере 1, но указано ограничение на 5 максимальных остановок для каждого курьера. В результате заказы распределены равномерно между всеми курьерами, даже несмотря на то, что несколько заказов расположены рядом и могли бы быть выполнены одним курьером.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Максимальная продолжительность смены

Иногда возникает необходимость продлить период работы курьера. При этом нужно ограничить максимальную продолжительность смены и установить период, в который желательно попасть. Например, есть определенное окно, в которое курьеры выполняют доставки, длиной в 14 часов (с 8 до 22 часов), но продолжительность смены каждого курьера не должна превышать 10 часов (max_duration_s), а продолжительность рабочего времени в смене — 8 часов (max_working_duration_s).

Маршрутизация позволяет планировать смены с жесткими временными окнами и желательной продолжительностью. При этом продолжительность смены курьера не влияет на время начала работы, а только на то время, которое он потратит на выполнение заказов.

Максимальная продолжительность смены может быть задана как мягкое ограничение shifts.N.max_duration_s, которое можно нарушить и получить штраф, и как жесткое ограничение shifts.N.hard_max_duration_s, которое нарушить нельзя:

  • При планировании с мягким ограничением нагрузка, не укладывающаяся в желательную смену одного курьера, распределяется на других или на того же курьера, но со штрафами за превышение длины смены. Все заказы, которые невозможно выполнить за время max_duration_s, добавляются в маршрут со штрафом за опоздание shift.penalty.late, если это значение указано, или за нарушение окна shift.penalty.out_of_time в противном случае. Итоговая сумма штрафа для маршрута за нарушение максимальной продолжительности смены указывается в ответе API в поле overtime_penalty. Если расчетная стоимость заказа с учетом штрафов выше, чем стоимость выполнения заказа другим курьером, заказ передается другому курьеру.

  • При планировании с жестким ограничением смена курьера ни при каких условиях не превышает значение, заданное в hard_max_duration_s.

Максимальная продолжительность рабочего времени в смене также может быть задана как мягкое shifts.N.max_working_duration_s и жесткое shifts.N.hard_max_working_duration_s ограничения.

  • Если нарушается мягкое ограничение, лишняя нагрузка распределится на других курьеров или на того же курьера, но со штрафами. Заказы, которые не будут выполнены за рабочее время в смене max_working_duration_s, добавятся в маршрут со штрафом working_overtime:

    • shifts.N.penalty.working_overtime.fixed — штраф за факт превышения максимальной продолжительности рабочего времени в смене;

    • shifts.N.penalty.working_overtime.minute — штраф за минуту такого превышения.

    Если значение этого штрафа не указано, к заказам применится штраф за нарушение окна shift.penalty.out_of_time. Итоговая сумма штрафа отразится в ответе API в поле working_overtime_penalty. Заказ будет передан другому курьеру, если расчетная стоимость заказа с учетом штрафов превысит стоимость выполнения заказа другим курьером.

  • При планировании с жестким ограничением максимальная продолжительность рабочего времени в смене ни при каких условиях не превышает значение, заданное в hard_max_working_duration_s.

Если для max_duration_s и max_working_duration_s заданы оба ограничения (мягкое и жесткое), то жесткое должно быть не меньше мягкого. По умолчанию max_duration_s и max_working_duration_s составляют 2 суток, hard_max_duration_s и hard_max_working_duration_s — 30 суток.

Пример 1

Пусть окно смены shifts.N.time_window — с 8 до 23. По умолчанию маршруты будут построены с использованием минимального количества курьеров.

Если указать max_duration_s = 14400, то нагрузка будет распределена между курьерами так, чтобы каждый из них работал примерно 4 часа (длина смены задается в секундах). При этом некоторые курьеры все еще могут работать больше 4 часов, потому что выгоднее оплатить лишнее время работы, чем доставить заказ другим курьером.

В результате планирования заказы распределены между тремя курьерами. Длина смены одного из курьеров превысила 4 часа, сумма штрафа за нарушение указана в ответе API в поле overtime_penalty.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

То же, что и в примере 1, но вместо мягких ограничений максимальной продолжительности смены заданы жесткие: hard_max_duration_s = 14400. При планировании для каждого курьера выдержана смена, не превышающая 4 часов. В результате количество курьеров увеличилось до 4.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Три курьера развозят 26 заказов. Окно смены shifts.N.time_window — с 8 до 23. Установлены штрафы за факт (shifts.N.penalty.working_overtime.fixed) и минуту (shifts.N.penalty.working_overtime.minute) превышения максимальной продолжительности рабочего времени в смене.

Если указать shifts.0.max_working_duration_s = 14400, то каждый из курьеров будет работать примерно 4 часа. Ограничение мягкое, поэтому смена одного из курьеров превышает это время.

В результате планирования все заказы распределены между курьерами, а общая сумма штрафа за нарушение указана в ответе API в поле working_overtime_penalty.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 4

То же, что в примере 3, но задано жесткое ограничение максимальной продолжительности рабочего времени в смене shifts.N.hard_max_working_duration_s = 14400.

В результате планирования все курьеры задействованы и работают не дольше 4 часов, но один из заказов при этом остался нераспределенным.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Максимальный пробег за смену

В некоторых случаях пробег машины нужно ограничить. Например:

  • В планировании участвуют наемные машины, и тариф за их использование подразумевает лимит по пробегу.

  • На дальние точки должны ехать определенные машины. Тогда прочим машинам можно ограничить пробег.

Параметр shifts.max_mileage_km определяет максимальный пробег машины за смену. Учитывается весь пробег, включая:

  • движение от склада или точки старта до первой точки из списка заказов;

  • возврат на склад или точку завершения маршрута от последней точки из списка заказов.

Ограничение мягкое: алгоритм может его нарушить. Штрафы задаются в полях:

  • shifts.penalty.max_mileage.fixed — штраф за факт превышения максимального пробега (по умолчанию 1000);

  • shifts.penalty.max_mileage.km — штраф за каждый километр превышения максимального пробега (по умолчанию 100).

Если для вас важен максимальный пробег за рейс, а машина может выполнить несколько рейсов за смену, нужно сделать несколько одинаковых смен (см. Пример 2).

Если курьер передвигается общественным транспортом, в пробеге возвращается только пешая часть маршрута.

Пример 1

Ограничение пробега каждого курьера — 50 км. За нарушение задан большой штраф. В результате плановый пробег на любом маршруте не превышает 50 км.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Есть один курьер, и каждый его рейс должен быть ограничен 50 км. Для этого у курьера задано несколько смен с одинаковыми временными окнами и ограничениями по пробегу. В результате сформировано 3 рейса, каждый протяженностью менее 50 км.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Кучность маршрута

Если для автомобиля нужно задать желаемый район работы — так, чтобы в маршрут включались заказы, расположенные недалеко от определенной точки, — используйте параметр global_proximity_attraction_point. В значении параметра укажите id точки с типом garage. Эта точка используется как «точка притяжения» — алгоритм стремится уменьшить сумму расстояний от заказов в маршруте до этой точки.

На кучность построения маршрутов вокруг «точки притяжения» влияет опция options.global_proximity_factor — чем больше ее значение, тем маршруты кучнее. Подробнее об опции см. в разделе Кучные маршруты.

Максимальное расстояние от точек маршрута до  «точки притяжения» хранится в параметре max_distance_to_attraction_point_m, который может использоваться для расчета стоимости маршрута. Итоговая сумма расстояний от всех заказов до  «точки притяжения» в маршруте влияет на размер штрафа за недостаточную сгруппированность маршрутов.

Другие способы сгруппировать заказы географически
  • С помощью опции global_proximity_factor можно построить кучные маршруты без указания «точки притяжения». Опция работает только для автомобилей, у которых не задан параметр global_proximity_attraction_point.
  • С помощью геозон для автомобилей можно задать ограничения по зонам доставки. Ограничение по геозонам нельзя нарушить, по сравнению с ним настройки кучности маршрутов являются более гибким инструментом.

Пример 1

Три автомобиля должны доставить 15 заказов. Маршрут рассчитывается исходя из веса заказов и грузоподъемности автомобилей. Иных ограничений на маршруте не задано.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

То же, что и в примере 1, но для каждого курьера задана «точка притяжения», обозначающая желаемый район работы. В результате маршруты стали более кучными. Максимальное расстояние от заказа до  «точки притяжения» в маршруте составило 20 663 м.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

То же, что и в примере 2, но для одного из курьеров изменена «точка притяжения». В результате за счет перегруппировки заказов расположение маршрутов на карте поменялось. Максимальное расстояние от заказа до  «точки притяжения» увеличилось и составило 28 528 м.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Стоимость автомобиля или курьера

Для каждого автомобиля в запросе к Маршрутизации можно задать различные компоненты стоимости использования. Для определения стоимости автомобиля или курьера используется опциональное поле запроса vehicle.cost.

Маршрутизация позволяет определить следующие основные компоненты стоимости:

  • cost.fixed — фиксированная стоимость использования автомобиля.

  • cost.hour — стоимость за час работы.

  • cost.km — стоимость за километр пробега.

  • cost.location — стоимость посещения одного заказа.

  • cost.run — стоимость выполнения одного рейса.

  • cost.tonne_km — стоимость за тонно-километр транспортной работы.

В данном случае используется стоимость, по которой алгоритм выбирает оптимальный вариант маршрутизации. Это не тариф, который начисляется в реальности за использование автомобиля, а скорее настройки алгоритма.

Cтоимость автомобиля или курьера также можно задать в виде арифметического выражения. Подробнее см. в разделе Расширенные настройки стоимости.

Значения стоимости

Обратите внимание, что некоторые компоненты стоимости транспортного средства уже заданы по умолчанию:

  • cost.fixed = 3000

  • cost.hour = 100

  • cost.km = 8

Они применяются в случаях:

  • если вы используете Excel и оставляете эти поля пустыми;

  • если вы обращаетесь по API и не заполняете поле запроса vehicle.cost.

Часто значения по умолчанию необходимо корректировать. Например, в следующих бизнес-кейсах:

Примечание

Всегда заполняйте cost.hour и cost.km значениями, отличными от 0 — иначе маршруты будут получаться хаотичными. Это происходит потому, что алгоритм оптимизирует итоговую стоимость, а если стоимость пробега или времени для него равна 0, то маршрут с любым пробегом будет стоить одинаково.

Если вы хотите минимизировать стоимость маршрута, значения cost.hour и cost.km должны быть больше 0.

Стоимость тонно-километра транспортной работы

Тяжело нагруженные машины расходуют больше топлива и быстрее изнашиваются. Поэтому для перевозки тяжелых грузов требуется строить маршруты так, чтобы расстояние, которое ТС проходит с большой загрузкой, было минимальным.

В Маршрутизации для этого используется свойство cost.tonne_km. Оно определяет стоимость одного километра пути для каждой тонны груза в машине. Значение по умолчанию — 0.

Суммарный объем транспортной работы в тонно-километрах возвращается в поле total_transport_work_tonne_km ответа API, а ее суммарная стоимость — в поле total_transport_work_cost.

Пример 1

Нужно доставить 3 груза весом 100, 200 и 2000 кг. Стоимость одного тонно-километра cost.tonne_km задана равной нулю. В результате самый тяжелый заказ доставлен последним: загрузка ТС не учитывалась при построении маршрута, а по другим критериям такой вариант оказался оптимальным.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Исходные данные те же, но cost.tonne_km = 8. В итоге решение оптимизировано с учетом загрузки: самый тяжелый заказ выгружен первым.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Расширенные настройки стоимости

Стоимость автомобиля или курьера можно задать в виде арифметического выражения. При планировании вы можете рассчитать стоимость одним выражением в поле vehicles.cost или использовать несколько выражений во вложенных полях:

  • cost.route — для маршрута;
  • cost.shift — для смены;
  • cost.run — для рейса.

Внимание

Если в поле vehicle.cost заданы формулы, то алгоритм рассчитывает стоимость автомобиля или курьера только по этим формулам. При этом стандартные компоненты стоимости участвуют в расчете, только если указаны в формулах в явном виде.

В выражении можно использовать ключевые слова и математические обозначения, которые приведены в таблицах ниже. Проверить правильность выражения можно с помощью HTTP-запроса.

Ключевые слова для параметров маршрута

Группа

Ключевое слово и пояснение

Рейсы

  • run_index_in_route — номер рейса в маршруте, начиная с 1. Используется только для рейса;
  • run_count_in_route — количество рейсов в маршруте. Используется только для маршрута;
  • run_index_in_shift — номер рейса в смене, начиная с 1. Используется только для рейса;
  • run_count_in_shift — количество рейсов в смене. Используется только для рейса или смены;
  • runs — количество рейсов. Если переменная используется для рейса, то ее значение равно 1; если для смены, то runs = run_count_in_shift; если для всего маршрута, то runs = run_count_in_route.

Смены

  • shift_index_in_route — номер смены в маршруте, начиная с 1. Пустые смены при этом пропускаются и не считаются;
  • shift_count_in_route — количество используемых (непустых) смен в маршруте.

Заказы и остановки

  • locations — количество заказов;
  • stops — количество остановок, включая заказы, склады, паркинги, якорные точки и т. п. (соседние точки с одинаковыми координатами считаются одной остановкой);
  • unique_stops — количество остановок с уникальными координатами;
  • total_custom_value — сумма значений поля custom_value (дополнительный параметр заказа) по всем заказам в маршруте;
  • max_custom_value — максимальное значение поля custom_value среди всех заказов в маршруте.

Длительность

  • duration_h — общая длительность маршрутов, в часах;
  • transit_duration_h — длительность движения;
  • service_duration_h — длительность обслуживания заказов;
  • wait_duration_h — длительность ожидания;
  • rest_duration_h — длительность отдыха.

Расстояние

  • distance_km — общая протяженность маршрутов, в км;
  • max_distance_from_depot_m — расстояние от склада до самой далекой точки маршрута;
  • max_distance_to_garage_m — максимальное расстояние до гаража в конце маршрута;
  • max_distance_to_attraction_point_m — максимальное расстояние от точек маршрута до «точки притяжения», указанной в опции global_proximity_attraction_point. Если опция не задана, то max_distance_to_attraction_point_m = 0.

Если для автомобиля нужно задать желаемый район работы — так, чтобы в маршрут включались заказы, расположенные недалеко от определенной точки, — используйте параметр global_proximity_attraction_point. В значении параметра укажите id точки с типом garage. Эта точка используется как «точка притяжения» — алгоритм стремится уменьшить сумму расстояний от заказов в маршруте до этой точки.

Транспортная работа

  • transport_work_tonne_km — транспортная работа, в тонно-километрах.

Склады

  • middle_depots — количество промежуточных складов в маршруте.

Начало и окончание движения

  • start_route_time_s — время начала маршрута, в секундах от начала суток;
  • finish_route_time_s — время окончания маршрута, в секундах от начала суток.

Движение между точками на маршруте

  • first_edges_distance_km — длина отрезка от склада или гаража (точки с типом garage) до первого заказа в рейсе, в км;
  • first_edges_duration_h — длительность отрезка от склада или гаража до первого заказа в рейсе, в часах;
  • max_first_edges_distance_km — максимальная длина отрезка от склада или гаража до первого заказа по всем рейсам в маршруте, в км;
  • max_first_edges_duration_h — максимальная длительность отрезка от склада или гаража до первого заказа по всем рейсам в маршруте, в часах;
  • last_edges_distance_km — длина отрезка от последнего заказа в рейсе до склада или гаража, в км;
  • last_edges_duration_h — длительность отрезка от последнего заказа в рейсе до склада или гаража, в часах;
  • max_last_edges_distance_km — максимальная длина отрезка от последнего заказа до склада или гаража по всем рейсам в маршруте, в км;
  • max_last_edges_duration_h — максимальная длительность отрезка от последнего заказа до склада или гаража по всем рейсам в маршруте, в часах;
  • max_edge_distance_m — длина максимального отрезка между заказами во всех маршрутах, в м;
  • max_edge_duration_h — длительность максимального отрезка между заказами во всех маршрутах, в часах.

При вычислении расстояния и времени движения между точками на маршруте заказами считаются типы delivery, pickup и drop_off. Кросс-доки приравниваются к обычным складам. Парковки (тип parking), якорные точки для прицепов (anchor) и места отдыха (rest_place) игнорируются. Например, если при построении маршрута получилась последовательность точек «заказ — парковка — заказ», то будет рассчитано расстояние и время движения между заказами напрямую.

Параметры используются для реализации тех же сценариев, что и штрафы за начало или окончание маршрута как можно ближе к складу.

Движение с заказами и без заказов

  • empty_distance_km — расстояние, пройденное без заказов (порожний пробег), в км;
  • non_empty_distance_km — расстояние, пройденное хотя бы с одним заказом, в км.

Вместимость

  • utilization_cbm — максимальной объем загрузки машины;
  • utilization_units — максимальная загрузка машины заказами;
  • utilization_kg — максимальный вес загрузки машины;
  • min_free_units — минимальное свободное место в машине;
  • min_free_weight_kg — минимальный свободный вес в машине;
  • min_free_volume_cbm — минимальный свободный объем в машине;
  • total_weight_kg — суммарный вес перевезенных грузов;
  • total_units — суммарное количество перевезенных грузов;
  • total_volume_cbm — суммарный объем перевезенных грузов.

Прицеп

  • trailer_used — если в маршруте используется прицеп, то trailer_used = 1; если не используется, то trailer_used = 0;
  • trailer_duration_h — общая продолжительность использования прицепа, в часах;
  • trailer_distance_km — путь, пройденный с прицепом, в км.

Пешеходные маршруты

  • walking_transit_duration_h — длительность движения пешком;
  • driving_transit_duration_h — длительность движения на автомобиле;
  • walking_distance_km — расстояние, которое курьер прошел пешком;
  • driving_distance_km — расстояние, которое курьер проехал на автомобиле.

Метрики маршрута рассчитываются по следующим формулам:

  • общая длительность маршрута transit_duration_h = walking_transit_duration_h + driving_transit_duration_h;
  • общая длина маршрута distance_km = walking_distance_km + driving_distance_km.

На вычисление переменных, которые используются в маршрутах с пешеходными частями, влияет способ передвижения:

  • walking — весь маршрут обслуживается пешком, расстояние driving_distance_km и длительность driving_transit_duration_h равны 0;
  • transit:
    • driving_distance_km = 0 — считается, что все заказы курьер посетил пешком (для подсчета расстояния, пройденного на общественном транспорте, недостаточно данных);
    • driving_transit_duration_h вычисляется на основании других данных, полученных при решении задачи (может быть ненулевым).

Математические обозначения и функции

Математические обозначения

Пояснение

Числа

Целые (положительные, отрицательные), рациональные.

Для десятичных дробей в качестве разделителя используйте точку.

Арифметические действия

+, -, *, /

Скобки

(…)

Математические функции

  • max()/min() с произвольным числом операндов;
  • Round() — округление до целого числа;
  • Ceil() — округление до большего целого числа;
  • Floor() — округление до меньшего целого числа;
  • Abs() — вычисление абсолютного значения (модуля) числа;
  • RoundTo()/CeilTо()/FloorTo() — округление дробей до цифры, которую задает пользователь, например (RoundTo(x, 100) == 100*Round(x/100)).

Логические функции

bool() — переводит любое ненулевое вещественное число в 1.0, а нулевое — в 0.0

Операции сравнения

<, >, =

Логические операции

  • & — логическое И;
  • | — логическое ИЛИ;
  • ! — логическое отрицание.

Функции

  • has_location(<условие>) — проверяет, есть ли в маршруте (рейсе, смене) остановка, соответствующая критерию;
  • has_order(<условие>) — проверяет, есть ли в маршруте (рейсе, смене) заказ (pickup или delivery), соответствующий критерию;
  • order_count(<условие>) — возвращает количество заказов (pickup или delivery) в маршруте (рейсе, смене), которые соответствуют критерию;
  • stop_count(<условие>) — возвращает количество остановок (pickup, delivery или dropoff) в маршруте (рейсе, смене), которые соответствуют критерию. В мультизаказе все заказы будут посчитаны, как одна остановка;
  • location_count(<условие>) — возвращает количество остановок любых типов в маршруте (рейсе, смене), которые соответствуют критерию. В мультизаказе каждый заказ будет посчитан, как отдельная остановка.

Условия функций

Следующие функции можно использовать только внутри условий функций has_location, has_order, order_count, stop_count и location_count:

  • in_zone(<название зоны>) — определяет, находится ли остановка в указанной зоне;
  • has_load_type(<название типа загрузки>) — определяет, есть ли у заказа указанный тип загрузки;
  • has_required_tag(<название тега>) — определяет, есть ли у заказа указанный обязательный тег;
  • has_optional_tag(<название тега>) — определяет, есть ли у заказа указанный опциональный тег;
  • has_tag(<название тега>) — определяет, есть ли у заказа указанный тег (опциональный или обязательный);
  • is_order() — определяет, является ли остановка заказом (pickup или delivery);
  • is_pickup() — определяет, является ли остановка заказом с типом pickup;
  • is_delivery() — определяет, является ли остановка заказом с типом delivery.
Примеры выражений
  • 500 + 500 * has_location(in_zone('West')) — если в маршруте есть остановка в зоне West, то вернется 1000, иначе 500.
  • 450 * location_count(in_zone('West') | in_zone('North')) — выражение посчитает количество остановок, которые попадают хотя бы в одну из двух зон (West, North) и вернет их количество, умноженное на 450.
  • 1000 + has_location(in_zone('West') & has_load_type('Заморозка')) * 500 — если в маршруте есть хотя бы одна остановка, которая одновременно находится в зоне West и имеет тип загрузки Заморозка, то выражение вернет 1500, иначе 1000.
  • 100 * (has_location(in_zone('West')) & has_location(in_zone('North'))) — если есть хотя бы одна остановка в зоне West и хотя бы одна остановка в зоне North (может быть одна остановка в обеих зонах или две разных), то вернется 100.
  • 100 * has_location(in_zone('West') & in_zone('North')) — если есть остановка, которая одновременно попадает в обе зоны West и North, то выражение вернет 100.
  • 100 * location_count(is_pickup() & in_zone('West') & !has_tag('Возврат')) — выражение посчитает количество заказов с типом pickup, которые находятся в зоне West и при этом не имеют тега Возврат, и вернет их количество, умноженное на 100.

Метрики решения

Если для автомобиля или курьера заданы расширенные настройки стоимости, в метриках решения вы увидите следующие поля:

  • run_custom_cost — стоимость рейса по формуле для cost.run.
  • shift_custom_cost — стоимость смены по формуле для cost.shift. Выводится только в первом рейсе смены.
  • shift_total_custom_cost — общая стоимость смены. Включает в себя стоимость смены, рассчитанную по формуле, и стоимость всех входящих в смену рейсов. Выводится только в первом рейсе смены.
  • route_custom_cost — стоимость маршрута по формуле для cost.route. Выводится только в первом рейсе маршрута.
  • total_custom_cost — полная стоимость маршрута, включая стоимость маршрута, рассчитанную по формуле, и стоимость всех смен. Выводится только в первом рейсе маршрута, в остальных рейсах выводится 0.

Пример 1

В задаче используется следующая схема тарификации:

  • Базовая стоимость одного мультизаказа — 170 единиц.

  • Стоимость мультизаказа повышается на 20 единиц каждые 100 километров.

  • За смену курьер получает не менее 4000 единиц, даже если по заказам столько не набирается.

Такому тарифу соответствует следующая стоимость: 100 * duration_h + 8 * distance_km + max(4000, (170 + 20 * Floor(distance_km / 100)) * unique_stops).

В результате стоимость использования каждого автомобиля получается не менее 4000. Стоимость сверх оплаты смены (или выполненных заказов) формируется исходя из общего времени и длины маршрута.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Нужно спланировать маршрут при условии, что стоимость зависит от пробега и определяется по формуле:

<стоимость автомобиля> = максимум {<минимальная стоимость маршрута>, <количество точек на маршруте> * <стоимость доставки на точку>}

Минимальная стоимость маршрута и стоимость доставки на точку указаны в таблице:

Пробег

Стоимость одного мультизаказа (руб.)

Минимальная стоимость маршрута (руб.)

не более 150 км

510

6 000

не более 450 км

530

7 000

не более 750 км

550

8 500

свыше 750 км

570

11 000

Тогда при планировании стоимость автомобиля рассчитывается по формуле:

max(6000 + (distance_km > 150)*1000 + (distance_km > 450)*1500 + (distance_km > 750)*2500, stops*(510 + min(60, Ceil(max(0, distance_km - 150)/300)*20)))

Подробнее о формуле расчета
  • минимальная стоимость маршрута: 6000 + (distance_km > 150)*1000 + (distance_km > 450)*1500 + (distance_km > 750)*2500;
  • количество точек на маршруте — определяется с помощью параметра stops;
  • стоимость доставки на точку — определяется следующим образом. Минимальная стоимость мультизаказа — 510, максимально возможная прибавка к ней — 570 - 510 = 60. Важно, что стоимость мультизаказов увеличивается равномерно с шагом 20 на каждые 300 км пробега — это можно представить с помощью формулы Ceil(max(0, distance_km - 150)/300)*20. Тогда стоимость доставки на точку с учетом данных из таблицы равна 510 + min(60, Ceil(max(0, distance_km - 150)/300)*20)).

В итоге у машины 1 длина маршрута больше 150 км, количество остановок — 18 (есть 1 мультизаказ). Итоговая стоимость — 9540. У машины 2 длина маршрута не более 150 км, количество остановок — 21 (есть 1 мультизаказ). Итоговая стоимость — 10710.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Нужно спланировать маршрут так, чтобы минимизировать недозагрузку автомобиля. Для этого в формуле можно задать дополнительную стоимость автомобиля при условии его загрузки менее определенного предела. Например, при планировании автомобилей грузоподъемностью 3000 кг необходимо загружать их не менее чем на 80%. При этом предполагаем, что остальная стоимость (за час, за км, за факт использования) будет по умолчанию. Тогда стоимость автомобиля рассчитывается по формуле:

3000 + duration_h*100 + distance_km*8 + max(0, 2400 - utilization_kg) * 100

Подробнее о формуле расчета

3000, 100, 8 в первых трех слагаемых — значения по умолчанию стоимости за факт использования, за час и за километр соответственно. В формуле добавляется стоимость 100 единиц за каждый недогруженный килограмм от 2400: <номинальная грузоподъемность> * <минимальный порог утилизации> = 3000 * 80% = 2400.

В итоге алгоритм будет стремиться нагрузить все машины не менее чем на 80% (если это возможно).

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 4

Нужно спланировать маршрут при условии, что некоторые торговые сети начинают работу раньше. В задаче используется следующая схема тарификации:

  • Базовая cтоимость маршрута формируется исходя из затраченного времени и пройденного расстояния.

  • Желательно начинать маршруты пораньше, чтобы избежать утренних пробок. Для этого в формулу расчета стоимости добавляется штраф за выезд позднее 8 часов утра.

Такому тарифу соответствует следующая стоимость: 100 * duration_h + 8 * distance_km + 50 * (start_route_time_s > 28800)

В результате планирования все автомобили приезжают на склад до 8 утра.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 5

Нужно спланировать маршруты при условии, что в пределах города в одном автомобиле нельзя перевозить легкие и тяжелые заказы одновременно. В задаче планирования задана геозона City и всем заказам присвоены теги Light или Heavy в зависимости от веса заказа.

Таким условиям соответствует следующая стоимость:

(has_location(in_zone('City')) & has_location(has_tag('Light')) & has_location(has_tag('Heavy')))*100000000

Использовать несовместимые типы заказов в этом случае не получится, так как ограничение на совместимость действует только в пределах одной геозоны.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Расчет выплаты курьеру

Чтобы рассчитать, какую оплату получит курьер за выполнение маршрута, используйте поле payout. При планировании вы можете рассчитать выплаты одним выражением в поле vehicle.payout или использовать несколько выражений во вложенных полях:

  • payout.route —для маршрута;
  • payout.shift — для смены;
  • payout.run — для рейса.

В выражениях можно использовать те же ключевые слова и математические обозначения, что и для расчета стоимости маршрута для компании (поле vehicle.cost).

Примечание

Поле vehicle.payout не влияет на оптимизацию маршрута, оно рассчитывается уже после того, как задача планирования решена.

Если для курьера задано поле vehicle.payout, в метриках решения вы увидите следующие поля:

  • run_payout — выплата за рейс по формуле для payout.run.
  • shift_payout — выплата за смену по формуле для payout.shift. Выводится только в первом рейсе смены.
  • shift_total_payout — общая выплата за смену. Включает в себя выплату за смену, рассчитанную по формуле, и выплату за все входящие в смену рейсы. Выводится только в первом рейсе смены.
  • route_payout — выплата за маршрут по формуле для payout.route. Выводится только в первом рейсе маршрута.
  • total_payout — полная выплата за маршрут, включая выплату за маршрут, рассчитанную по формуле, и выплату за все смены. Выводится только в первом рейсе маршрута, в остальных рейсах выводится 0.

Если хотя бы для одного курьера задано поле payout, в результатах планирования также присутствует метрика total_payout — общий объем выплат курьерам.

Расчет выплат курьерам

Посмотреть видео

Пример 1

Два курьера развозят 40 заказов, каждый курьер делает по 2 рейса. Стоимость курьеров для компании задается выражением в поле cost. Для курьера 1 рассчитывается сумма выплаты за выполненный маршрут с помощью выражения в поле payout — эта сумма отображается в метриках первого рейса и составляет 5000 единиц. Для курьера 2 сумма выплаты не рассчитывается, поэтому общая сумма выплат total_payout также составляет 5000 единиц.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Два курьера развозят 40 заказов. Для курьера 1 задан расчет выплат: за факт выхода на смену курьер получает 3000 единиц, за каждый километр пути — 10 единиц, за каждый доставленный заказ — 50 единиц. Если за смену он доставит больше 10 заказов, ему начисляется бонус в 500 единиц. Для курьера 2 сумма выплаты не рассчитывается.

В результате планирования курьер 1 делает 2 рейса и доставляет 20 заказов. За каждый рейс ему начисляется run_payout — 1232 и 1053 единиц, за смену shift_total_payout — 2785 единиц (с учетом бонуса shift_payout в 500 единиц) и за маршрут route_payout — 3000 единиц. Всего курьеру начислено total_payout 5785 единиц.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Нужно спланировать маршрут при условии, что выплата курьеру зависит от зоны, в которой находится заказ. Для заказов используется следующая схема тарификации:

  • Стоимость доставки внутри МКАД — 150 единиц.
  • Стоимость доставки за пределами МКАД — 250 единиц.

Выплата курьеру определяется как суммарная стоимость доставки всех заказов в маршруте:

<выплата курьеру> = 150 * <количество заказов внутри МКАД> + 250 * <количество заказов за пределами МКАД>

При планировании используются публичные геозоны public_inside_ttk (зона внутри ТТК) и public_inside_mkad (зона от ТТК до МКАД). Тогда выплата рассчитывается по формуле:

150 * order_count(in_zone('public_inside_ttk') | in_zone('public_inside_mkad')) + 250 * order_count(!in_zone('public_inside_ttk') & !in_zone('public_inside_mkad'))

Для 7 заказов внутри МКАД и 3 заказов за пределами МКАД выплата составляет 1050 + 750 = 1800 единиц.

Запрос API (JSON)Ответ APIОткрыть на карте

Теги автомобиля

При определении автомобиля или курьера в запросе к Маршрутизации можно назначить ему правила совместимости (или теги) с заказами.

Правила совместимости могут потребоваться при наличии у автомобиля специального оборудования, которое необходимо для выполнения того или иного заказа — например, изотермического фургона для перевозки продуктов питания.

Правила совместимости автомобилей и заказов (теги автомобиля) задаются в следующих полях:

  • Поле vehicle.tags — свойства автомобиля, которые частично могут совпадать со свойствами, требуемыми заказом.

  • Поле vehicle.excluded_tags — свойства автомобиля, которые не должны совпадать со свойствами, требуемыми заказом.

Для определения тегов заказов используется поле запроса location.required_tags.

Внимание

Теги заказов определяют требуемые заказом характеристики автомобиля, а теги автомобилей определяют фактические правила совместимости того или иного автомобиля с различными заказами.

Определение тегов автомобиля возможно как в виде строк, так и в виде регулярных выражений. В строках теги могут перечисляться через запятую. В этом случае автомобиль сможет доставить заказ, если хотя бы один из перечисленных тегов автомобиля совпадает с тегом заказа или если у заказа нет тегов. Регулярные выражения — это способ описать более сложную логику и правила совместимости между автомобилями и заказами.

В Яндекс Маршрутизации используется синтаксис регулярных выражений POSIX Extended. Для тестирования регулярных выражений можно воспользоваться сервисом Regex101.

Рассмотрим, как можно применять теги на реальных примерах.

Пример 1

Рассмотрим сценарий, в котором транспортная компания доставляет продукты питания и напитки мелким оптом. Некоторые из продуктов питания необходимо доставлять строго в изотермических грузовиках. При этом все напитки и часть товаров из группы продуктов питания могут быть доставлены без холодильников. В дополнение часть клиентов может принять груз, только если автомобили оборудованы гидробортом.

Для определения таких ограничений заказов укажем в поле location.required_tags следующие теги:

  • TAIL_LIFT — для заказов, которые могут быть разгружены, только если автомобиль оборудован гидробортом.

  • ISOTHERMAL_TRUCK — для заказов, содержащих товары, которые требуют перевозки с соблюдением температуры.

  • NORMAL_TRUCK — для заказов, не имеющих товаров со специальными условиями перевозки.

Для определения возможностей автомобилей используем следующие теги в поле vehicle.tags:

  • TAIL_LIFT — для автомобилей, оснащенных гидробортом.

  • ISOTHERMAL_TRUCK — для автомобилей, оснащенных изотермическим фургоном.

  • NORMAL_TRUCK — для обычных автомобилей без изотермического фургона.

Примечание

Автомобиль при этом может иметь как один, так и несколько тегов, или не иметь их вообще, в зависимости от его реальной конфигурации. Это же правило касается и тегов заказов.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Рассмотрим сценарий, в котором в некоторых заказах есть ограничение по высоте кузова для автомобиля из-за разной высоты зон разгрузки.

Например, есть заказы, у которых ограничение по высоте кузова составляет 2 метра, 2,3 метра и 2,5 метра. В таком случае у них должны быть соответствующие теги: Max_200, Max_230, Max_250.

На машинах теги необходимо проставлять более сложным образом, поскольку машина высотой до 2 метров может доставить любые заказы, а машина высотой 2,8 метра – далеко не все заказы. То есть если использовать только tags, то при высоте машины:

  • до 2 метров — в поле vehicle.tags будут все значения Max_200, Max_230, Max_250;

  • от 2 до 2,3 метра — в поле vehicle.tagsбудут значения Max_230, Max_250;

  • от 2,3 до 2,5 — в поле vehicle.tags будет значение Max_250;

  • более 2,5 метров — поле vehicle.tags будет пустым.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Рассмотрим сценарий, в котором в некоторых заказах есть ограничение по заезду автомобилей определенной грузоподъемности (при этом действует условие ИЛИ, когда подходит любая из соответствующих машин).

Например, есть машины с разной грузоподъемностью: 1, 3, 9 и 15 тонн. Зафиксируем эти характеристики с помощью тегов vehicle.tags. Поскольку при описании заказов эти теги придется комбинировать, зададим их с помощью регулярных выражений: .*1TON.*, .*3TON.*, .*9TON.* и .*15TON.* (.* — означает «любая подстрока»).

Для некоторых заказов ограничение по грузоподъемности автомобиля составляет от 1 до 15 тонн, от 3 до 9 тонн и от 1 до 3 тонн. Это ограничение задается для заказа строкой с регулярным выражением, которое включает теги всех подходящих машин. То есть в поле location.required_tags будут следующие регулярные выражения при требуемой грузоподъемности:

  • от 1 до 15 тонн — ##1TON##3TON##9TON##15TON##;
  • от 3 до 9 тонн — ##3TON##9TON##;
  • от 1 до 3 тонн — ##1TON##3TON##.

Примечание

В примере 2 теги заказа задаются простым перечислением, так как у автомобиля должны быть все перечисленные теги (условие И). В примере 3 необходимо, чтобы у автомобиля был хотя бы один из тегов заказа (условие ИЛИ), это можно реализовать с помощью регулярных выражений или через создание отдельных тегов для каждого возможного сочетания из условий ИЛИ.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Опциональные теги

Иногда при планировании нужно учитывать, какие автомобили желательно использовать (или не использовать) для определенных заказов. Например, доставку VIP-заказов лучше поручать специально обученным курьерам.

Для таких необязательных требований предназначены опциональные теги, которые перечисляются в поле location.optional_tags. Допускается нарушение заданных предпочтений, если их нельзя удовлетворить (например, из-за ограничений по весу или времени доставки). Этим опциональные теги отличаются от требуемых характеристик ТС.

Примечание

Если автомобили желательно (но не обязательно) использовать на определенной территории, задайте для них опциональные геозоны.

Приоритет предпочтений регулируется с помощью веса тега location.optional_tags.value. Его значение может быть как положительным, так и отрицательным. При планировании опциональный тег сравнивается с тегами машины, на которой выполняется заказ. Если тег из location.optional_tags совпал с тегом ТС в списке:

  • vehicle.tags, то value вычитается из стоимости маршрута;

  • vehicle.excluded_tags, то value прибавляется к стоимости маршрута.

Значение, которое опциональные теги добавляют к стоимости маршрута, возвращается в поле result.routes.metrics.total_optional_tags_cost (может быть отрицательным).

Пример

Нужно доставить 10 заказов, некоторым из них заданы следующие опциональные теги:

  • vip — 6 заказов, вес тега на разных точках варьируется от 100 до 350;
  • morning — 3 заказа, вес тега на всех точках одинаковый, 500.

У одного из автомобилей теги vip и morning определены в поле vehicle.excluded_tags. Таким образом указано, что этому курьеру лучше не поручать заказы с тегом vip, а также заказы с тегом morning из-за позднего времени начала маршрута.

В итоге требования в большинстве случаев нарушены не были: пять из шести vip-заказов доставляет курьер без ограничения по тегу vip, по тегу morning нарушений нет.

Но один vip-заказ был запланирован на автомобиль с тегом vip в excluded_tags — из-за ограничения по вместимости. В поле total_optional_tags_cost этого маршрута возвращается значение 100: использование «нежелательного» автомобиля увеличило стоимость на 100 единиц. Предпочтение было нарушено для заказа c наименьшим весом location.optional_tags.value.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Зарезервированные теги

Внимание

С 1 ноября 2024 года использование зарезервированных тегов при планировании не будет поддерживаться. Вместо них можно использовать публичные геозоны.

Для проезда по Москве грузовикам нужны специальные пропуска:

  • для проезда внутрь МКАД;

  • для проезда внутрь ТТК.

Эту особенность необходимо учитывать при составлении задачи планирования, чтобы грузовики без пропусков не получали маршруты в зоны, куда им нельзя проехать.

  1. Для определения разрешений используйте теги автомобиля:

    • vehicle.tags = inside_mkad — для отметки грузовика с пропуском внутрь МКАД, но без въезда в ТТК;

    • vehicle.tags = inside_ttk, inside_mkad — для отметки грузовика с пропуском внутрь МКАД и внутрь ТТК;

    • vehicle.tags = inside_ttk — для отметки грузовика, который будет брать заказы только внутри ТТК.

  2. Алгоритм при загрузке присвоит теги заказам:

    • location.required_tags = inside_ttk — точкам внутри TTK;

    • location.required_tags = inside_mkad — точкам между МКАД и ТТК.

Если вы проставите теги заказам самостоятельно, то алгоритм:

  • не будет их корректировать;

  • не присвоит использованный вами тег другим заказам, даже если они ему соответствуют.

Примечание

Алгоритм не присвоит заказам теги, которых нет ни у одного автомобиля.

Например, для автомобиля указан тег vehicle.tags = inside_ttk. Тогда тег inside_mkad для заказов не будет добавлен, даже если точка доставки заказа находится между МКАД и ТТК.

Примеры бизнес-кейсов см. в разделе Планирование маршрутов по зонам.

Несовместимость заказов в автомобиле

Заказы могут иметь несовместимые типы, они задаются с помощью параметров:

  • options.incompatible_load_types — задает несовместимость заказов для всех автомобилей одинаково. Подробнее см. в разделе Несовместимость заказов.

  • vehicle.incompatible_load_types — задает несовместимость заказов для конкретного автомобиля, то есть позволяет учесть особенности автомобиля.

  • vehicle.onboard_incompatible_load_types — при значении false (по умолчанию) несовместимость заказов действует в течение всего рейса; при значении true — только пока заказы находятся в автомобиле.

Примечание

Параметр vehicle.incompatible_load_types имеет более высокий приоритет и для данного автомобиля полностью переопределяет параметры options.incompatible_load_types.

Например, для перевозки молока и мороженого требуются разные температурные режимы. Если у автомобиля один отсек, он будет перевозить либо молоко, либо мороженое. Если же у автомобиля два отсека с разными температурными режимами, он может перевозить молоко и мороженое одновременно, в разных отсеках. В этом случае достаточно указать несовместимость заказов vehicle.incompatible_load_types для автомобилей с одним отсеком. Для автомобилей с двумя отсеками этот параметр не нужен, и для заказов в целом несовместимые типы options.incompatible_load_types также указывать не нужно.

Если несовместимость заказов вызвана не характеристиками автомобиля, а иными причинами, используйте параметр vehicle.onboard_incompatible_load_types = true. Например, если нельзя одновременно перевозить заказы конкурентов, тогда курьер будет забирать и развозить заказы каждой фирмы по отдельности без заезда на склад. Это позволит уменьшить пробег и время маршрута.

Пример 1

Доставка состоит из 4 адресов со следующими типами заказов:

  • заказ 1 (id = 1) — flowers;

  • заказ 2 (id = 2) — flowers;

  • заказ 3 (id = 3) — flowers, sweets;

  • заказ 4 (id = 4) — flowers, ice-cream.

При этом flowers и sweets несовместимы для доставки в одном автомобиле. Дополнительно, в автомобиле 2 запрещается одновременная доставка flowers и ice-cream, но разрешена доставка flowers и sweets. Тогда решение будет содержать доставку заказов 2 и 4 в первом автомобиле и заказов 1 и 3 во втором автомобиле.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2.1

Нужно забрать и доставить 3 заказа разных компаний. Заказы 1 и 2, 2 и 3 нельзя доставлять вместе, так как они принадлежат компаниям-конкурентам.

В результате планирования курьер забирает и развозит заказы 1 и 3, затем возвращается на склад, чтобы в новом рейсе загрузить и доставить заказ 2.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2.2

То же, что и в примере 2.1, но vehicle.onboard_incompatible_load_types = true.

В результате планирования курьер забирает и доставляет заказ 2, а затем без заезда на склад забирает и развозит заказы 1 и 3. Пробег и время маршрута уменьшились.

Запрос API (JSON)Ответ APIОткрыть на карте

Геозоны

Для автомобилей могут быть заданы ограничения по зонам доставки. Зоны, в которые транспортное средство может доставлять заказы, задаются на листе Vehicles в поле Разрешенные геозоны (vehicles.allowed_zones в API):

  • автомобиль может выполнять заказы в любой зоне, указанной в этом поле;

  • если зоны доступности не заданы, то курьер может выполнять заказы без ограничений;

  • заказ не может быть выполнен, если для всех курьеров указаны зоны доступности, а точка заказа не попадает ни в одну из них.

Зоны, запрещенные для доставки, задаются в поле Запрещенные геозоны (vehicle.forbidden_zones в API). Курьер не может доставлять заказы ни в одну из зон, указанных в этом поле.

Примечание

Если заказ расположен в области пересечения разрешенной и запрещенной зон, то он не может быть доставлен — значения в поле Запрещенные геозоны (forbidden_zones) имеют более высокий приоритет, чем в поле Разрешенные геозоны (allowed_zones).

Если зоны запрещены для посещения всем курьерам, используйте глобальную опцию options.avoid_zones. В зонах из vehicle.forbidden_zones курьер не может выполнять заказы, но может проезжать через них. В зоны из options.avoid_zones курьеры не могут даже заезжать. Подробнее см. Исключенные зоны.

Для проезда по Москве грузовикам нужны специальные пропуска:

  • для проезда внутрь МКАД;

  • для проезда внутрь ТТК.

Эту особенность необходимо учитывать при составлении задачи планирования, чтобы грузовики без пропусков не получали маршруты в зоны, куда им нельзя проехать.

Чтобы задать ограничение по доставке, используйте следующие публичные геозоны:

  • public_inside_ttk — территория внутри ТТК;
  • public_inside_mkad — территория от МКАД до ТТК (не включает территорию внутри ТТК);

Укажите идентификатор публичной геозоны как значение поля Разрешенные геозоны или Запрещенные геозоны.

При распределении заказов учитывается несовместимость геозон — как заданная глобальной опцией, так и определенная для отдельных курьеров. Также при планировании можно отменить все ограничения, связанные с геозонами.

Пример

В примере 4 заказа и 2 автомобиля, в интерфейсе заданы 4 геозоны. Принадлежность заказов к геозонам определяется автоматически по координатам:

  • Заказ 1 — одновременно в зонах zone1 и zone2;

  • Заказ 2 — в зоне zone1;

  • Заказ 3 — одновременно в зонах zone2 и zone3;

  • Заказ 4 — в зоне zone4.

Определена доступность геозон для автомобилей:

Логин курьера

Разрешенные геозоны (allowed_zones)

Запрещенные геозоны (forbidden_zones)

Автомобиль 1

zone1, zone2

zone3

Автомобиль 2

Зоны не определены

zone2

В итоге Автомобиль 1 развозит Заказы 1 и 2, Автомобиль 2 — Заказ 4. А Заказ 3 остался нераспределенным, потому что его адрес находится в зонах, запрещенных для обоих автомобилей.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Опциональные геозоны

Для распределения заказов между автомобилями можно использовать опциональные геозоны, за посещение которых начисляется бонус или штраф. Для каждого автомобиля можно назначить одну или несколько таких геозон.

Опциональные геозоны — это нежесткое ограничение. С их помощью можно задать предпочтительные для посещения зоны (приоритетные и неприоритетные).

Опциональные геозоны задаются с помощью массива vehicle.optional_zones:

  • optional_zones.N.zone — название геозоны;
  • optional_zones.N.value — если значение параметра больше 0, то автомобиль получает бонус за посещение указанной геозоны (значение этого параметра вычитается из стоимости маршрута), а если меньше 0 — штраф (значение прибавляется к стоимости маршрута).

Приоритет геозон

Посмотреть видео

Пример 1

Нужно доставить 10 заказов двумя автомобилями. Для одного автомобиля задана опциональная геозона South, а для другого North. За посещение этих геозон назначен бонус 1000 единиц. В результате один автомобиль развозит заказы на юге, а второй — на севере. Заказ 5 стал исключением — он относится к зоне South, но был доставлен автомобилем Courier north.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

4 курьера должны доставить 27 заказов. Для курьеров город поделен на 4 опциональных геозоны: Northwest, Northeast, Southwest и Southeast. Для каждого курьера задана одна приоритетная зона, за посещение которой он получает бонус, две неприоритетных зоны и зона, за посещение которой будет начислен штраф. В результате планирования курьеры доставляют заказы в своих приоритетных зонах. Исключениями стали заказы 18, 20 и 23 из-за ограничения по вместимости автомобилей.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Несовместимые геозоны

Чтобы в один рейс курьера не попадали заказы, которые относятся к разным зонам доставки, можно определить несовместимость геозон.

Список таких зон можно задать не только для всего решения, но и для конкретного курьера — параметром vehicles.incompatible_zones. Несовместимые зоны, определенные для курьера, имеют приоритет над зонами, определенными глобально. Чтобы на курьера не распространялось глобальное ограничение options.incompatible_zones, задайте для него в поле vehicles.incompatible_zones пустой список.

Внимание

При планировании через Excel, чтобы на курьера не распространялось глобальное ограничение несовместимости геозон, проставьте для него в ячейках incompatible_zones.N пробел (соответствует пустому списку).

Пример

Каждый из трех курьеров должен доставить по 4 заказа в разные районы города: северо-западный, юго-западный, северо-восточный и юго-восточный. Эти районы заданы при планировании геозонами: Northwest, Southwest, Northeast, Southeast.

Глобально определена несовместимость геозон: южные зоны (Southwest и Southeast) несовместимы с северными (Northwest и Northeast). Для двух курьеров также задан параметр vehicles.incompatible_zones: у первого курьера он содержит пустой список, а для второго определено, что западные зоны (Northwest и Southwest) несовместимы с восточными (Northeast и Southeast).

В результате планирования:

  • на первого курьера Courier 1 глобальное ограничение несовместимости не распространяется и у него в один рейс попадают все 4 заказа из разных районов;
  • для второго курьера Courier 2 работают ограничения по несовместимости зон, заданные для него в параметре vehicles.incompatible_zones: в один рейс попадают заказы в восточные зоны, а в другой — в западные;
  • на третьего курьера Courier 3 действуют глобальные ограничения: по разным рейсам разнесены заказы в южные зоны и в северные.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Способ передвижения

При построении маршрутов по умолчанию предполагается, что курьер использует для доставки легковой автомобиль (грузоподъемность меньше 2,5 тонн). Доставку грузов пешком, на грузовом автомобиле или с помощью общественного транспорта можно отразить с помощью параметра vehicle.routing_mode. Если все курьеры выполняют доставку одним способом, можно использовать опцию маршрутизации options.routing_mode.

Примечание

Параметр vehicle.routing_mode имеет более высокий приоритет, чем options.routing_mode.

Возможные значения:

  • driving — способ по умолчанию, маршрутизация для автомобилей с грузоподъемностью меньше 2,5 тонн;

  • truck — маршрутизация для грузовых автомобилей, по умолчанию — с грузоподъемностью от 2,5 тонн. Дополнительные параметры можно указать в характеристиках транспортного средства. При планировании с использованием этого способа передвижения учитываются дорожные знаки, ограничивающие движение грузовых автомобилей, в том числе грузовой каркас для Москвы;

  • walking — маршрут с пешеходным профилем. В маршруте используются только те дороги, по которым может ходить пешеход;

  • transit — маршрут с использованием общественного транспорта и перемещением пешком от остановки до точки доставки.

Для курьеров, которые передвигаются на велосипедах или самокатах, указывайте способ передвижения пешком routing_mode = walking и используйте коэффициент корректировки скорости travel_time_multiplier. Для каждого курьера стоит вывести индивидуальный коэффициент корректировки. Например, с помощью отчета План-факт можно сравнить фактическое время в пути для курьера на велосипеде или самокате с плановым временем в пути, рассчитанным для передвижения пешком.

Пример 1

В примере ниже используется способ передвижения transit для всех курьеров. В результате курьеры выполняют доставку на общественном транспорте и заказы распределены оптимально для них.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Примечание

В построенных маршрутах пробег указан только для расстояний, которые курьер ходит пешком. Расстояния, покрытые в общественном транспорте, учитываются для оптимизации, но не указываются в метриках.

Пример 2

В примере ниже используется способ передвижения transit для одного курьера, и driving для другого курьера. Заказы распределены между курьерами так, чтобы автомобиль выполнял доставку в точки, более удаленные от остановок общественного транспорта или друг от друга.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Режим работы курьера

По умолчанию сервис планирует маршрут только с остановками, которые необходимы для доставки грузов. Однако часто курьеры не работают без остановок: им нужно делать перерыв на обед, и это надо учитывать при построении маршрутов. Также на дальних рейсах есть требование соблюдать режим труда и отдыха, когда водитель обязан останавливаться после определенного времени движения.

Чтобы управлять режимом работы курьеров, используйте объект vechicle.rest_schedule.breaks. Вы можете описать простые или сложные схемы перерывов на отдых, техническое обслуживание и другие действия.

Пресеты перерывов

Вы можете задать режим работы курьера с помощью параметра vehicles.rest_schedule_preset, который содержит готовый набор настроек:

  • не позже чем через 4,5 часа работы курьера будет установлен 45-минутный перерыв;

  • на длительность смены без учета перерывов будут наложены ограничения:

    • мягкое — 9 часов;

    • жесткое — 10 часов.

Возможные значения параметра rest_schedule_preset:

  • rest_schedule_preset = private_transport — перерыв можно разбить на две части: 15 и 30 минут;

  • rest_schedule_preset = public_transport — перерыв можно разбить на несколько частей продолжительностью не меньше 10 минут.

Перерыв в маршруте будет разбиваться на части при выполнении следующих условий:

  • если между заказами нет интервала, в который можно полностью поместить перерыв;

  • между заказами есть ожидания, куда могут поместиться перерывы.

Также вы можете запретить разбивать перерывы на части. Для этого используйте опцию can_split_preset_work_breaks = false (по умолчанию can_split_preset_work_breaks = true).

Пример 1

Для курьера запланирован режим работы rest_schedule_preset = private_transport. В него входит один перерыв, который можно разбить на две части. Между заказами есть интервал, в который полностью помещается перерыв. В результате запланирован один перерыв продолжительностью 45 минут.

Запрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Для курьера запланирован режим работы rest_schedule_preset = public_transport. В него входит один перерыв, который можно разбить на несколько частей. Между заказами нет интервала, куда можно полностью поместить перерыв. Также есть ожидание, в которое может поместиться часть перерыва. В результате запланировано 2 перерыва: 32 и 12 минут.

Запрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Для курьера запланирован режим работы rest_schedule_preset = public_transport. У курьера 14 заказов. На длительность смены наложено жесткое ограничение: 10 часов. В результате один заказ остался невыполненным, так как для его доставки курьеру пришлось бы работать больше 10 часов.

Запрос API (JSON)Ответ APIОткрыть на карте

Шаблоны расписаний

Вы можете описать перерывы отдельно для каждого курьера или создать шаблоны для нескольких курьеров. В том числе, можно совмещать индивидуальные расписания и шаблонные.

Чтобы создать шаблон, добавьте в options параметр template_rest_schedules и укажите в нем массив расписаний: [{"id": string, "breaks": [...]}].

Чтобы использовать шаблон, добавьте в vehicles параметр rest_schedule_id и укажите в нем id шаблона расписания из options.

Продолжительность перерыва

Продолжительность перерыва устанавливается параметром rest_duration_s, обязательным для каждого перерыва.

Параметр

Значение

Пример

rest_duration_s

Продолжительность перерыва в секундах.

"rest_duration_s": 600

Перерыв должен длиться 10 минут (600 секунд).

Условия начала перерыва

Начало перерыва обозначается диапазоном времени (от и до). Условия можно задать несколькими способами, которые рассмотрены подробнее в таблице ниже.

Параметр

Значение

Пример

work_time_range_from_start

Время работы от начала маршрута. Включает в себя: время движения, ожидания и сервисное время на заказах и складах.

Наличие и продолжительность других перерывов не имеют значения.

"work_time_range_from_start": "01:00:00-03:00:00"

Начать перерыв не раньше, чем через 1 час, и не позже, чем через 3 часа после начала маршрута.

work_time_range_till_rest

Время работы от последнего перерыва (или от начала маршрута, если это первый перерыв). Включает в себя: время движения, ожидания и сервисное время на заказах и складах.

"work_time_range_till_rest": "02:00:00-04:00:00"

Начать перерыв не раньше, чем через 2 часа, и не позже, чем через 4 часа после начала смены (включая приезд на склад, сервисное время, периоды движения и ожидания).

travel_time_range

Время движения и ожидания от начала маршрута. Сервисное время при этом не учитывается.

"travel_time_range": "01:00:00-03:00:00"

Начать перерыв не раньше, чем через 1 час, и не позже, чем через 3 часа после начала маршрута с учетом периодов движения и ожидания, но без учета сервисного времени на заказах и складах.

continuous_travel_time_range

Время движения и ожидания от момента завершения предыдущего заказа. Сервисное время при этом не учитывается.

"continuous_travel_time_range": "02:00:00-03:00:00"

Начать перерыв не раньше, чем через 2 часа, и не позже, чем через 3 часа непрерывного движения.

driving_time_range

Время движения от начала маршрута. Время ожидания и сервисное время не учитывается.

"driving_time_range": "01:00:00-03:00:00"

Начать перерыв не раньше, чем через 1 час, и не позже, чем через 3 часа от начала движения.

exact_time_range

Время начала перерыва. Перерыв не может быть повторяющимся.

Время начала работы, наличие и продолжительность других перерывов не имеют значения.

Перерыв не начнется, если маршрут закончится раньше времени начала перерыва.

"exact_time_range": "17:00:00-20:00:00"

Начать перерыв в диапазоне с 17:00 до 20:00.

Если перерывов несколько, в каждом указывается диапазон времени работы после завершения предыдущего перерыва. Например, если в первом перерыве задано 04:00–05:00, а во втором — 02:00–03:00, то первый перерыв должен начаться между 4 и 5 часами после начала работы, а второй — между 2 и 3 часами работы после завершения первого перерыва.

Условия планирования перерыва

Вы можете указать дополнительные параметры: сделать перерыв обязательным или задать минимальное время работы для начала перерыва.

Параметр

Значение

Пример

necessary_route_duration_s

Время с начала маршрута, после которого перерыв обязателен. Задается в секундах.

"necessary_route_duration_s": 14400

Обязательно начать перерыв, когда с начала маршрута пройдет 4 часа (14400 секунд).

route_duration_s

Параметр устанавливает минимальное время работы, при котором перерыв должен быть запланирован. Если общее время работы меньше, то перерыв не будет запланирован. Задается в секундах.

"route_duration_s": 14400

Начать перерыв, только если маршрут длится как минимум 4 часа (14400 секунд).

Условия объединения перерывов

Параметр

Значение

Пример

before_first_location

Возможность объединения перерыва с другими перерывами до первого заказа. Перерыв можно объединять только с теми перерывами, типы которых указаны в merge_with_types.

"before_first_location": true

Перерыв будет объединен с последним перерывом перед первой локацией, где тип перерыва указан в  merge_with_types. Если такого перерыва нет, то этот перерыв будет прямо перед первой локацией. Все такие перерывы должны быть в отдельной цепочке.

after_last_location

Возможность объединения перерыва с другими перерывами после последнего заказа. Перерыв можно объединять только с теми перерывами, типы которых указаны в merge_with_types.

"after_last_location": true

Перерыв будет объединен с первым перерывом после последней локации, где тип перерыва указан в merge_with_types. Если такого перерыва нет, то этот перерыв будет сразу после последней локации. Все такие перерывы должны быть в отдельной цепочке.

type

Тип перерыва.

"type": "Обед"

Тип этого перерыва — «обед».

merge_with_types

Параметр устанавливает, с какими типами перерывов можно объединить указанный перерыв. Его можно использовать только в сочетании с  after_last_location или before_first_location.

"merge_with_types": ["Обед", "Сон"]

Этот перерыв можно объединить с перерывом на обед или сон.

Разделяемые перерывы

При необходимости вы можете разделить перерыв на несколько частей. Например, если между заказами перерыв целиком не помещается. Для этого в расписании у перерыва breaks укажите параметр can_be_split = true.

Вы можете указать дополнительные параметры для разделяемого перерыва:

Параметр

Значение

Пример

max_split_parts

Параметр определяет, сколько у перерыва будет частей. По умолчанию это 2 части.

"max_split_parts": 5

Перерыв можно разбить на 5 частей.

min_split_part_duration_s

Минимальное время, на которое можно разбить часть перерыва. Задается в секундах. По умолчанию это 10 минут.

"min_split_part_duration_s": 1200

Часть перерыва можно разбить минимум на 20 минут (1200 секунд).

min_first_split_part_duration_s

Параметр устанавливает минимальное время для первой части перерыва. Задается в секундах. По умолчанию это 1/3 от общей длительности перерыва.

"min_first_split_part_duration_s": 1800

Первая часть перерыва должна длиться не меньше 30 минут. (1800 секунд).

min_last_split_part_duration_s

Минимальное время для последней части перерыва. Задается в секундах. По умолчанию это 2/3 от общей длительности перерыва.

"min_last_split_part_duration_s": 2400

Последняя часть перерыва должна длиться не меньше 40 минут (2400 секунд).

Пример

Для курьера предусмотрен 1 перерыв продолжительностью 2 часа "rest_duration_s": 7200. Для первых трех заказов установлены узкие временные окна, поэтому время ожидания перед заказами можно заполнить перерывами. Так как между заказами перерыв целиком не помещается, он разбивается на 3 части.

Запрос API (JSON)Ответ APIОткрыть на карте

Перерывы во время обслуживания заказов

Параметр

Значение

Пример

can_rest_during_service

Параметр перерыва. Определяет, может ли этот перерыв пересекаться с сервисным временем заказа или склада. По умолчанию true.

"breaks": [
  {
    "can_rest_during_service": true,
    "rest_duration_s": 3000,
    "work_time_range_from_start": "1:30 - 2:00"
  },
  ...
]    

can_have_rest_during_service

Параметр заказа или склада. Определяет, может ли перерыв пересекаться с сервисным временем этого заказа или склада. По умолчанию true.

"locations": [
  {
    "id": 123,
    "can_have_rest_during_service": true,    
    "service_duration_s": 600,  
    ...
  }
]

По умолчанию перерывы могут пересекаться с сервисным временем заказа или склада. В маршруте такие перерывы указываются перед заказом или складом. Время начала arrival_time_s и окончания departure_time_s перерыва совпадают с arrival_time_s и departure_time_s заказа или склада. Внутри этого общего интервала длительность сервисного времени определяется параметром service_duration_s. В ответе для такого заказа или склада добавляется поле is_after_service_work_break = true, означающее, что обслуживание начинается после перерыва.

При can_rest_during_service = true перерыв может быть спланирован как первая точка в смене. Для обычных перерывов, не пересекающихся с сервисным временем, такое невозможно.

Чтобы запретить пересечение перерыва с сервисным временем, нужно для заказа или склада указать can_have_rest_during_service = false, а для перерыва — can_rest_during_service = false.

Пример 1

Перерыв длительностью 50 минут должен быть запланирован через 1,5 часа после начала маршрута. В маршруте 2 заказа, у которых время обслуживания 1 час и параметр can_have_rest_during_service = true. В результате перерыв пересекается со временем обслуживания первого заказа, на который курьер приезжает через 1 час 8 минут после начала маршрута и уезжает через 2 часа 20 минут.

Запрос API (JSON)Ответ APIОткрыть на карте

Пример 2

То же, что в примере 1, но у заказов параметр can_have_rest_during_service = false. В результате перерыв запланирован в точке первого заказа, но перед обслуживанием заказа, раньше времени — всего через 1 час 9 минут после начала маршрута.

Запрос API (JSON)Ответ APIОткрыть на карте

Место перерыва

Параметр

Значение

Пример

at_rest_place

Возможность отдохнуть в точке с типом rest_place. Если возможность включена, либо все перерывы должны быть в таких точках, либо все перерывы — вне таких точек.

"at_rest_place": true

Все перерывы будут проходить точках с типом location.type, равным rest_place.

Курьер не может посещать места для перерывов, которые находятся в запрещенных для него геозонах.

Вы можете задавать требования к заезду в место перерыва с типом rest_place с помощью параметра incompatible_load_types, см. Несовместимость заказов. Например, курьер перевозит заказ с типом load_type = ice-cream, а у точки rest_place указан тип load_type = no-refrigerator. Чтобы курьер не мог заехать в такое место для перерыва, на листе Incompatible_load_types укажите, что тип ice-cream несовместим с no-refrigerator.

Цепочки перерывов

Расписание rest_schedule может содержать множество независимых цепочек перерывов breaks. Каждая цепочка может содержать множество перерывов с особенными условиями. Наступление перерыва в каждой цепочке зависит только от построенного маршрута и не зависит от перерывов в других цепочках.

Пример

Пояснение

Возможность задать

1 цепочка: отдыхать 15 минут через каждые 3 часа движения.

2 цепочка: отдыхать 6 часов через 8 часов после начала смены.

Перерывы в цепочке 2 зависят только от начала смены и не зависят от расписания движения и отдыха в цепочке 1.

1 цепочка: отдыхать 15 минут через каждые 3 часа движения.

2 цепочка: отдыхать 6 часов через каждые 8 часов движения.

Начало перерыва в цепочке 2 зависит от расписания движения и отдыха в цепочке 1.

Порядок цепочек не имеет значения, но перерывы в одной цепочке необходимо указывать последовательно.

Если маршрут заканчивается до наступления остановки (например, маршрут выполнен за 3 часа, а остановка запланирована через 4), то все невыполненные остановки сбрасываются.

Пример

Маршрут построен с получасовыми перерывами на отдых через 4–4,5 часа работы, а через 15 часов после начала маршрута запланирован перерыв на сон. В результате алгоритм запланировал перерыв на сон через 1,5 часа после перерыва на отдых.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Штрафы

В некоторых случаях сервис может планировать маршруты с нарушением окна отдыха. Чтобы начислять штрафы за эти нарушения, используйте поля penalty.late и penalty.early. Если штраф выше, чем полученная от нарушения окна экономия, то маршрут будет запланирован без нарушений.

Параметр

Значение

Пример

penalty.early.fixed

Штраф за факт раннего начала перерыва.

"penalty": {"early": {"fixed": 1000}}

Устанавливает штраф 1000 за факт раннего перерыва.

penalty.early.minute

Штраф за каждую минуту раннего перерыва.

"penalty": {"early": {"minute": 17}}

Устанавливает штраф 17 за каждую минуту раннего перерыва.

penalty.late.fixed

Штраф за факт позднего перерыва.

"penalty": {"late": {"fixed": 1000}}

Устанавливает штраф 1000 за факт позднего перерыва.

penalty.late.minute

Штраф за каждую минуту позднего перерыва.

"penalty": {"late": {"minute": 17}}

Устанавливает штраф 17 за каждую минуту позднего перерыва.

Условия повтора

Параметр

Значение

Пример

repeatable

Параметр указывает, что перерыв нужно повторять. Можно использовать только для последнего в цепочке перерыва.

"repeatable": true

Перерыв будет повторяться до конца смены.

Пример 1

В этом примере построен маршрут с перерывом на обед через 4–5 часов работы. В результате алгоритм планирует остановку на обед для выполняющего доставку курьера.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

В этом примере построен маршрут между Москвой и Санкт-Петербургом с первым перерывом через 4–4,5 часа, и затем с перерывами каждые 2 часа. Алгоритм выделил два перерыва.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Для двух курьеров задан перерыв с условием work_time_range_from_start через 3-4 часа после начала работы, но только если общая продолжительность route_duration_s минимум 6 часов. Первый курьер заканчивает работу за 5 часов, поэтому работает без отдыха. Второй курьер работает более 6 часов, поэтому получает один перерыв.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 4

Курьер везет заказы в соседний город и нуждается в периодическом отдыхе. С помощью условия повтора repeatable заданы перерывы через каждые 60-80 минут маршрута (travel_time_range). В результате алгоритм запланировал два перерыва.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 5

Как в примере 4, но маршрут длится несколько дней, и перерывы задаются на сон каждые 12 часов:

  • используется условие повтора repeatable;

  • минимальная и максимальная продолжительность маршрута до отдыха travel_time_range: "12:00-12:00".

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 6

Задаются перерывы длительностью 10 минут на каждые 55-60 минут непрерывного движения continuous_travel_time_range. В результате запланирован перерыв на единственном интервале между точками, где время движения более 55 минут.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 7

Для курьеров запланировано два перерыва с условием начала перерыва work_time_range_till_rest через 2-3 часа от последнего перерыва или от начала работы, если это первый перерыв.

  • первый перерыв — 20 минут.

  • второй перерыв — 30 минут.

Первый курьер заканчивает работу раньше и получает только первый перерыв. Второй курьер работает дольше и получает оба перерыва.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 8

Для двух курьеров запланировано 19 заказов. Первый курьер должен отдыхать каждые 2-3 часа работы, второй — каждые 3-4 часа. Для них указано общее место для отдыха — точка с типом rest_place.

Первый курьер выезжает на маршрут в 7:00 и в 9:48 приезжает на место отдыха, отдыхает 30 минут и продолжает маршрут. Второй курьер выезжает на маршрут в 8:00 и успевает развезти все свои заказы до 12 часов, без перерыва на отдых.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Запланированный маршрут

Пользователь может указать, какой курьер должен выполнить конкретные заказы. Это пригодится:

  • при допланировании — когда есть заранее запланированные маршруты;

  • когда заказ связан с определенным курьером.

Для указания ранее спланированных заказов для данного курьера используется опция vehicle.planned_route. Опция обладает следующими свойствами:

  • Все заказы, указанные в vehicle.planned_route, при планировании не могут стать нераспределенными, даже если будут нарушены жесткие ограничения — вместимость автомобиля или временные окна, у которых hard_window = true.

  • Последовательность заказов, определенная в planned_route, по умолчанию не фиксируется. При повторном планировании заказы могут перестроиться в новой последовательности.

  • Если необходимо сохранить указанный в planned_route маршрут без изменений (без изменения последовательности и без добавления новых заказов), то используйте vehicle.fixed_planned_route = true.

Для каждого заказа, определенного planned_route, обязательно указывать принадлежность к смене автомобиля (даже если у автомобиля 1 смена).

Если в planned_route задано несколько смен, то зафиксировать заказы за сменами можно при помощи опции fix_planned_shifts = true. По умолчанию опция принимает значение false.

Если курьер приехал на заказ слишком рано, время вручения заказа определяется параметром vehicle.wait_if_early:

  • true — курьер ждет начала временного окна заказа (значение по умолчанию);
  • false — курьер обслуживает заказ сразу после прибытия.

Внимание

Если для заказа указано жесткое временное окно location.hard_window = true, параметр vehicle.wait_if_early должен принимать значение true.

Если курьеру во время маршрута необходимо посетить склады для дозагрузки, укажите их в поле middle_depot_id. Они могут совпадать со складами, которые курьер посещает в начале или конце маршрута.

Если в planned_route курьер должен посетить склады для дозагрузки, укажите для них опцию is_middle_depot = true (по умолчанию false). Если указать опцию is_middle_depot = true для всех складов, то алгоритм спланирует начальные и конечные склады в соответствии с настройками курьера, см. разделы Старт с одного из нескольких складов и Возврат на склад в конце маршрута или рейса.

Пример 1

У каждого из двух курьеров в planned_route были определены заказы, в итоге они так и попали на каждого из курьеров.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

В данном примере участвует 1 машина, на которую привязаны заказы через planned_route. Суммарный вес заказов превышает вместимость машины, но такой маршрут все равно планируется (поскольку заказы, определенные в этой опции, не могут попасть в нераспределенные), при этом статус задачи будет UNFEASIBLE.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Теоретически 2 курьера могли бы доставить все 20 заказов без перегруза и опозданий. Но для курьера 1 при помощи параметра vehicle.fixed_planned_route = true указана фиксированная последовательность заказов, поэтому он доставит только заказы из этой последовательности. Курьер 2 не ограничен жестким планом, поэтому возьмет столько заказов, сколько сможет увезти. И несколько заказов останется на складе, несмотря на свободные места и время у курьера 1.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 4.1

2 курьерам за 2 смены необходимо доставить 15 заказов. При помощи опции planned_route заказы 1-8 зафиксированы за курьером 1, а заказы 9-15 за курьером 2. При этом указано, что заказы 1-4 и 9-12 необходимо доставить в первую смену, а заказы 5-8 и 13-15 во вторую смену. Так как fix_planned_shifts = false и курьеры успевают доставить все заказы в одну смену, то распределение заказов по сменам не учитывается.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 4.2

То же, что и в примере 4.1, но опция fix_planned_shifts = true. Поэтому при доставке заказов учитывается, в какую смену их необходимо доставить.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Загруженные заказы

Если заказ уже находится в автомобиле, курьер может сразу ехать на доставку. Для выполнения такого сценария укажите параметры в поле planned_route:

Параметр

Описание

Значение

location.loaded_orders*

Список id заказов с типом delivery, которые уже загружены в автомобиль на складе или в точке с типом garage. За остальными заказами нужно дополнительно заезжать на склад. Независимо от значения loaded_orders в точку можно привозить любые заказы с типом pickup.

id

location.delivery_in_current_run*

Все загруженные в автомобиль заказы должны быть обслужены в этом же рейсе прежде, чем автомобиль заедет на склад.

true / false

planned_runs_first

Автомобиль заедет на все склады в planned_route перед тем, как совершать незапланированные рейсы.

Используйте, если:

  • запланированные заказы на складах уже подготовлены к погрузке с вечера, и их будет удобнее забрать раньше;

  • применяете параметр delivery_in_current_run, чтобы сначала развезти заказы из planned_route.

true / false

* Указывается для складов и заказов типа garage.

Пример

Несколько заказов загружено в автомобиль курьера с вечера, за ними не нужно заезжать на склад. Поэтому в месте, откуда будет выезжать курьер, указана точка типа garage.

Параметр loaded_orders показывает, что загружены заказы 1 и 2 . Курьер может сразу отвезти их в место назначения.

В условиях также заданы параметры:

  • planned_runs_first = true;

  • delivery_in_current_run = true для склада и гаража.

Курьер стартует из гаража и сразу доставляет заказы 1 и 2. Затем он отправляется на склад, где забирает заказы № 3 и № 4, которые должен доставить сразу после загрузки. После этих двух доставок курьер возвращается на склад за заказами 5 и 6 и следует по маршруту дальше.

Запрос API (JSON)Ответ APIОткрыть на карте

Фиксированная часть маршрута

Функциональность visited_locations пригодится, если:

  • начало маршрута должно проходить в строгом порядке.

  • нужно изменить точку старта при допланировании.

Маршрут необходимо фиксировать для каждого курьера индивидуально.

Чтобы это сделать, укажите в vehicles массив visited_locations и опишите точки фиксированного маршрута с помощью следующих параметров.

Параметр

Описание

id*

Идентификатор заказа из locations или склада из depots. Обратите внимание, что идентификаторы заказов и складов не должны совпадать.

shift_id

Идентификатор смены курьера из vehicle.shifts. Определяет, в какой смене нужно обслужить эту точку.

time

Время отправления из точки. Если для первой точки фиксированной части маршрута:

  • указано время, то старт будет с этой точки.
  • не указано время, то маршрут начнется со склада, а начало работы будет рассчитано по окну склада или смены.

Параметр можно указать на нескольких заказах — тогда время посещения рассчитается согласно указанному времени time.

wait_if_early

Необходимость ждать начала временного окна в случае раннего приезда.

  • По умолчанию имеет значение true — то есть курьер будет ждать начала временного окна.
  • Если указано false, то курьер начнет обслуживание сразу после прибытия.

* Обязательный параметр

Пример 1

В примере 5 заказов. Последовательность заказов 1, 2, 3 зафиксирована в visited_locations. Заказы 4 и 5 могут быть выполнены в любом порядке.

Запрос API (JSON)Ответ APIОткрыть на карте

Пример 2

С помощью visited_locations указано начать маршрут с заказа 2 в 10:00.

Запрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Последовательность заказов 1, 2, 3 задана, как в примере 1. Дополнительно указано отправление с заказа 1 в 08:20 и с заказа 3 — в 11:00.

Запрос API (JSON)Ответ APIОткрыть на карте

Пример 4

В примере 8 заказов. Указана последовательность: заказы 1, 2, 3, затем склад, затем заказ 4. Оставшиеся заказы курьер выполняет в любом порядке.

Запрос API (JSON)Ответ APIОткрыть на карте

Корректировка времени движения автомобиля

Для расчета скорости автомобиля при построении маршрута используются данные Яндекс Карт о пробках и указанная в запросе скорость. Однако часто получается так, что грузовики движутся по пробками медленнее, а некоторые водители водят более агрессивно и приезжают раньше расчетных значений.

Чтобы компенсировать такие отклонения, в Маршрутизации есть опция travel_time_multiplier, в которой можно указать дробное значение. При значении 1 расчет будет произведен для автомобиля с ожидаемой средней скоростью. При меньших значениях (например, 0,8), расчет будет для более быстрых автомобилей, при больших (например, 1,2) — для более медленных.

Примечание

Параметр travel_time_multiplier влияет только на скорость движения автомобиля. Время обслуживания на точке доставки остается прежним.

Пример 1

В примере ниже запрос на маршрутизацию отправлен без корректировки времени движения. В результате автомобиль выполняет доставку за 4 часа 20 минут, из которых 3 часа 40 минут уходит на перемещение между точками.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

То же, что и в примере 1, но добавлен параметр travel_time_multiplier, равный 0,5. В построенном маршруте курьер выполняет доставку за 2 часа 25 минут, из которых 1 час 45 минут уходит на перемещение между точками. При этом время, затраченное на парковку и передачу товара, не изменяется.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

То же, что и в примере 1, но добавлен параметр travel_time_multiplier, равный 2. В построенном маршруте курьер выполняет доставку за 7 часов 58 минут, из которых 7 часов 18 минут уходит на перемещение между точками. На перемещение уходит примерно в 2 раза больше времени, чем в маршруте примера 1, потому что часть построенного маршрута выпадает на час пик, и автомобиль не может использовать максимальную скорость. Время, затраченное на парковку и передачу товара, не изменяется.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Корректировка времени обслуживания

Курьеру при доставке заказа нужно потратить время, чтобы его передать. В это время включается парковка, подъем на лифте, передача доставки и оформление бумаг. В Маршрутизации это обеспечивается полями service_duration и shared_service_duration у заказов. Однако некоторые курьеры передают товар быстрее, чем другие. Например:

  • При одновременном планировании для автомобилей и курьеров на общественном транспорте курьеры, которые передвигаются общественным транспортом, не тратят время на парковку. В результате им нужно меньше времени на обслуживание.

  • У курьеров может быть разный уровень квалификации. Опытные курьеры обычно тратят меньше времени на передачу заказа.

Чтобы компенсировать разницу между временем работы курьеров, в Маршрутизации есть опции service_duration_multiplier и shared_service_duration_multiplier, влияющие на длину обслуживания конкретным курьером. При значении 1 время обсуживания будет совпадать с указанным в поле service_duration или shared_service_duration, при значениях меньше 1 время обслуживания будет меньше, а при значениях больше 1 — больше.

Примечание

Параметры service_duration_multiplier и shared_service_duration_multiplier влияют только на время обслуживания. Время перемещения между точками остается прежним.

Пример 1

В примере ниже запрос на маршрутизацию отправлен без корректировки времени обслуживания.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

В примере ниже на маршрутизацию отправлен тот же запрос, что и в примере 1, но со значением параметра service_duration_multiplier в 0,5. Обслуживание заказов в расчете занимает вполовину меньше времени по сравнению с примером 1.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 3

В примере ниже на маршрутизацию отправлен тот же запрос, что и в примере 1, но со значением параметра service_duration_multiplier в 2. Обслуживание занимает вдвое больше времени по сравнению с примером 1.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Доставка как можно раньше

Для построения оптимального маршрута алгоритм минимизирует ожидание между точками маршрута. Но бывают случаи, когда полезно сдвигать доставку на более раннее время. Например:

  • нужно минимизировать риск опоздания;
  • курьеру комфортнее ехать в светлое время суток.

Чтобы заказы были доставлены как можно раньше, используйте penalty.arrival_after_start, который состоит из двух параметров:

  • average_h — задает размер штрафа за среднее время приезда после начала временного окна. При использовании опции рекомендуется всегда указывать это значение.
  • as_soon_as_possible — определяет, нужно ли начинать маршрут максимально рано. Параметр принимает значение true или false (по умолчанию). Указывается в дополнение к average_h.

Примечание

Алгоритм может сдвигать время старта и приезда автомобиля, только если для склада включено гибкое время старта.

Если не использовать штраф penalty.arrival_after_start, то маршрут будет строиться с минимальным ожиданием между точками и максимально поздним временем старта со склада.

При использовании штрафа алгоритм будет строить маршруты так, чтобы начинать их раньше, если это не ухудшает качество.

Если маршрут следует начать максимально рано (даже если из-за этого появится дополнительное ожидание), укажите penalty.arrival_after_start.as_soon_as_possible = true.

Пример 1

Маршрут состоит из 4 заказов, которые имеют разные временные окна. Самое раннее начало временного окна у заказа 5 — в 08:00. Курьер стартует со склада в 11:02 и прибывает на первый заказ в 11:40. Заказ 5 доставляется в 12:59.

Запрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Используются те же данные, что и в примере 1, но назначен штраф за среднее время приезда после начала временного окна при помощи параметра penalty.arrival_after_start.average_h. При этом курьер стартует со склада в 06:59, ждет 8 минут и доставляет самый ранний заказ (заказ 5) в 08:00.

Запрос API (JSON)Ответ APIОткрыть на карте

Пример 3

Используются те же данные, что и в примере 2, но дополнительно задан параметр penalty.arrival_after_start.as_soon_as_possible = true. При этом курьер стартует со склада в 06:00, ждет 1 час 7 минут и доставляет самый ранний заказ (заказ 5) в 08:00.

Запрос API (JSON)Ответ APIОткрыть на карте

Сцепки

Сцепка — это грузовик с прицепом. Заказы можно размещать в грузовике и в прицепе, при этом один заказ может быть загружен частично в грузовик, частично в прицеп.

Для описания прицепа используйте объект trailer.

Поле

Описание

trailer.сapacity

Вместимость прицепа, описывается полями:

  • weight_kg — вместимость в килограммах;
  • units — вместимость в единицах.

Добавляется к вместимости грузовика.

trailer.capacity.custom

Количество пользовательских единиц измерения, которое можно перевозить в прицепе.

Вместимости в пользовательских единицах задаются в формате "name": size, где:

  • name — название пользовательской единицы (задается вместо поля additionalProperties);
  • size — вместимость автомобиля в соответствующих единицах, выражается неотрицательным вещественным числом.

Если название единицы присутствует в отправлениях или других автомобилях, но не в этом, то вместимость полагается неограниченной.

trailer.capacity.limits

Предел загрузки прицепа, описывается полями:

  • units_perc — в пользовательских единицах измерения, выражается в процентах от вместимости прицепа;
  • volume_perc — в процентах от объема прицепа;
  • weight_perc — в процентах от максимально допустимого общего веса груза, перевозимого в прицепе.

trailer.capacity.volume

Метрические размеры прицепа, описываются полями:

  • depth_m* — глубина;
  • height_m* — высота;
  • width_m* — ширина.

Значения выражаются в метрах.

* — Обязательный параметр

trailer.capacity.volume_cbm

Объем прицепа в кубометрах.

Если у прицепа заданы и метрические размеры, и объем, то trailer.capacity.volume определяет габариты, а trailer.capacity.volume_cbm — вместимость.

trailer.max_capacity_difference

Максимальная разница в загрузке прицепа и грузовика описывается полями:

  • units — на сколько единиц товаров может быть в прицепе больше, чем в грузовике;
  • volume_cbm — на сколько кубических метров загрузка прицепа может быть больше, чем загрузка грузовика;
  • weight_kg — на сколько килограмм загрузка прицепа может быть больше, чем загрузка грузовика.

Если какое-то из полей пропущено, значит, по нему нет ограничений.

На разницу в загрузке прицепа и грузовика есть физические ограничения. Если грузовик пустой, а прицеп тяжелый, то автомобиль становится неуправляемым, сцепка не сможет ехать.

trailer.max_capacity_difference.custom

Максимально допустимая разница в загруженном количестве пользовательских единиц измерения у прицепа и грузовика.

Допустимая разница в пользовательских единицах задается в формате "name": size, где:

  • name — название пользовательской единицы (задается вместо поля additionalProperties);
  • size— вместимость автомобиля в соответствующих единицах, выражается неотрицательным вещественным числом.

Если название единицы присутствует в отправлениях или других автомобилях, но не в этом, то ограничения нет.

trailer.cost

Стоимость прицепа, описывается полями:

  • fixed — фиксированная стоимость за использование прицепа;
  • hour — стоимость за час использования прицепа;
  • km — стоимость за километр (добавляется только за участки пути, где грузовик едет с прицепом);
  • location — стоимость использования прицепа в расчете на один пункт назначения;
  • run — стоимость за один рейс со склада до  пункта назначения;
  • tonne_km — стоимость перевозки одной тонны на один километр.

Добавляется к стоимости грузовика, если прицеп будет использован.

trailer.decoupling_time_s

Время отсоединения прицепа в секундах.

Только для заказов с типом anchor и parking (см. раздел Использование прицепа).

trailer.coupling_time_s

Время присоединения прицепа в секундах.

Только для заказов с типом anchor и parking (см. раздел Использование прицепа).

trailer.rolling_cost

Штраф за каждую перекатку* грузов из прицепа в грузовик.

* Перекатка — перемещение заказов из прицепа в грузовик (чтобы доставить их в неподъездные локации (см. раздел Использование прицепа)).

trailer.rolling_time

Время перекатки груза из прицепа в грузовик, задается в секундах. Может быть описано полями:

  • fixed_time_s — фиксированное время;
  • s_per_kg — время разгрузки на килограмм груза;
  • s_per_m3 — время разгрузки на кубометр груза;
  • s_per_unit — время разгрузки на единицу груза.

Если указано несколько типов времени, используется тот, который затрачивает больше всего времени. Если ни один тип не указан, используется только фиксированное время.

Ко времени перекатки добавляется coupling_time_s и decoupling_time_s, так как для перекатки нужно сначала присоединить прицеп, а потом отсоединить его.

Пример описания прицепа в запросе:

{
    "trailer": {
        "capacity": {
            "weight_kg": 10000,
            "units": 200
        },
        "max_capacity_difference": {
            "units": 10,
            "weight_kg": 0
        },
        "cost": {
            "fixed": 1000,
            "km": 10
        },
        "decoupling_time_s": 300,
        "coupling_time_s": 300,
        "rolling_time": {
            "fixed_time_s": 3000
        }
    }
}

Подробнее об использовании грузовика с прицепом см. в разделе Использование прицепа.

Минимальный вес заказа для автомобиля

Чтобы тяжелый грузовик не вез один легкий заказ в другой конец города, используйте параметр min_stop_weight. С помощью этого параметра вы можете указать минимальный суммарный вес, который автомобиль будет доставлять в одну точку. Актуально при планировании грузовых перевозок разнотоннажным транспортом.

Ограничение мягкое — алгоритм может его нарушить. Штрафы задаются в полях:

  • penalty.min_stop_weight.fixed — штраф за факт нарушения минимального суммарного веса всех заказов в одной точке (по умолчанию 1000);

  • penalty.min_stop_weight.kg — штраф за каждый недостающий килограмм в суммарном весе заказов, доставляемых в одну точку (по умолчанию 50).

Подробнее об использовании разнотоннажного транспорта см. в разделе Транспорт с разной грузоподъемностью.

Пример 1

Два автомобиля с грузоподъемностью 1500 и 10000 кг развозят заказы весом 100, 500, 900 и 9000 кг. Большому автомобилю достаются и легкие, и тяжелые заказы.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Пример 2

Для автомобиля с грузоподъемностью 10000 кг указан параметр min_stop_weight со значением 1000. В результате большому автомобилю достается только заказ с весом 9000 кг.

Пример ExcelЗапрос API (JSON)Ответ APIОткрыть на карте

Написать в службу поддержки
Следующая