コード見直し学習&フォルダ整理&PJ要約資料作成開始⑦
この書き方
{ route: plan.route }は責務分離としては良いのですが、UTMでは route の中身が曖昧だと将来かなり危険です。
あなたの今の流れだと、まさにここは重要ポイントです。
まず何が危険か
`route` という名前は広すぎます。
見る側によって意味がズレやすいです。
たとえば `plan.route` が次のどれなのかが、人やサービスごとに変わりやすいです。
// 1. ただの始点終点
route: {
start: [139.7, 35.6],
end: [139.71, 35.62]
}
// 2. TCノードの経路ヒント
route: {
tcFrom: "A",
tcTo: "D"
}
// 3. 実際の飛行経路の折れ線
route: {
waypoints: [
[139.7, 35.6],
[139.705, 35.605],
[139.71, 35.62]
]
}
// 4. 時刻付き経路
route: {
start: [139.7, 35.6],
end: [139.71, 35.62],
tStart: "2026-01-08T10:00:10.000Z"
}同じ `route` という名前でも意味が全然違います。
すると SDSP 側が
req.body.route.startを期待していたのに、実際には
{ tcFrom: "A", tcTo: "D" }しか来ない、という事故が起きます。
これが「座標系バグ」につながる理由
UTMでは、位置情報が少し曖昧なだけで大事故になります。
特に危ないのは次のズレです。
1. `[lon, lat]` と `[lat, lon]` の取り違え
これは最頻出です。
たとえば
[139.7, 35.6]を
正しくは `[経度, 緯度]`
でも別の人は `[緯度, 経度]` と思って使う
すると地点が全然違う場所になります。
名古屋周辺を想定していたのに、地図上ではとんでもない場所に飛ぶ、ということが起こります。
あなたが前に扱っていた `isValidLonLatPair(v)` で長さ2を見ていたのは、まさにこの種の事故を減らす第一歩です。
ただし 長さ2だけでは順序ミスは防げません。
2. TCノード座標と実地理座標の混同
今のUTM-Labでは TC 側に `A → D` のようなノード世界がありますよね。
これは
TCの内部グラフのノード
現実地図の緯度経度
が別物です。
なのに `route` に両方を混ぜると危ないです。
例:
route: {
tcFrom: "A",
tcTo: "D",
start: [136.9, 35.1],
end: [136.92, 35.11]
}これ自体は悪くないですが、SDSPがどちらを信じるのか不明だと危険です。
SDSPは `start/end` を使うつもり
FIMSは `tcFrom/tcTo` さえあればよいと思っている
将来別の人が `route.tcFrom` だけ送るように変える
こうなると geofence 判定が実質壊れます。
3. 単なる直線と実際の通過経路のズレ
`start` と `end` だけ送る場合、SDSPはたいてい
始点から終点への直線で判定します。
でも TC が実際に作る経路は
A → B → C → Dのような折れ線かもしれません。
すると問題が出ます。
ケース
始点と終点を結ぶ直線は geofence に入らない
でも実際のノード経路は途中で geofence を横切る
この場合、SDSPは「安全」と言うのに、実ルートは危険です。
逆もあります。
直線では geofence に当たる
実際の経路は避けている
この場合、不要な reject が起きます。
つまり route が抽象経路なのか実経路なのか明示されていないと危険です。
4. 高度・時間が route に無い
geofence は本当は 2D ではなく、UTMではかなりの場面で 3D/4D です。
つまり必要なのは
どこを飛ぶか
何mを飛ぶか
いつ飛ぶか
です。
しかし
{ route: plan.route }だけだと、route の中に高度や時間がない場合があります。
すると SDSP は
地図上だけで判定
時間窓を無視
高度制限を無視
することになります。
これだと「geofence チェックをしたつもりで、実は簡略版判定しかしていない」状態になります。
じゃあ今のコードのどこが危ないのか
危険なのはこの1行そのものというより、`plan.route` の契約が弱いことです。
const res = await axios.post(
`${SDSP_URL}/api/geofence/check`,
{ route: plan.route },
{ timeout: 3000 }
);このコードは
`route` の構造
座標順序
必須項目
直線扱いなのか折れ線なのか
が明文化されていないと、将来メンテで壊れやすいです。
今は自分が全部分かっているから動きます。
でも少し経つと、未来の自分でも「あれ、SDSPに送る route って start/end だけだっけ?」となりやすいです。
改善の方向
一番大事なのは、`route` を曖昧語のまま使わず、SDSPに渡す専用の形を固定することです。
例えばこんな形です。
const geofenceRequest = {
geometry: {
type: "LineString",
coordinates: [
plan.route.start,
plan.route.end,
],
coordinateOrder: "lonlat"
},
altitude: {
min: plan.alt?.min ?? null,
max: plan.alt?.max ?? null
},
timeWindow: {
start: plan.route.tStart ?? null,
end: plan.route.tEnd ?? null
}
};そして送る。
const res = await axios.post(
`${SDSP_URL}/api/geofence/check`,
geofenceRequest,
{ timeout: 3000 }
);これなら SDSP 側が期待するものがかなり明確です。
最低限やるべきこと
今の段階なら、まず次の3つだけでもかなり違います。
1. route の形を固定する
たとえば「SDSPに渡す route は必ず start/end の lon-lat 配列」と決める。
2. 座標順序を明記する
コメントでもいいので固定する。
// route.start / route.end are [lon, lat]3. SDSP送信用の変換関数を作る
直で `plan.route` を渡さない。
function buildGeofenceRequest(plan) {
const route = plan.route || {};
return {
start: route.start,
end: route.end,
coordinateOrder: "lonlat",
altitude: plan.alt || null,
tStart: route.tStart || null,
};
}こうすると、将来 `plan.route` の内部が変わっても、SDSPとの境界は守れます。
あなたの今のUTM-Lab文脈で言うと
今の設計では
FIMSは管理と検証
TCは時間SoTと経路スケジュール
SDSPは geofence 判定
という分離を目指しているので、サービス境界で生の `plan.route` をそのまま流すのは少し危ないです。
理由は、`plan.route` が FIMS 内部モデルであって、SDSP API モデルではないからです。
ここを分けるとかなり強くなります。
一言でまとめると
`{ route: plan.route }` の本当の危険は、
「route という曖昧な内部表現を、そのまま別サービス契約にしてしまうこと」
です。
その結果起きやすいのが
lon/lat 順序ミス
TCノードと地理座標の混同
直線経路と実経路のズレ
高度・時間の欠落
将来変更での静かな破壊
です。
