見出し画像

コード見直し学習&フォルダ整理&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ノードと地理座標の混同

  • 直線経路と実経路のズレ

  • 高度・時間の欠落

  • 将来変更での静かな破壊

です。


いいなと思ったら応援しよう!