ルート違反を無視して、通常では到達不可能なジョブを割り当てる

道路の閉鎖や通行禁止区域によってジョブの場所へのアクセスが遮断されている場合、HERE Tour Planning APIはその場所を到達不可能として扱います。その結果、ジョブは未割り当てのままとなり、どの旅程にも追加されません。

その他のルーティング制約も同様の結果につながる可能性があります。たとえば、次のような場合にジョブが到達不可能になることがあります。

  • 車両プロファイルに、特定の道路、橋、ゾーンのいずれかへのアクセスを妨げる物理的な制限 (車軸重量制限など) が含まれている。
  • 問題の設定で、回避エリアや回避セグメントがその場所への有効なルートをすべて排除するような形で使用されている。

ラストマイル配送などの実際のシナリオでは、このような制約はルートの最後の数メートルにのみ影響することがよくあります。そのような場合、ドライバーは近くに駐車して最後のセグメントを徒歩で移動することで、道路ネットワークでは到達不可能であっても実質的にはジョブに到達可能となります。

この点を考慮し、ルーティング制限がある場合でもドライバーが物理的には配送を完了できる場合に、不必要な未割り当てが発生するのを防ぐには、ignoreRouteViolations機能を使用します。

この機能を設定すると、最適化アルゴリズムは、通常であればREACHABLE_CONSTRAINT違反を引き起こすような場所も到達可能として扱い、対応するジョブを旅程計画に含めます。

REACHABLE_CONSTRAINT違反は、最適化アルゴリズムが、制限されている、または通行止めになっている道路セグメントを通らずに、2地点間のルートを見つけられない場合に発生します。

📘

ignoreRouteViolations機能は、その場所が物理的にアクセス可能かどうかを確認することなく、ルーティング制限を無効にします。ジョブの場所が徒歩であっても実際に到達不可能な場合、最適化アルゴリズムによって割り当てられたとしても、ドライバーはその停車地を完了することはできません。この機能は、業務上の状況から、ドライバーがルートの最後のセグメントを徒歩で移動できることが確認されている場合にのみ使用してください。

詳細については、「運行管理」を参照してください。

例:車軸重量によってブロックされたジョブを割り当てる

このサンプルシナリオでは、トラック全車両でweightPerAxleGroupオプションが使用されています。この設定により、以下に掲示されている車軸重量制限を車両がクリアできる道路および橋梁にルートが限定されます。

  • single: 10000:トラックは単一の車軸グループに10,000 kgの荷重をかけます。
  • tandem: 18000:トラックはタンデム車軸グループに18,000 kgの荷重をかけます。

問題のJSONでは、以下のスニペットに示すように、これらの制限は対応するトラックプロファイルのfleet.profilesで定義されています。

{
  "name": "my_delivery_truck",
  "type": "truck",
  "options": {
    "weightPerAxleGroup": {
      "single": 10000,
      "tandem": 18000
    }
  }
}

最適化アルゴリズムが、これらの値よりも低い重量制限のある道路や橋を検出した場合、その道路をこの車両の通行禁止区間として扱います。ジョブの場所への唯一の道路が、制限のある道路や橋に通じている、またはそれらを横断している場合、そのジョブは到達不可能となります。

以下の旅程計画の問題では、トラック全車両が完了すべきジョブは2つのみで、1つはベルリン郊外、もう1つは市街地中心部に位置しています。

Click to expand/collapse the sample JSON
{
  "fleet": {
    "types": [
      {
        "profile": "my_delivery_truck",
        "amount": 1,
        "capacity": [
          100
        ],
        "costs": {
          "time": 0.005555555555555556,
          "distance": 0.0015,
          "fixed": 370
        },
        "id": "vehicle_1",
        "shifts": [
          {
            "start": {
              "location": {
                "lat": 52.58993,
                "lng": 13.42273
              },
              "time": "2025-09-26T07:58:00Z"
            }
          }
        ]
      }
    ],
    "profiles": [
      {
        "name": "my_delivery_truck",
        "type": "truck",
        "options": {
          "weightPerAxleGroup": {
            "single": 10000,
            "tandem": 18000
          }
        }
      }
    ]
  },
  "plan": {
    "jobs": [
      {
        "id": "delivery_1",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "duration": 300,
                  "location": {
                    "lat": 52.595251760429065,
                    "lng": 13.456764166098564
                  }
                }
              ],
              "demand": [
                4
              ]
            }
          ]
        }
      },
      {
        "id": "delivery_2",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "duration": 300,
                  "location": {
                    "lat": 52.51613904868212,
                    "lng": 13.376546984072776
                  }
                }
              ],
              "demand": [
                2
              ]
            }
          ]
        }
      }
    ]
  }
}

初期ソリューションを解釈する

次の図は作成されるソリューションの概要を視覚的に示したものです。

ルート制限違反により割り当てられていないジョブを含む旅程

概要が示しているように、最適化アルゴリズムはdelivery_2location_unreachableステータスとして未割り当てにしました。原因としては、利用可能なルートがすべて掲示されている車軸重量制限に違反しており、トラックがジョブの目的地にアクセスできないことが考えられます。

ソリューションファイル全体については、次のJSONファイルを参照してください。

Click to expand/collapse the sample JSON
{
  "statistic": {
    "cost": 381.08094444444447,
    "distance": 4091,
    "duration": 890,
    "times": {
      "driving": 590,
      "serving": 300,
      "waiting": 0,
      "stopping": 0,
      "break": 0,
      "intraStop": 0
    },
    "intraStopDistance": 0
  },
  "tours": [
    {
      "vehicleId": "vehicle_1_1",
      "typeId": "vehicle_1",
      "stops": [
        {
          "time": {
            "arrival": "2025-09-26T07:58:00Z",
            "departure": "2025-09-26T07:58:00Z"
          },
          "load": [
            4
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure",
              "location": {
                "lat": 52.58993,
                "lng": 13.42273
              },
              "time": {
                "start": "2025-09-26T07:58:00Z",
                "end": "2025-09-26T07:58:00Z",
                "arrival": "2025-09-26T07:58:00Z"
              }
            }
          ],
          "location": {
            "lat": 52.58993,
            "lng": 13.42273
          },
          "distance": 0
        },
        {
          "time": {
            "arrival": "2025-09-26T08:07:50Z",
            "departure": "2025-09-26T08:12:50Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "delivery_1",
              "type": "delivery",
              "location": {
                "lat": 52.595251760429065,
                "lng": 13.456764166098564
              },
              "time": {
                "start": "2025-09-26T08:07:50Z",
                "end": "2025-09-26T08:12:50Z",
                "arrival": "2025-09-26T08:07:50Z"
              }
            }
          ],
          "location": {
            "lat": 52.595251760429065,
            "lng": 13.456764166098564
          },
          "distance": 4091
        }
      ],
      "statistic": {
        "cost": 381.08094444444447,
        "distance": 4091,
        "duration": 890,
        "times": {
          "driving": 590,
          "serving": 300,
          "waiting": 0,
          "stopping": 0,
          "break": 0,
          "intraStop": 0
        },
        "intraStopDistance": 0
      },
      "shiftIndex": 0
    }
  ],
  "unassigned": [
    {
      "jobId": "delivery_2",
      "reasons": [
        {
          "code": "REACHABLE_CONSTRAINT",
          "description": "location unreachable"
        }
      ]
    }
  ]
}

ルート違反を無視する

道路の重量制限を無効にし、最適化アルゴリズムがdelivery_2のジョブを旅程に確実に割り当てるようにするには、値をallに設定したignoreRouteViolationsオプションを使用できます。以下のスニペットに示すように、名前付きprofileオブジェクト (fleet.profiles) でこのオプションを設定します。

{
  "name": "my_delivery_truck",
  "type": "truck",
  "ignoreRouteViolations": [
    "all"
  ],
  "options": {
    "weightPerAxleGroup": {
      "single": 10000,
      "tandem": 18000
    }
  }
}

その結果、最適化アルゴリズムはmy_delivery_truckプロファイルを参照しているfleet.types内のすべての車両タイプに対して、すべてのルート違反を無視するようになります。これにより、本来であれば未割り当てのまま残ってしまうはずのジョブを旅程に組み込めるようになります。

📘

"ignoreRouteViolations"配列内の"all"値を、"traffic"などの他の値と併用することはできません。そうするとエラーが発生します。

サポートされているその他のignoreRouteViolations値の詳細については、「APIリファレンス」を参照してください。

以下のサンプルは、my_delivery_truckという車両プロファイルのignoreRouteViolationsオプションがallに設定されているという問題の例です。

Click to expand/collapse the sample JSON
{
  "fleet": {
    "types": [
      {
        "profile": "my_delivery_truck",
        "amount": 1,
        "capacity": [
          100
        ],
        "costs": {
          "time": 0.005555555555555556,
          "distance": 0.0015,
          "fixed": 370
        },
        "id": "vehicle_1",
        "shifts": [
          {
            "start": {
              "location": {
                "lat":52.58993,
                "lng":13.42273
              },
              "time": "2025-09-26T07:58:00Z"
            }
          }
        ]
      }
    ],
    "profiles": [
      {
        "name": "my_delivery_truck",
        "type": "truck",
        "ignoreRouteViolations": [
          "all"
        ],
        "options": {
          "weightPerAxleGroup": {
            "single": 10000,
            "tandem": 18000
          }
        }
      }
    ]
  },
  "plan": {
    "jobs": [
      {
        "id": "delivery_1",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "duration": 300,
                  "location": {
                    "lat": 52.595251760429065,
                    "lng": 13.456764166098564
                  }
                }
              ],
              "demand": [
                4
              ]
            }
          ]
        }
      },
      {
        "id": "delivery_2",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "duration": 300,
                  "location": {
                    "lat": 52.51613904868212,
                    "lng": 13.376546984072776
                  }
                }
              ],
              "demand": [
                2
              ]
            }
          ]
        }
      }
    ]
  }
}

更新されたソリューションを解釈する

新しいソリューションが示しているように、最適化アルゴリズムはすべてのジョブを旅程に割り当てました。これには、以前は到達不可能であったために未割り当てとなっていたdelivery_2ジョブも含まれています。

ルーティング違反が無視されたジョブの場所を含む更新されたソリューション

更新されたソリューションが示しているように、最適化アルゴリズムは重量、車高、その他の物理的制限を含むすべてのルート違反を抑制しました。これにより、ジョブの目的地に物理的にアクセスできるかどうかの確認は、ドライバー側の責任となります。これには、車両を近くの駐車場に駐車し、ルートの残りのセグメントを徒歩で移動することが含まれる場合があります。

さらに、最適化アルゴリズムがルーティング違反を無視したすべてのジョブについては、notices配列にそれに対応する警告が表示されます。これは、delivery_2ジョブの例に示されているとおりです。

{
  "jobId": "delivery_2",
  "type": "delivery",
  "location": {
    "lat": 52.51613904868212,
    "lng": 13.376546984072776
  },
  "time": {
    "start": "2025-09-26T08:36:50Z",
    "end": "2025-09-26T08:41:50Z",
    "arrival": "2025-09-26T08:36:50Z"
  },
  "notices": [
    {
      "code": "unreachableLocation",
      "title": "Due to ignored route violations (all), this location can be unreachable",
      "action": "Remove ignoreRouteViolations to be sure that location is reachable"
    }
  ]
}

更新されたソリューションの全体については、次のセクションで確認できます。

Click to expand/collapse the sample JSON
{
  "statistic": {
    "cost": 410.1831111111111,
    "distance": 17048,
    "duration": 2630,
    "times": {
      "driving": 2030,
      "serving": 600,
      "waiting": 0,
      "stopping": 0,
      "break": 0,
      "intraStop": 0
    },
    "intraStopDistance": 0
  },
  "tours": [
    {
      "vehicleId": "vehicle_1_1",
      "typeId": "vehicle_1",
      "stops": [
        {
          "time": {
            "arrival": "2025-09-26T07:58:00Z",
            "departure": "2025-09-26T07:58:00Z"
          },
          "load": [
            6
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure",
              "location": {
                "lat": 52.58993,
                "lng": 13.42273
              },
              "time": {
                "start": "2025-09-26T07:58:00Z",
                "end": "2025-09-26T07:58:00Z",
                "arrival": "2025-09-26T07:58:00Z"
              }
            }
          ],
          "location": {
            "lat": 52.58993,
            "lng": 13.42273
          },
          "distance": 0
        },
        {
          "time": {
            "arrival": "2025-09-26T08:07:50Z",
            "departure": "2025-09-26T08:12:50Z"
          },
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "delivery_1",
              "type": "delivery",
              "location": {
                "lat": 52.595251760429065,
                "lng": 13.456764166098564
              },
              "time": {
                "start": "2025-09-26T08:07:50Z",
                "end": "2025-09-26T08:12:50Z",
                "arrival": "2025-09-26T08:07:50Z"
              }
            }
          ],
          "location": {
            "lat": 52.595251760429065,
            "lng": 13.456764166098564
          },
          "distance": 4091
        },
        {
          "time": {
            "arrival": "2025-09-26T08:36:50Z",
            "departure": "2025-09-26T08:41:50Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "delivery_2",
              "type": "delivery",
              "location": {
                "lat": 52.51613904868212,
                "lng": 13.376546984072776
              },
              "time": {
                "start": "2025-09-26T08:36:50Z",
                "end": "2025-09-26T08:41:50Z",
                "arrival": "2025-09-26T08:36:50Z"
              },
              "notices": [
                {
                  "code": "unreachableLocation",
                  "title": "Due to ignored route violations (all), this location can be unreachable",
                  "action": "Remove ignoreRouteViolations to be sure that location is reachable"
                }
              ]
            }
          ],
          "location": {
            "lat": 52.51613904868212,
            "lng": 13.376546984072776
          },
          "distance": 17048
        }
      ],
      "statistic": {
        "cost": 410.1831111111111,
        "distance": 17048,
        "duration": 2630,
        "times": {
          "driving": 2030,
          "serving": 600,
          "waiting": 0,
          "stopping": 0,
          "break": 0,
          "intraStop": 0
        },
        "intraStopDistance": 0
      },
      "shiftIndex": 0
    }
  ]
}

次のステップ


このページは役に立ちましたか?