コンテンツにスキップ

geospatialサービス API設計書

本ドキュメントは、geospatialサービスAPI(docs/openapi/frontend/geospatial.yaml および docs/openapi/frontend/geospatial-sse.yaml)を設計するにあたって参照したインプット情報と、そこから導出した下記2点を整理し、設計判断の根拠を後から追跡可能にすることを目的とする。

  • 各APIのレスポンスが、データモデル(utm-design-docs/docs/data-model/data-model.md)のどのテーブル・カラムと対応するかのマッピング表
  • 各APIの検索条件(リクエストボディ)が、旧USS(自USS)のGeoServer WFS API(uss/design/geoserver_api_spec/)のCQLフィルタと、どう対応・差異があるか

OpenAPI定義(.yaml)そのものがAPI契約のSource of Truthであり、本ドキュメントはそれを補足する設計メモという位置付けである。仕様の変更時は、まずOpenAPI定義を更新し、本ドキュメントのマッピング表・対応表に差分がないかを確認すること。

分類エンドポイント定義ファイル
飛行計画領域POST /api/v1/geo/flight-plan-area/searchfrontend/geospatial.yaml
飛行計画領域(他Operator)POST /api/v1/geo/flight-plan-area/others/searchfrontend/geospatial.yaml
空域制限(空港等)POST /api/v1/geo/airspace-restriction/airport/searchfrontend/geospatial.yaml
空域制限(レッドゾーン)POST /api/v1/geo/airspace-restriction/red-zone/searchfrontend/geospatial.yaml
空域制限(イエローゾーン)POST /api/v1/geo/airspace-restriction/yellow-zone/searchfrontend/geospatial.yaml
空域制限(条例等)POST /api/v1/geo/airspace-restriction/ordinance/searchfrontend/geospatial.yaml
空域制限(有人機離着陸エリア)POST /api/v1/geo/airspace-restriction/manned-airport/searchfrontend/geospatial.yaml
空域制限(緊急時用務空域)POST /api/v1/geo/airspace-restriction/emergency/searchfrontend/geospatial.yaml
空域制限(その他1)POST /api/v1/geo/airspace-restriction/other1/searchfrontend/geospatial.yaml
空域制限(その他2)POST /api/v1/geo/airspace-restriction/other2/searchfrontend/geospatial.yaml
空域制限(DID)GET /static/tiles/airspace-restriction/did.pmtiles(個別タイルAPIではなく単一の静的PMTilesアーカイブ、HTTP Range Request配信)frontend/geospatial.yaml
飛行軌跡GET /api/v1/geo/telemetry/{flightPlanId}frontend/geospatial.yaml
現在位置一覧POST /api/v1/geo/telemetry/position/searchfrontend/geospatial.yaml
現在位置(リアルタイム購読)GET /api/v1/geo/events/telemetry(SSE)frontend/geospatial-sse.yaml

3. 本ドキュメントのインプット情報

Section titled “3. 本ドキュメントのインプット情報”
種別資料参照範囲用途
データモデルutm-design-docs/docs/data-model/data-model.md飛行計画ドメイン、空域制限ドメイン(Telemetryドメインは TODO: IX側で検討する のため未確定)スキーマのフィールド名・enum値の裏付け、「5. データモデルとのマッピング表」の一次情報源
API管理ポリシー「OpenAPI Spec管理ポリシー」(社内ポリシー。audience単位でのファイル分割、problem.yaml等による横断的関心事の共有方法、x-ix-* 拡張命名規則、破壊的変更検知ツールを規定)拡張プロパティ(x-ix-changes等)のプレフィックスは自組織のnamespace配下で定義することが推奨されており、本ドキュメント・OpenAPI定義ではx-ix-をそのnamespaceとして使用する。
運航情報のyamldocs/openapi/openapi_coordination_backend.yaml(運航調整バックエンドAPI)概要のフォーマットを揃えるための参照
旧USS GeoServer API仕様uss/design/geoserver_api_spec/README.mdTEMPLATE_GeoServer_API.mdMAP-GEO-000-001MAP-GEO-009-001飛行計画取得(if1)、テレメトリ取得(if2)、飛行実績取得(if3)、規制空域取得(if4)、RemoteID取得(if5)、GeoZone一覧取得(if7)、DIPS飛行計画情報取得(if12)新APIの検索条件と、旧APIのCQLフィルタパターン・レスポンスプロパティとの対応関係の洗い出し(「6. 各APIの検索仕様」の一次情報源)
DIPS 2.0 API(FPR)ガイドラインDIPS OSS公開ポータルのPDF §2.3.6 飛行計画情報取得API、§2.3.7 飛行禁止エリア情報取得APIexternalTypeIdflightProhibitedAreaTypeId)、円の中心・半径フィールド等のフィールド名の裏付け、および「DIPSの空域制限レスポンスには高度フィールドが一切存在しない」という前提の確認
用語意味
bbox検索範囲を表すバウンディングボックス(minLon,minLat,maxLon,maxLat、WGS84)。新APIでは検索の基本条件として明示化した。ID指定(飛行計画領域検索のflightPlanId/dipsFlightPlanId、現在位置のflightPlanIds/uasEntityIds)を伴う場合は省略可。
FeatureCollection / FeatureGeoJSON(RFC 7946)に準拠した地物集合/地物の表現。新APIはapplication/geo+jsonで配信する。
CQLフィルタ旧USSのGeoServer WFS API(GetFeatureリクエスト)におけるcql_filterクエリパラメータで指定する属性絞り込み条件。本ドキュメントでは、新APIの検索条件(リクエストボディのプロパティ)との対応関係の比較対象とする。
WFSWeb Feature Service。旧USSのGeoServerが提供するOGC標準の地理情報配信インターフェース。
DID人口集中地区(Densely Inhabited District)。国土地理院(GSI)提供の統計区域データに基づく空域制限分類の1つ。旧USSのGeoServer WFS APIには対応するレイヤーが存在せず、新API独自に静的PMTilesアーカイブとして追加した区分。PMTilesアーカイブ内のレイヤー名もdid固定。
PMTiles単一の静的ファイルにタイル化された地理データを格納し、サーバー側の処理を介さずHTTP Range Requestのみで必要な範囲を取得できるファイルフォーマット。本APIではDIDの配信にのみ使用する(詳細は6.4参照)。
自組織 / 他Operator自組織=自社UTM管理下のOperatorの計画、他Operator=それ以外(他社UTM管理下 または 自社UTM内の他組織)の計画。旧USSのis_managedフラグ(true/false)に相当する区分を、新APIではエンドポイント分割で表現する。
currentTime「指定時刻時点で有効な」計画・位置情報を取得するための検索条件。旧USSのvalidAt/asOf相当のパラメータ名を統一したもの。
currentTimeFrom / currentTimeTo飛行計画領域系(FlightPlanAreaSearchRequest/OtherFlightPlanAreaSearchRequest)のみで使用する、「指定期間内のいずれかの時点で有効な」計画を取得するための検索条件(区間の重なり判定)。currentTime(単一時点指定)とは併用しない。
validAt「指定時刻時点で有効な」空域制限を取得するための検索条件(AirspaceRestrictionSearchRequestのみで使用)。旧USSのvalid_from/valid_to相当のデータ項目名に合わせたパラメータ名で、意味はcurrentTimeと同じ時点包含フィルタ。
validFrom / validToAirspaceRestrictionSearchRequestのみで使用する、「指定期間内のいずれかの時点で有効な」空域制限を取得するための検索条件(区間の重なり判定)。currentTimeFrom/currentTimeToと考え方は同じだが、validAtとの命名の一貫性を優先してこの名前にしている。validAt(単一時点指定)とは併用しない。

5. データモデルとのマッピング表

Section titled “5. データモデルとのマッピング表”

各APIレスポンスのプロパティが、データモデル(utm-design-docs/docs/data-model/data-model.md)のどのテーブル・カラムに対応するかを示す。

5.1 飛行計画領域(FlightPlanAreaProperties / FlightPlanAreaFeature

Section titled “5.1 飛行計画領域(FlightPlanAreaProperties / FlightPlanAreaFeature)”

対象API: POST /api/v1/geo/flight-plan-area/search

他Operator向け(POST /api/v1/geo/flight-plan-area/others/search)は本節のスキーマをそのまま使わず、OtherFlightPlanAreaProperties(公開可能な最小限のプロパティのみ)を返す。詳細は6.2参照。

flowchart LR
    subgraph DB["データモデル(DB)"]
        FLIGHT_PLAN["FLIGHT_PLAN"]
        FLIGHT_PLAN_REVISION["FLIGHT_PLAN_REVISION"]
        FLIGHT_PLAN_DIPS_ATTRS["FLIGHT_PLAN_DIPS_ATTRS"]
        FLIGHT_PLAN_PILOT_ASSIGNMENT["FLIGHT_PLAN_PILOT_ASSIGNMENT"]
        FLIGHT_PLAN_AREA["FLIGHT_PLAN_AREA"]
        FLIGHT_PLAN_AREA_CIRCLE["FLIGHT_PLAN_AREA_CIRCLE"]
        FLIGHT_PLAN_AREA_ROUTE["FLIGHT_PLAN_AREA_ROUTE"]
    end
    subgraph EXT["データモデル外の参照データ"]
        ELEVATION["地表標高データ<br/>(AMSL/WGS84換算用。GSJ統合DEM(GeoTIFF)+<br/>ジオイド高JPGEO2024(ISG)、utm-backend内蔵コンポーネント)"]
    end
    subgraph API["APIレスポンス"]
        FlightPlanAreaProperties["FlightPlanAreaProperties"]
        FlightPlanAreaFeature["FlightPlanAreaFeature<br/>(geometry + properties)"]
    end
    FLIGHT_PLAN -->|id, created_by| FlightPlanAreaProperties
    FLIGHT_PLAN -->|status| FlightPlanAreaProperties
    FLIGHT_PLAN_REVISION -->|planned_start_at,<br/>planned_end_at| FlightPlanAreaProperties
    FLIGHT_PLAN_DIPS_ATTRS -->|report_required,<br/>report_exemption_reason| FlightPlanAreaProperties
    FLIGHT_PLAN_PILOT_ASSIGNMENT -->|aircraft_id| FlightPlanAreaProperties
    FLIGHT_PLAN_AREA -->|area_type, min/max_altitude_m_agl,<br/>min/max_altitude_m_amsl, min/max_altitude_m_wgs84,<br/>altitude_reference, geometry ※CIRCLEの中心復元用,<br/>plan_geometry, operational_intent_geometry,<br/>top_bottom_3d_geometry, および対になる _wgs84 列| FlightPlanAreaProperties
    FLIGHT_PLAN_AREA_CIRCLE -->|radius_m| FlightPlanAreaProperties
    FLIGHT_PLAN_AREA_ROUTE -->|buffer_m| FlightPlanAreaProperties
    FLIGHT_PLAN_AREA -.登録・収集時に 形状の頂点列と<br/>min/max_altitude_m_agl を渡す.-> ELEVATION
    ELEVATION -.換算結果を min/max_altitude_m_amsl,<br/>min/max_altitude_m_wgs84 と _wgs84 列へ書き戻す<br/>※応答時には参照しない.-> FLIGHT_PLAN_AREA
    FlightPlanAreaProperties --> FlightPlanAreaFeature

ELEVATION(地表標高データ)の実体: 国土地理院提供のDEMを事前にGeoTIFFへ変換したものを地表標高、 JPGEO2024(ISG形式)をジオイド高として用いる(旧GSIGEO2011は使用しない)。当面は全国の一部地域のみを カバーする小さいデータセットから始め、段階的に全国データへ拡張する運用とする。この変換処理は別マイクロ サービスへ切り出さず、utm-backend内の独立コンポーネント(domain.port.AltitudeConverterinfrastructure.elevation配下の実装)としてプロセス内に持つ。DEM・ジオイドファイルは起動時に1回だけ 読み込み、リクエストごとの外部I/Oは発生しない。アーキテクチャ・実データ形式の詳細・テスト戦略・ 既知の制限はElevation Service設計書を参照。 本決定の正式な記録(ADR化・ utm-design-docs/docs/data-model/data-model.mdへの反映)は別リポジトリ側の対応が必要で未着手followups.md参照)。

OpenAPIプロパティデータモデル上の対応備考
flightPlanIdFLIGHT_PLAN.id
createdByFLIGHT_PLAN.created_by作成者のユーザーID。自組織向け(/flight-plan-area/search)のみに含まれ、他Operator向け(/flight-plan-area/others/search)のOtherFlightPlanAreaPropertiesには含まれない(6.2参照)
statusFLIGHT_PLAN.status運航状態軸(ASTM F3548-21ベース)。FLIGHT_PLAN_STATE_EVENTから導かれる導出キャッシュをFLIGHT_PLANに置く(リビジョンではない。状態遷移は内容リビジョンを作らないため)。report_required/report_status(通報状態軸)は直交する別軸のため別プロパティとして公開する(下記参照)。他Operator向け(/flight-plan-area/others/search)のOtherFlightPlanAreaPropertiesでは設定されない(6.2参照)
reportRequiredFLIGHT_PLAN_DIPS_ATTRS.report_required航空局(DIPS)への通報義務の有無。flight_airspaceflight_type・機体重量から判定され、領域・高度の変更でtruefalseに変動しうる。DIPS通報固有の属性は飛行計画本体から分離するため、FLIGHT_PLAN_DIPS_ATTRSFLIGHT_PLAN_REVISIONと1:1)が保持する
reportStatusカラムを持たずFLIGHT_PLAN_STATE_EVENT.report_status_afterから導出DIPS通報状態。値はUNREPORTED/REPORTING/REPORTED/WITHDRAWING/WITHDRAWN5値(本ドキュメントの旧記述は3値だった)。reportRequiredとは独立した軸であり、その値によらず設定する。通報義務がなくても通報でき(reportFlightPlanreportRequiredを判定しない)、成功すればREPORTEDになる。通報していない間は義務の有無を問わずUNREPORTEDflight_planning.dips_report_status_typeUNREPORTEDが「未通報(通報不要・未通報のいずれも含む)」と定義されており、FLIGHT_PLAN_STATE_EVENTに該当行が1件もなければUNREPORTEDに定まるため、値が未設定になる経路がない)。OASでもFlightPlanAreaProperties.requiredに含まれる。GUI側でACTIVATE可否(status=ACCEPTED AND(reportRequired=false OR reportStatus=REPORTED))を判定・表示するために必要なため公開する
reportExemptionReasonFLIGHT_PLAN_DIPS_ATTRS.report_exemption_reason通報義務なし(reportRequired=false)の根拠(例: WEIGHT_UNDER_100G)。reportRequired=trueの場合は未設定。INDOOR_ONLYは屋内飛行を申告する入力項目がなく10月デモの対象外のため、デモ範囲では設定されない
dipsFlightPlanIdDIPS_REPORT.dips_receipt_noFLIGHT_PLANに対する最新のDIPS_REPORTレコードの値。docs/data-model/flight-plan-field-mapping.mdの「飛行計画ID(DIPS)」項目と同一)DIPSへの通報後にDIPS側で払い出される飛行計画ID(MAP-GEO-009-001flight_plan_id相当。例: AAAAAAAAAAAAAAAAAAA.FP20221125042709013.001)。dips_receipt_noはカラム名こそ「受付番号」だが、格納する値はDIPS飛行計画登録APIレスポンスのflightPlanIdそのもの(registerFlightPlanのレスポンス項目dipsFlightPlanIdと同じ値・同じ出自)。reportStatusが一度もREPORTEDになっていない間は未設定
plannedStartAt / plannedEndAtFLIGHT_PLAN_REVISION.planned_start_at / planned_end_at
minAltitudeMAgl / maxAltitudeMAglFLIGHT_PLAN_AREA.min_altitude_m_agl / max_altitude_m_aglWaypointごとの高度指定は廃止し、フロントエンドから入力可能な高度は飛行計画全体で1つ(最大高度)のみになった。areaType=ROUTEは入力された飛行高度がmaxAltitudeMAglとなり、minAltitudeMAgl0(地表)固定となる(DIPS側の制約により経路の下限は常に地表として扱うため)。POLYGON/CIRCLEは床面〜天井の範囲として両者が異なりうる(7章参照)。ただし10月デモでは床面(底面)の高度指定に対応せずminAltitudeMAgl0固定とする決定のため、デモの範囲ではareaTypeによらず0になる
altitudeReference返却する形状の列で決まる(altitude_referenceは接尾辞のない列の基準を示すのみ)geometryのZ値が準拠する高度基準(AGL/WGS84)を自己記述的に示す。本設計は両基準の形状を実体化しており、AGLのFeatureは接尾辞のない列、WGS84のFeatureは_wgs84列から生成する。同一flightPlanIddataTypeに対し、基準ごとにgeometryのZ値のみが異なる2つのFeatureを返却する(7章参照)。RFC 7946 §4は座標の第3要素を楕円体高と規定するため、AGL基準のFeatureは同規定から意図的に外れている(7章参照)
minAltitudeMAmsl / maxAltitudeMAmslFLIGHT_PLAN_AREA.min_altitude_m_amsl / max_altitude_m_amslmin/maxAltitudeMAglと地表標高データから算出した参考値で、領域内の全頂点における換算値の最小/最大。領域あたりの代表値をカラムに保持する(登録時に一度だけ換算し、応答のたびに外部データを参照しない)。Elevation Serviceが有効(elevation.enabled=true)な環境では、地表標高データが当該地点をカバーしておらず換算できない場合は登録・更新自体を拒否するため、行が存在する時点で本値は常に設定済みである(後から補完する必要もない)。elevation.enabled=false(既定値・ローカル開発)の環境では拒否せずNULLのまま保存するため、その場合はNULLになりうる(docs/data-model/flight-plan-er.mdの「高度は換算値をカラムに保持する」参照)
minAltitudeMWgs84 / maxAltitudeMWgs84FLIGHT_PLAN_AREA.min_altitude_m_wgs84 / max_altitude_m_wgs84min/maxAltitudeMAmslとジオイド高から算出した参考値で、領域内の全頂点における換算値の最小/最大。上記と同様に領域あたりの代表値をカラムに保持する。altitudeReference=WGS84のFeatureのgeometryのZ値は頂点ごとに地表標高を反映するため、本値は個々の頂点のZ値と一致するとは限らない
areaTypeFLIGHT_PLAN_AREA.area_typeROUTE/CIRCLE/POLYGON同一flightPlanIdの複数Featureで共通の値(dataTypeによらず変化しない)
dataTypeデータモデル上に対応するカラムなし当該Featureが元の形状(FLIGHT_PLAN)か、bufferMを適用して水平方向に膨らませた形状(OPERATIONAL_INTENT)かを示す(旧if1_operationalintentsdata_type相当)。bufferM未設定時はFLIGHT_PLANのみ返却される。高度・時刻はFLIGHT_PLAN/OPERATIONAL_INTENT間で変化しない(7章参照)
bufferMFLIGHT_PLAN_AREA_ROUTE.buffer_m水平方向の安全マージン幅。areaType=ROUTEのみが持つ(形状ごとのサブテーブルに分けており、CIRCLE/POLYGONはバッファを持たない)。設定時は元の形状(geometry)に加えて、bufferM分だけ外側に膨らませたPolygon(dataType=OPERATIONAL_INTENTareaTypeは元の値のまま)を同一flightPlanIdの追加Featureとして返却する(6.1参照)。limit/totalCountはFeature数ではなく飛行計画(flightPlanId)単位で数えるため、この追加Featureはカウントに影響しない。他Operator向け(OtherFlightPlanAreaProperties)は本プロパティを持たない(DIPSから収集した計画はROUTEを取らないため。6.2参照)
circleCenterLng / circleCenterLat / circleRadiusM個別カラムは持たず、中心点はFLIGHT_PLAN_AREA.geometryPoint)、半径はFLIGHT_PLAN_AREA_CIRCLE.radius_mareaType=CIRCLEの場合のみ設定。geometryはCIRCLEもPolygon近似で返却するため、元の中心・半径(正規化前の元値)を保持し、編集画面での再現性を確保する。中心点を経度・緯度の2カラムに分けずgeometryで持つのは、空間索引と空間関数をそのまま使えるようにするため
uasIdFLIGHT_PLAN_PILOT_ASSIGNMENT.aircraft_id使用UASのアセットID。本設計では操縦者・機体をリビジョン単位のN:M中間テーブルで持つため、FLIGHT_PLAN_REVISIONに単一のuas_idは存在しない。複数機体を指定した飛行計画では本プロパティを配列化する必要がある(10月デモの範囲では単一機体のため据え置き)
geometrydataTypeに対応する実体化列。FLIGHT_PLANplan_geometryOPERATIONAL_INTENToperational_intent_geometryTOP_BOTTOM_3Dtop_bottom_3d_geometryaltitudeReference=WGS84のFeatureは各_wgs84dataType=FLIGHT_PLANareaType=ROUTE→GeoJSON LineStringPOLYGON/CIRCLEPolygonOPERATIONAL_INTENTPolygonTOP_BOTTOM_3Dは上面・下面のMultiPolygon。座標(Position)の3つ目の要素(高度)の基準はaltitudeReferenceで示す(AGL基準のFeatureではminAltitudeMAgl/maxAltitudeMAglと同一基準、WGS84基準のFeatureでは頂点ごとに換算した楕円体高。詳細は7章参照)。Waypointごとの高度指定は廃止したため、AGL基準のFeatureはリング(線・面)ごとに全頂点共通の値を設定するフラットな表現とする(単一のジオメトリで飛行計画を表すdataType=FLIGHT_PLAN/OPERATIONAL_INTENTは天面として扱い、代表高度に上限側=maxAltitudeMAglを用いる。areaTypeによって代表高度の意味が変わらないようにするため。minAltitudeMAgldataType=TOP_BOTTOM_3Dの下面以外ではジオメトリの高さに反映されない)。WGS84基準のFeatureはareaTypeによらず頂点ごとに地表標高を反映するため、地表が傾斜していれば頂点ごとにZ値が異なる(平坦な場所では結果として全頂点が同値になる)

5.2 空域制限(AirspaceRestrictionProperties / AirspaceRestrictionFeature、DID PMTiles x-ix-feature-properties

Section titled “5.2 空域制限(AirspaceRestrictionProperties / AirspaceRestrictionFeature、DID PMTiles x-ix-feature-properties)”

対象API: categoryごとの検索エンドポイント8種(POST /api/v1/geo/airspace-restriction/{airport|red-zone|yellow-zone|ordinance|manned-airport|emergency|other1|other2}/search)、GET /static/tiles/airspace-restriction/did.pmtiles

flowchart LR
    subgraph DB["データモデル(DB)"]
        AIRSPACE_RESTRICTION["AIRSPACE_RESTRICTION"]
    end
    subgraph API["APIレスポンス"]
        AirspaceRestrictionProperties["AirspaceRestrictionProperties"]
        AirspaceRestrictionFeature["AirspaceRestrictionFeature<br/>(geometry + properties)"]
        DIDPMTiles["didレイヤー<br/>x-ix-feature-properties (PMTiles)"]
    end
    AIRSPACE_RESTRICTION -->|id, external_id, source_kind, status,<br/>category, name, description, info_url, geometry_type,<br/>circle_*, min/max_altitude_agl, min/max_altitude_amsl,<br/>min/max_altitude_wgs84, altitude_unit, altitude_reference,<br/>valid_from/to, geometry, top_bottom_3d_geometry| AirspaceRestrictionProperties
    AirspaceRestrictionProperties --> AirspaceRestrictionFeature
    GSI["国土地理院のデータセット<br/>※10月デモではDBに行を持たない"] -.ビルド時に生成.-> DIDPMTiles
OpenAPIプロパティデータモデル上の対応備考
restrictionIdAIRSPACE_RESTRICTION.idUTMが採番したuuid。同一性の判定はこのプロパティで行う。取得元の識別子はexternalIdで別途参照できる
externalIdAIRSPACE_RESTRICTION.external_id(NULL可)取得元における識別子(DIPSのflightProhibitedAreaId)。取得元の資料と突き合わせる用途で参照できる任意項目。同一性の判定にはrestrictionIdを使う。外部IDを持たないデータソース(sourceKindGSIMANUAL)では未設定
sourceKindAIRSPACE_RESTRICTION.source_kindDIPS_FPR/GSI/MANUAL。概念モデルのAIRSPACE_SOURCE.kindを列へ降格したもので、収集の実装時にsource_id(FK)へ置き換える
categoryAIRSPACE_RESTRICTION.category値はAIRPORT_VICINITY/DENSELY_INHABITED_DISTRICT/SMALL_UAV_PROHIBITION_RED_ZONE/SMALL_UAV_PROHIBITION_YELLOW_ZONE/ORDINANCE_DESIGNATED_AREA/MANNED_AIRCRAFT_TAKEOFF_LANDING_AREA/EMERGENCY_OPERATIONS_AIRSPACE/OTHER_1/OTHER_2の9種。定義はdocs/openapi/domain.yamlAirspaceRestrictionTypeで、飛行計画ドメインと共有する。ソース固有の生の型ID(AIRSPACE_RESTRICTION.external_type_id、DIPSのflightProhibitedAreaTypeId)とは別に設けた正規化分類軸である。DIPS_FPR/GSI/MANUALのソースを横断して使え、categoryごとに分離した検索エンドポイント(6.3参照)の切り分けキー、およびレスポンス上の自己記述的な値(地図上の色分け表示等の用途を想定)として使用する。DENSELY_INHABITED_DISTRICTのみsourceKind=GSI固定(実データはGSI提供の人口集中地区データセットを使用し、配信もPMTilesによる静的配信とする。DIPS側にもflightProhibitedAreaTypeId=2「人口集中地区」の区分定義自体は存在するが、本APIではDIPSのデータではなくGSI由来のデータセットを採用している)。external_type_id自体はAPIでは非公開(データモデルのみ)とする。external_type_idcategoryの対応は次の通り: 1=AIRPORT_VICINITY、2=人口集中地区(GSI由来データセットを採用するため不使用)、5=SMALL_UAV_PROHIBITION_RED_ZONE、6=SMALL_UAV_PROHIBITION_YELLOW_ZONE、7=ORDINANCE_DESIGNATED_AREA、8=MANNED_AIRCRAFT_TAKEOFF_LANDING_AREA、9=EMERGENCY_OPERATIONS_AIRSPACE、10=OTHER_1、11=OTHER_2
nameAIRSPACE_RESTRICTION.name(DIPS: name
descriptionAIRSPACE_RESTRICTION.description(DIPS: detailOpenAPIのdescriptionキーワードと同名で紛らわしい点がある(detailへの改名案あり、未解消)
infoUrlAIRSPACE_RESTRICTION.info_url(DIPS: url
geometryTypeAIRSPACE_RESTRICTION.geometry_typeCIRCLE/POLYGON/MULTIPOLYGONgeometry.typeと1対1対応(CIRCLE/POLYGONPolygonMULTIPOLYGONMultiPolygon)。空港周辺の規制空域等、互いに分離した複数領域から成る場合にMULTIPOLYGONとなる。データモデル側のgeometry_type列挙値にもMULTIPOLYGONの追加が必要(別リポジトリdata-model.md側の対応が必要、本ドキュメントの変更のみでは反映されない点に注意)
circleCenterLng / circleCenterLat / circleRadiusMAIRSPACE_RESTRICTION.circle_center_lng / circle_center_lat / circle_radius_mgeometryType=CIRCLEの場合のみ設定(正規化前の元値を保持)
minAltitudeMAgl / maxAltitudeMAglAIRSPACE_RESTRICTION.min_altitude_agl / max_altitude_agl(いずれもNULL可)床面(floor)・天面(ceiling)の対地高度。取得元が提供する値を返す。取得元が高度を持たない場合、および種別により高度の概念がない場合(レッドゾーン・イエローゾーン等)は未設定で、必須項目ではない。天面が傾斜する領域ではtop_bottom_3d_geometryの頂点ごとのZ値が正で、本2プロパティは領域全体の最小・最大にとどまる(airspace-er.mdの「高度は床面と天面を格納する」)。カラム名に単位を含めないのはaltitude_unitへ外出しする方針のため(PR #211)
altitudeReference返却する形状の列で決まる(AIRSPACE_RESTRICTION.altitude_referenceは接尾辞のない列の基準を示すのみで、現時点では常にAGL。飛行計画ドメインの同名カラムと同じ扱い)geometryのZ値(天面の高度)が準拠する高度基準を自己記述的に示す。本設計は両基準の形状を実体化しており、AGLのFeatureはtop_bottom_3d_geometryWGS84のFeatureはtop_bottom_3d_geometry_wgs84から生成する(airspace-er.mdの「WGS84基準の形状も実体化列で持つ」)。同一restrictionIdに対し、基準ごとにgeometryのZ値のみが異なる2つのFeatureを返却するのが基本形である(2件にならない場合がある_wgs84の2列がともにNULLの行・高度を持たない行はBusinessLogicSpecifications.mdの5.3の1-3-5・1-3-6が、WGS84側の天面を組み立てられない行はdetailed-design.mdの11-1節が定める)。値域はAGL/WGS84の2値で、飛行計画ドメインの同名カラムと揃えている
altitudeUnitAIRSPACE_RESTRICTION.altitude_unit高度関連プロパティおよびgeometryのZ値が準拠する単位(m固定)を自己記述的に示す。カラム名から単位を外した分の単位判別をこのカラムが担う
minAltitudeMAmsl / maxAltitudeMAmslminAltitudeMWgs84 / maxAltitudeMWgs84AIRSPACE_RESTRICTION.min_altitude_amsl / max_altitude_amsl / min_altitude_wgs84 / max_altitude_wgs84(いずれもNULL可・遅延充填)地表の標高データ・ジオイド高を用いてminAltitudeMAgl/maxAltitudeMAglから換算した参考値で、領域内の全頂点における換算値の最小/最大=領域全体の代表値。max側はaltitudeReference=WGS84のFeatureの天面のZ値に対応するが、頂点ごとに算出するため個々の頂点のZ値と一致するとは限らない。min側は返却しない床面(0mAGL相当)側の値であり、geometryのZ値には現れない
validFrom / validToAIRSPACE_RESTRICTION.valid_from / valid_to(DIPS: startTime/finishTime
statusAIRSPACE_RESTRICTION.statusACTIVE/DISAPPEARED取得元での存在状態。フライト計画の運航状態(FlightPlanStatus)とは別概念
geometryAIRSPACE_RESTRICTION.geometrytop_bottom_3d_geometryaltitudeReference=WGS84ではgeometry_wgs84top_bottom_3d_geometry_wgs84。PostGIS正規化形)CIRCLEもPolygon近似で返却、元の中心・半径は上記circle系プロパティで別途保持。geometryType=MULTIPOLYGONの場合はgeometry.type=MultiPolygon(複数の分離したPolygonから成る)。天面(ceiling)のZ値はtop_bottom_3d_geometryの上面リング(WGS84top_bottom_3d_geometry_wgs84)から生成し、当該列がNULLの行では水平形状(geometrygeometry_wgs84)にmin/maxAltitudeMAgl相当の値を組み立てて代える。床面(floor)は返却しない。詳細は7章参照

5.3 テレメトリ(TelemetryTrackProperties / TelemetryPositionProperties

Section titled “5.3 テレメトリ(TelemetryTrackProperties / TelemetryPositionProperties)”

対象API: GET /api/v1/geo/telemetry/{flightPlanId}POST /api/v1/geo/telemetry/position/searchGET /api/v1/geo/events/telemetry(SSE)

テレメトリのデータ形状はテレメトリドメインER図を正とする。フィールドの出自は、旧USSのGeoServer WFS API(if2_telemetryif3_flightrecord)のView項目に準拠している。

flowchart LR
    subgraph DB["データモデル(DB)"]
        FLIGHT_PLAN["FLIGHT_PLAN"]
        USER["USER"]
        TELEMETRY["TELEMETRY<br/>(飛行軌跡)"]
        CURRENT_TELEMETRY["CURRENT_TELEMETRY<br/>(現在位置)"]
    end
    subgraph API["APIレスポンス"]
        TelemetryTrackProperties["TelemetryTrackProperties<br/>(飛行軌跡)"]
        TelemetryPositionProperties["TelemetryPositionProperties<br/>(現在位置)"]
    end
    TELEMETRY -->|reported_uas_id, uas_nickname, aircraft_id, flight_plan_id,<br/>operator_id, operator_name, status,<br/>observed_at, speed, direction 等| TelemetryTrackProperties
    CURRENT_TELEMETRY -->|reported_uas_id, uas_nickname, aircraft_id, flight_plan_id,<br/>operator_id, operator_name, status,<br/>observed_at, speed, direction 等| TelemetryPositionProperties

上図は10月デモの実装を示す。 operatorIdoperatorNamestatusTELEMETRYCURRENT_TELEMETRYへ 複写して持つため、テレメトリの表だけで応答を組み立てられる (telemetry-er.md)。

TO-BEでは複写をやめ、FLIGHT_PLANidcreated_bystatus)とUSERdisplay_name)を 結合して解決する。図中のFLIGHT_PLANUSERは、その結合先として残している。

テレメトリは飛行計画に紐づかないことがある。10月デモでは他社UTMが管理する機体をASSETとしてだけ 登録し、IX UTM上に飛行計画を作らないためである(telemetry-er.md)。 この機体はflightPlanIdが空になり、operatorIdstatusTELEMETRY_DISPLAY_DEFAULTに登録した 既定値が返る。検索仕様上statusはANDで効くため(「6. 各APIの検索仕様」)、既定値がないと status指定の検索から機体が落ちる。

operatorNameは機体を問わずTELEMETRY_DISPLAY_DEFAULTから返る。10月デモではIAMドメインの実体が utm-backendに無く、上図が示すUSER.display_nameとの結合が自組織の機体に対しても成立しないため である(telemetry-er.md)。 同テーブルに行が無い機体はoperatorNameを埋められない。

OpenAPIプロパティ10月デモのDBカラム(telemetry-er.md旧USS View項目(if2_telemetry/if3_flightrecord。参考: フィールド名の出自)備考
uasIdTELEMETRY.reported_uas_idCURRENT_TELEMETRY.reported_uas_iduas_id受信した生値をそのまま返す。登録記号・機体UUID・製造番号・セッションIDのいずれが入るかは値からは判別できない(uasRegistrationId/uasSerialNumber/uasUtmId/uasSpecificSessionIdのいずれか)。FLIGHT_PLAN_AREAuasId(アセットID=UUID)とは別種のIDである
uasNicknameTELEMETRY.uas_nicknameCURRENT_TELEMETRY.uas_nickname(10月デモ限りの複写列)対応する項目なし(新規)運航者が機体に付けた名前(ASSET.nickname)。テレメトリ画面で機体を見分けるために表示する。TO-BEはASSETとの結合で解決する。必須にしていないのは、機体を解決できない行では値を作れないためである(現在の取り込みはそのようなテレメトリを破棄するため、取り込み側が複写を実装すれば常に入る。実装はtelemetry-service-proto PR #7で、反映されるまでは値が入らない。followups.mdの台帳)
uasEntityIdTELEMETRY.aircraft_idCURRENT_TELEMETRY.aircraft_iduas_entity_id飛行軌跡・現在位置の両方に存在する。自UTMのASSETに存在する機体はUTM側で払い出すUUID(ASSET.id)と一致する。他Operator機(自UTMのASSETに存在しない機体)に対して何を返すかは未決(followups.md
flightPlanIdTELEMETRY.flight_plan_idCURRENT_TELEMETRY.flight_plan_idflight_plan_idFLIGHT_PLAN.idと一致する。飛行計画に紐づかない機体では空になる(上記)
operatorIdTELEMETRY.operator_idCURRENT_TELEMETRY.operator_id(10月デモ限りの複写列)operator_idTO-BEはFLIGHT_PLAN.created_byを結合で解決する(作成者のユーザーID。「6. 各APIの検索仕様」参照)。10月デモは複写列を直接返す
operatorNameTELEMETRY.operator_nameCURRENT_TELEMETRY.operator_name(10月デモ限りの複写列)operator_nameTO-BEはUSER.display_nameを結合で解決する。10月デモは複写列を直接返す。その値の出どころはTELEMETRY_DISPLAY_DEFAULTである(上記)
telemetryTime / latestTelemetryTimeTELEMETRY.observed_atCURRENT_TELEMETRY.observed_attelemetry_timeミリ秒(小数点以下3桁)を含むISO8601形式で返却する(utm-design-docsの機能要求5.1.1.2「タイムスタンプは最低でも0.1秒の精度で表現する」に対応。飛行計画領域・空域制限系の日時プロパティは「予定・有効期間」であり同要求の対象外、7章参照)。取り込み側が秒未満を切り捨てる既知の問題があり、10月デモの期間中は小数部が常に.000になる(followups.md
telemetryTimes(飛行軌跡のみ)TELEMETRY.observed_at(頂点ごとの値の配列)telemetry_time(頂点ごとの値の配列)geometry(LineString)の頂点順と1:1対応する各頂点の計測時刻(UTC、古い順)。telemetryTimeと同様ミリ秒を含む。詳細は本節末尾の補足参照
speed / latestSpeedspeedUnitTELEMETRY.speedCURRENT_TELEMETRY.speedTELEMETRY.speed_unitspeedspeed_unit"m/s"固定)
direction / latestDirectiondirectionUnitTELEMETRY.directionCURRENT_TELEMETRY.directionTELEMETRY.direction_unitdirectiondirection_unit"degree"固定)
altitudeReferenceデータモデル上に対応するカラムなしデータモデル上に対応するカラムなしgeometryのZ値が準拠する高度基準(AGL/WGS84)を自己記述的に示す。飛行軌跡は基準ごとに2つのFeatureを返し、現在位置(一覧・SSE)はAGL基準のFeature1件にaltitudeMWgs84を併記する(7章参照)
geometryのZ値対地高度: TELEMETRY.altitude_agl_mCURRENT_TELEMETRY.altitude_agl_m(DEM参照による導出値)/楕円体高: TELEMETRY.positionCURRENT_TELEMETRY.positionのZ値(Remote IDの測地高度)。いずれもtelemetry-er.md対応する項目なし(新規)原則AGL基準。DEM参照に失敗し対地高度が得られない場合、現在位置は当該FeatureのみaltitudeReference=WGS84として測地高度を入れて返す(位置情報を落とさないため)。飛行軌跡はAGLのFeatureを返さない(欠測頂点の間引きは軌跡形状を変えるため)
altitudeMWgs84(現在位置のみ)CURRENT_TELEMETRY.positionのZ値(Remote IDの測地高度、telemetry-er.md対応する項目なし(新規)Remote ID入力の実測値であり、地表標高データによる換算を伴わない。測地高度が「値なし」特殊値(-1000)のテレメトリは取り込み時の入力チェック(UnknownCheck)で弾かれ保持されないため、Featureが返る場合は常に設定される(必須プロパティ)
statusTELEMETRY.statusCURRENT_TELEMETRY.status(10月デモ限りの複写列)statusTO-BEはFLIGHT_PLAN.statusを結合で解決する(運航状態軸、ASTM F3548-21ベース。FLIGHT_PLAN_STATE_EVENTから導かれる導出キャッシュをFLIGHT_PLANに置く)。10月デモは複写列を直接返す

telemetryTimes追加の経緯: 飛行軌跡(TelemetryTrackProperties)は従来latestTelemetryTimelatestSpeedlatestDirectionという直近値のみを保持し、geometry(LineString)の各頂点がいつの位置かを示す情報を持たなかった。フロントエンド側で各頂点が直近60秒以内かどうかを判定する必要があり、直近値だけでは判別できないという指摘を受け、geometryの頂点順と1:1対応するtelemetryTimes(ISO8601日時文字列の配列)を追加した。配列は頂点順=時系列順(古い順、末尾が直近=latestTelemetryTimeと同一時刻)であることを前提とする。latestTelemetryTimelatestSpeedlatestDirection自体は直近値の参照用として維持し、置き換えは行わない。

α版でTO-BE(PR #29)へ寄せる際は、本APIの形状(uasId優先順フォールバック、uasEntityIduasIdの使い分け、latestSpeed/latestDirectionspeed/directionの命名差異、telemetryTimesによる頂点ごとの時刻表現)を起点として整合を取ることを推奨する。

6. 各APIの検索仕様と旧USS GeoServer API(CQLフィルタ)との対応

Section titled “6. 各APIの検索仕様と旧USS GeoServer API(CQLフィルタ)との対応”

新APIは検索条件をクエリパラメータではなくリクエストボディで指定する(POST + /search)。旧USSのGeoServer WFS APIはGETリクエストのcql_filterクエリパラメータで属性絞り込みを行っていた。両者の対応関係を、対象APIごとに示す。

6.1 飛行計画領域検索 — POST /api/v1/geo/flight-plan-area/search

Section titled “6.1 飛行計画領域検索 — POST /api/v1/geo/flight-plan-area/search”

旧API対応: MAP-GEO-001-001(飛行計画取得、if1_operationalintents)のis_managed=true相当のデータ。dipsFlightPlanIdフィルタのみMAP-GEO-009-001(DIPS飛行計画情報取得、if12_dips_flight_plan)のflight_plan_idと対応(下記参照)。

新API: FlightPlanAreaSearchRequestプロパティ旧API(if1_operationalintents)のCQLフィルタ対応関係
bbox該当パターンなし旧APIのCQLフィルタ仕様には空間範囲によるパターンが定義されていない(地図ビューア側でのWFSネイティブなbbox指定に依存していたと推測される)。新APIでは検索条件として明示化した。当初は必須項目としていたが、flightPlanIdによるID直接指定ユースケースでは不要なため任意項目に変更(flightPlanId未指定時は実質的に必須。両方省略した場合は範囲限定なしの検索となる)
currentTimeパターン1: start_time <= 【指定日時】 AND end_time >= 【指定日時】(指定時刻に有効な飛行計画を取得する)同一セマンティクス(planned_start_at <= currentTime AND planned_end_at >= currentTime)。プロパティ名をstart_time/end_timeからplannedStartAt/plannedEndAtに、validAt/asOf表記からcurrentTimeに統一
currentTimeFrom/currentTimeTo該当パターンなし新規追加。単一時点ではなく期間で「その期間内のいずれかの時点で有効な」計画を取得したいという要求に応え、currentTimeとは別に区間重なり判定(planned_start_at <= currentTimeTo AND planned_end_at >= currentTimeFrom)のペアパラメータを追加した。currentTimeと同時指定はしない
flightPlanIdパターン2: flight_plan_id = 【指定値】(指定した飛行計画を取得する)同一。指定時はbboxを省略可
dipsFlightPlanId該当パターンなし。強いて言えばMAP-GEO-009-001if12_dips_flight_plan)のCQLフィルタflight_plan_id = 【指定値】が同種のID(DIPS側の飛行計画ID)による絞り込みだが、if12_dips_flight_plan自体は別レイヤー(本APIの対象外、5.1参照)DIPS側の飛行計画IDによる検索・レスポンスへの反映に対応するため追加。FlightPlanAreaSearchRequest/FlightPlanAreaProperties(自組織向け)に加え、OtherFlightPlanAreaSearchRequest/OtherFlightPlanAreaProperties(他Operator向け、6.2参照)にも同様に追加し、bbox/flightPlanIdと同様に検索キーとしても使えるようにした
statusFlightPlanStatusFilter該当パターンなし(statusはレスポンスプロパティのみで旧APIの絞り込み対象外)新規追加のフィルタ
limit該当パターンなし。maxFeaturesクエリパラメータ(WFS標準機能、CQLフィルタではない)が同等の役割パラメータ名を変更し、デフォルト値(1000)・上限(10000)を明示
(該当なし)パターン3: is_managed = 【指定値】(指定した管理対象の飛行計画を取得する)is_managed属性はデータモデルから意図的に除外されている。本システムはRow-Level Security(RLS)を採用しており、レコードの可視性はクエリ実行時に評価されるセキュリティポリシーによって制御されるため

サンプルリクエスト

新API:

POST /api/v1/geo/flight-plan-area/search HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
{
"bbox": [139.7671, 35.6812, 139.8671, 35.7812],
"currentTime": "2023-05-02T12:00:00Z",
"status": ["ACTIVATED", "ACCEPTED"],
"limit": 500
}

旧API(GeoServer WFS、自組織分の例としてis_managed=trueを併用):

GET http://geoserver.service.geoserver:8080/geoserver/utm/ows?service=WFS&version=2.0.0&request=GetFeature&typeNames=utm%3Aif1_operationalintents&maxFeatures=500&outputFormat=application%2Fjson&exceptions=application%2Fjson&cql_filter=start_time%3C=2023-05-02T12:00:00Z+AND+end_time%3E=2023-05-02T12:00:00Z+AND+is_managed=true

新API(DIPS側の飛行計画IDで直接検索する例。指定時はbbox省略可):

POST /api/v1/geo/flight-plan-area/search HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
{
"dipsFlightPlanId": "AAAAAAAAAAAAAAAAAAA.FP20221125042709013.001"
}

なお、本APIの200レスポンスにはrouteareaType=ROUTEのLineString+そのbufferM分を可視化したPolygonの2フィーチャ)・polygonareaType=POLYGON+そのbufferM分を可視化したPolygonの2フィーチャ)・circleareaType=CIRCLE+そのbufferM分を可視化したPolygonの2フィーチャ)の3種類の名前付きレスポンス例(examples)をfrontend/geospatial.yaml側に定義しており、Scalar等のプレビューではドロップダウンで切り替えて確認できる。bufferMが設定されている計画は「元の形状のFeature(dataType=FLIGHT_PLAN)」と「水平方向にbufferM分だけ外側に膨らませたFeature(dataType=OPERATIONAL_INTENTareaTypeは元の値のまま、高度・時刻はFLIGHT_PLAN側と変化しない)」の2件で表現される。

6.2 飛行計画領域(他Operator)検索 — POST /api/v1/geo/flight-plan-area/others/search

Section titled “6.2 飛行計画領域(他Operator)検索 — POST /api/v1/geo/flight-plan-area/others/search”

旧API対応: MAP-GEO-001-001if1_operationalintents)のis_managed=false相当のデータ。dipsFlightPlanIdフィルタのみMAP-GEO-009-001if12_dips_flight_plan)のflight_plan_idと対応(6.1と同様、下記参照)。

新API: OtherFlightPlanAreaSearchRequestプロパティ旧API(if1_operationalintents)のCQLフィルタ対応関係
bbox該当パターンなし6.1と同様。当初必須だったが、flightPlanIdによるID直接指定ユースケースでは不要なため任意項目に変更(flightPlanId未指定時は実質的に必須)
currentTimeパターン1と同様6.1と同様
currentTimeFrom/currentTimeTo該当パターンなし6.1と同様
status該当パターンなし共通条件として受け取るが、他Operator計画は運航状態を持たないため絞り込みには使わない(FlightPlanStatusFilterのdescriptionに明記。持たない理由はflight-plan-er.mdの「他Operator計画のstatusは持たない」)
limit該当パターンなし6.1と同様
flightPlanIdパターン2相当運航調整のため特定の他Operator/他UTM計画を直接参照したいという要求に応え追加した(当初は「近傍の他Operatorの計画を一覧表示する」ユースケースのみを想定し単一計画IDでの絞り込みは非搭載としていたが、運航調整ユースケースでは特定計画の直接取得が必要なため搭載に変更。指定時はbboxを省略可)
dipsFlightPlanId該当パターンなし(6.1参照)6.1と同一理由・同一セマンティクスで他Operator向けにも追加した。OtherFlightPlanAreaPropertiescreatedBy/uasId等の内部IDは非公開のままだが、dipsFlightPlanIdはDIPSという外部システム上の識別子であり内部IDではないため、レスポンス(OtherFlightPlanAreaProperties.dipsFlightPlanId)にも公開する方針とした
(該当なし)パターン3: is_managed = 【指定値】6.1と同様

サンプルリクエスト

新API(近傍の他Operator計画を一覧表示する例):

POST /api/v1/geo/flight-plan-area/others/search HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
{
"bbox": [139.7671, 35.6812, 139.8671, 35.7812],
"currentTime": "2023-05-02T12:00:00Z"
}

新API(運航調整のため特定の他Operator計画をIDで直接取得する例。flightPlanId指定時はbbox省略可):

POST /api/v1/geo/flight-plan-area/others/search HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
{
"flightPlanId": "a2002e22-9207-4f8f-8118-925a35e17c41"
}

旧API(GeoServer WFS、他Operator分の例としてis_managed=falseを併用):

GET http://geoserver.service.geoserver:8080/geoserver/utm/ows?service=WFS&version=2.0.0&request=GetFeature&typeNames=utm%3Aif1_operationalintents&outputFormat=application%2Fjson&exceptions=application%2Fjson&cql_filter=start_time%3C=2023-05-02T12:00:00Z+AND+end_time%3E=2023-05-02T12:00:00Z+AND+is_managed=false

本APIの200レスポンスは、スキーマが6.1のFlightPlanAreaFeatureCollectionではなくOtherFlightPlanAreaFeatureCollectionである点と、名前付きレスポンス例がpolygon/circleの2パターンである点が6.1と異なる。DIPSの飛行計画参照APIが返す形状はCircle/Polygonのみで経路(ROUTE)に相当する区分を持たないため(flight_planning.dips_flight_plan_area_type)、areaType=ROUTE・バッファ幅(bufferM)・dataType=OPERATIONAL_INTENTはいずれも現れず、Featureは同一flightPlanIdにつき最大4件(dataType2種 × altitudeReference2種)になる。ただしaltitudeReference=WGS84の2件は、DIPSからの収集時点で地表標高データがカバーしていない場合・elevation.enabled=falseの場合は返却されない(OtherFlightPlanAreaFeatureのdescription参照。issue #271)。当初は6.1と同じrouteの例とbufferMを定義していたが、実データでは取りえないためPR #228で取り下げた。他Operator向けに公開可能な最小限のプロパティ(flightPlanIdplannedStartAt/plannedEndAt・高度系・areaType/dataType)のみを含み、createdBy(作成者のユーザーID)・uasId(使用UASのアセットID)等の内部IDは含まない(5.1参照)。statusはスキーマ上のプロパティとしては残るが常に未設定である(flight-plan-er.mdの「他Operator計画のstatusは持たない」参照)。

6.3 空域制限検索 — categoryごとの検索エンドポイント(POST /api/v1/geo/airspace-restriction/{category}/search

Section titled “6.3 空域制限検索 — categoryごとの検索エンドポイント(POST /api/v1/geo/airspace-restriction/{category}/search)”

旧API対応: MAP-GEO-004-001(規制空域取得、if4_constraint)。DID分は旧APIに存在しない(6.4参照)。

if4_constraintは単一レイヤーで、category相当の絞り込み自体が存在しなかった(constraint_typeはレスポンスプロパティのみ)。本APIでは、カテゴリごとに実際のデータソース・更新頻度・配信方式が異なりうる(例: DIPS_FPR由来のカテゴリとGSI/MANUAL由来のカテゴリでは更新特性が異なる)ため、DIDと同様にカテゴリごとに独立したエンドポイントとして設計している。これにより、カテゴリ単位でのキャッシュ方針・レート制限・将来的な配信方式変更(例: 特定カテゴリのみ静的配信化)を互いに影響させずに個別対応できる。

対象カテゴリと対応エンドポイント(AirspaceRestrictionTypeDENSELY_INHABITED_DISTRICT以外の8値と1対1対応):

categoryエンドポイント
AIRPORT_VICINITYPOST /api/v1/geo/airspace-restriction/airport/search
SMALL_UAV_PROHIBITION_RED_ZONEPOST /api/v1/geo/airspace-restriction/red-zone/search
SMALL_UAV_PROHIBITION_YELLOW_ZONEPOST /api/v1/geo/airspace-restriction/yellow-zone/search
ORDINANCE_DESIGNATED_AREAPOST /api/v1/geo/airspace-restriction/ordinance/search
MANNED_AIRCRAFT_TAKEOFF_LANDING_AREAPOST /api/v1/geo/airspace-restriction/manned-airport/search
EMERGENCY_OPERATIONS_AIRSPACEPOST /api/v1/geo/airspace-restriction/emergency/search
OTHER_1POST /api/v1/geo/airspace-restriction/other1/search
OTHER_2POST /api/v1/geo/airspace-restriction/other2/search

各エンドポイントのリクエストボディ(AirspaceRestrictionSearchRequest)は共通スキーマで、categoryはボディに含まない(エンドポイント自体がカテゴリを表す)。

新API: AirspaceRestrictionSearchRequestプロパティ旧API: if4_constraintのCQLフィルタ対応関係
bbox(必須)該当パターンなし6.1と同様の理由
validAtパターン1: start_date_time >= 【指定日時】 AND end_date_time <= 【指定日時】(指定日時範囲の規制空域を取得する)セマンティクスが異なる点に注意。 旧パターン1は「規制の有効期間が指定範囲[指定日時A, 指定日時B]に完全に収まるもの」を取得する“範囲内包”フィルタ(例: start_date_time>=2023-05-02T11:00:00Z and end_date_time<=2023-05-02T19:00:00Z)。一方、新APIのvalidAtは「指定した単一時刻に有効なもの」を取得する“時点包含”フィルタ(valid_from <= validAt AND valid_to >= validAt)であり、6.1のcurrentTime(飛行計画)と同じ考え方に統一している。旧MAP-GEO-006-001(GeoZone、if7_geo_zones)のvalid_from >= X and valid_to <= Yも同じ“範囲内包”方式であり、旧システムでは規制系レイヤーで共通の慣習だった点も踏まえ、意図的な仕様変更として申し送る
validFrom / validTo該当パターンなし新規追加。空域制限は飛行計画画面・テレメトリ画面の両方で表示する想定で、テレメトリ側はvalidAt(現在時刻の単一時点)で絞り込めるが、飛行計画側は「飛行開始時刻〜飛行終了時刻」という期間で絞り込みたい要求がある。単一時点のvalidAtでは表現できないため、6.1のcurrentTimeFrom/currentTimeToと同じ考え方(区間重なり判定: valid_from <= validTo AND valid_to >= validFrom)のペアパラメータを追加した。パラメータ名はcurrentTimeFrom/currentTimeToではなくvalidAtの命名に揃え、validFrom/validToとした。validAtと同時指定はしない
statusAirspaceRestrictionStatus該当パターンなし(旧APIにstatus概念自体が存在しない)データモデル側で新設した「取得元での存在状態」(ACTIVE/DISAPPEARED)軸に基づく新規フィルタ
limit該当パターンなし(maxFeaturesが同等)getFlightPlanArea系と同様にlimitが付与されている(getFlyingDronePositions側も同様)

サンプルリクエスト(レッドゾーンの例。他カテゴリも同一ボディ形式で、エンドポイントのみ異なる):

新API(テレメトリ画面向け。現在時刻の単一時点で絞り込む):

POST /api/v1/geo/airspace-restriction/red-zone/search HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
{
"bbox": [139.78, 35.55, 139.79, 35.56],
"validAt": "2023-05-02T12:00:00Z",
"limit": 1000
}

新API(飛行計画画面向け。飛行開始時刻〜飛行終了時刻の期間で絞り込む):

POST /api/v1/geo/airspace-restriction/red-zone/search HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
{
"bbox": [139.78, 35.55, 139.79, 35.56],
"validFrom": "2023-05-02T12:00:00Z",
"validTo": "2023-05-02T13:00:00Z",
"limit": 1000
}

複数カテゴリ(例: レッドゾーンとイエローゾーン)が必要な場合は、/red-zone/search/yellow-zone/searchをそれぞれ呼び出し、クライアント側で結果を合成する。

旧API(GeoServer WFS。categoryに相当する絞り込みは存在せず、validAtとはセマンティクスが異なる“範囲内包”フィルタである点に注意):

GET http://geoserver.service.geoserver:8080/geoserver/utm/ows?service=WFS&version=2.0.0&request=GetFeature&typeNames=utm%3Aif4_constraint&maxFeatures=1000&outputFormat=application%2Fjson&exceptions=application%2Fjson&cql_filter=start_date_time>=2023-05-02T11:00:00Z+and+end_date_time<=2023-05-02T19:00:00Z

6.4 空域制限(DID)PMTilesアーカイブ取得 — GET /static/tiles/airspace-restriction/did.pmtiles

Section titled “6.4 空域制限(DID)PMTilesアーカイブ取得 — GET /static/tiles/airspace-restriction/did.pmtiles”

旧API対応: なし(新規追加)uss/design/geoserver_api_spec/配下のいずれのGeoServer WFS APIにもDID(人口集中地区)を配信するレイヤーは存在しない。

設計の経緯(当初案からの修正): 当初はDIDをGET /api/v1/geo/airspace-restriction/did/{zoom}/{x}/{y}という個別タイル取得エンドポイントとして設計していたが、これはPMTilesという配信形式とAPIの形が食い違っていた。PMTilesは「サーバー側の処理を介さず、静的ファイルへのHTTP Range Requestだけで必要な範囲を取得できる」ことを前提としたファイルフォーマットであり、zoom/x/yごとにバックエンドがアーカイブ内部を解析して個別タイルを切り出す実装は、PMTiles本来の使い方に反し、不要な複雑さを持ち込むことが判明したため設計を修正した。新設計では、DIDのPMTilesアーカイブ(レイヤー名did固定)を単一の静的ファイルとして配信し、クライアント側のPMTilesリーダーがHTTP Range Requestで必要なバイト範囲のみを取得する(tile-serving-proto相当の配信方式)。バックエンド側でタイルを切り出す処理は不要になり、静的ファイルホスティング(CDN等)に配信を委ねられる。

認証・配信元: 静的ファイル配信・CDNキャッシュの活用を前提とし、他のAPIエンドポイントと異なりBearer認証を要求しない。配信元ホスト(CDN等)は本APIサーバーとは別ホストとなる想定だが、実際のインフラ構成(CDNプロバイダ、ドメイン等)は未確定であり別途確認が必要。frontend/geospatial.yaml側ではservers拡張でその旨を明記している。

Range Requestの契約: Rangeリクエストヘッダを指定した場合は206 Partial ContentContent-Range付き)、指定しない場合はファイル全体を200 OKで返す。指定された範囲がファイルサイズを超える等の不正な場合は416 Range Not Satisfiableを返す。Accept-Ranges: bytesをレスポンスヘッダとして返し、Range Requestに対応していることをクライアントに自己記述的に示す。

キャッシュ方針: アーカイブ内容はDIDデータの再生成時以外は不変であるため、200/206レスポンスにCache-Control(長期キャッシュ可、例:public, max-age=86400, immutable)・ETag(アーカイブバージョン識別子)ヘッダを付与し、リクエスト側のIf-None-Matchヘッダによる条件付きリクエストと、内容不変時の304 Not Modifiedレスポンスを維持する(当初案から引き継ぐ契約)。

サンプルリクエスト

新API(ファイル全体を取得する場合):

GET /static/tiles/airspace-restriction/did.pmtiles HTTP/1.1

新API(バイト範囲を指定して部分取得する場合。PMTilesリーダーがヘッダ部・該当タイルのみを取得する際に使用):

GET /static/tiles/airspace-restriction/did.pmtiles HTTP/1.1
Range: bytes=0-16383

旧API: 該当なし(新規追加のため対応する旧APIリクエストは存在しない)

6.5 飛行軌跡取得 — GET /api/v1/geo/telemetry/{flightPlanId}

Section titled “6.5 飛行軌跡取得 — GET /api/v1/geo/telemetry/{flightPlanId}”

旧API対応: MAP-GEO-003-001(飛行実績取得、if3_flightrecord)のパターン2。MAP-GEO-002-001(テレメトリ取得、if2_telemetry)ではない点に注意(下記参照)。

新API旧API: if3_flightrecordのCQLフィルタ対応関係
(対象外)パターン1: flight_plan_id = '【指定値】'(飛行計画全体のテレメトリー情報取得=飛行実績確認画面でのリクエスト)新APIの「飛行軌跡」は監視用途(直近60秒のみ)であり、事後の全期間の飛行実績確認は対象外(frontend/geospatial.yamlのタグ説明で「事後に配信される飛行実績とは別物」と明記)。全期間の飛行実績を扱うAPIは本仕様のスコープ外であり、別途検討が必要
flightPlanId(パスパラメータ) + 「直近60秒分」固定パターン2: flight_plan_id = 【指定値】 and telemetry_time >= 【現在日時 - 60秒】SORTBY=telemetry_time desc推奨)(選択した飛行計画の過去60秒間のテレメトリー情報取得=飛行状況監視画面で機体が選択された場合のリクエスト)同一ユースケース。旧APIでは汎用のcql_filterSORTBYパラメータの組み合わせで表現していた60秒ウィンドウを、新APIでは専用エンドポイント(クエリパラメータなし)として固定化した

サンプルリクエスト

新API:

GET /api/v1/geo/telemetry/a2002e22-9207-4f8f-8118-925a35e17c41 HTTP/1.1
Authorization: Bearer <token>

旧API(GeoServer WFS。現在時刻が2023-05-02T12:00:00Zの場合の直近60秒指定の例):

GET http://geoserver.service.geoserver:8080/geoserver/utm/ows?service=WFS&version=2.0.0&request=GetFeature&typeNames=utm%3Aif3_flightrecord&outputFormat=application%2Fjson&exceptions=application%2Fjson&cql_filter=flight_plan_id=%27a2002e22-9207-4f8f-8118-925a35e17c41%27+and+telemetry_time%3E=2023-05-02T11:59:00Z&sortBy=telemetry_time+D

6.6 現在位置一覧検索 — POST /api/v1/geo/telemetry/position/search

Section titled “6.6 現在位置一覧検索 — POST /api/v1/geo/telemetry/position/search”

旧API対応: MAP-GEO-002-001(テレメトリ取得、if2_telemetry)。

新API: FlyingDronePositionsSearchRequestプロパティ旧API: if2_telemetryのCQLフィルタ対応関係
bbox該当パターンなし6.1と同様の理由。当初は必須項目としていたが、特定機体の追跡ユースケース(flightPlanIds/uasEntityIdsによるID直接指定)では表示範囲が無関係なため任意項目に変更(ID未指定時は実質的に必須。いずれも省略した全件検索はanyOfで禁止し422。6.1・6.2と同じ書き方に揃えている。この書き方が破壊検知ツールに誤検知される点は7章参照)
flightPlanIdsパターンなし(旧APIはCQLフィルタ自体「特になし」)飛行計画IDで追跡対象を名指しするために追加。bboxとの併用時は和集合(下記参照)。上限100件
uasEntityIds該当パターンなし同上。飛行計画をまたいで同一機体を追い続ける場合に使用する。上限100件
status該当パターンなし新規追加のフィルタ。bbox・ID の和集合に対してANDで適用されるため、追跡目的では指定しない(状態遷移で追跡対象が消えるため)
limit該当パターンなし(maxFeaturesが同等)切り詰めはbbox由来の機体にのみ適用し、IDで名指しした機体は常に返す(追跡対象がbbox内の機体数に押し出されて消えないようにするため)。totalCountは和集合の全件数、truncatedbbox由来分が切り詰められたかを示す
currentTime該当パターンなし(旧APIはCQLフィルタ自体「特になし」=常に現在の全飛行中機体を返す)新APIで追加した任意時点スナップショット取得機能。取得元からの最終送信が古い機体を誤って返さないよう、バックエンド側で許容範囲(タイムアウト)を設ける想定。実装時に確認が必要な内部設計事項であり、OpenAPI記述には含めない

サンプルリクエスト

新API:

POST /api/v1/geo/telemetry/position/search HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
{
"bbox": [139.7671, 35.6812, 139.8671, 35.7812],
"status": ["ACTIVATED"],
"currentTime": "2023-05-02T12:00:00Z"
}

新API(特定の機体をIDで直接取得する例。ID指定時はbbox省略可):

POST /api/v1/geo/telemetry/position/search HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>
{
"flightPlanIds": ["a2002e22-9207-4f8f-8118-925a35e17c41"]
}

旧API(GeoServer WFS。CQLフィルタなし=常に現在の全飛行中機体を返す):

GET http://geoserver.service.geoserver:8080/geoserver/utm/ows?service=WFS&version=2.0.0&request=GetFeature&typeNames=utm%3Aif2_telemetry&maxFeatures=50&outputFormat=application%2Fjson&exceptions=application%2Fjson

6.7 現在位置(リアルタイム購読) — GET /api/v1/geo/events/telemetry(SSE)

Section titled “6.7 現在位置(リアルタイム購読) — GET /api/v1/geo/events/telemetry(SSE)”

旧API対応: 直接の対応なし。旧USSはGeoServer WFSによるポーリング取得のみで、プッシュ型のリアルタイム購読の仕組みを持たない。新APIで6.6(一覧取得・スナップショット)とは別に、継続的なライブ追跡向けにSSE購読エンドポイントを新設した。配信対象のうち更新のあった機体のみを1件ずつプッシュ配信する。

配信対象はbbox(表示範囲)とflightPlanIds/uasEntityIds(名指しした追跡対象)の和集合で決まり、6.6の検索APIと同じ意味論に揃えてある。クエリパラメータで指定するためbboxminLon,minLat,maxLon,maxLat、IDは各100件までのカンマ区切りとする(既存のbboxと同じstyle: form/explode: false)。いずれも指定しない場合は400を返す(全機体の無条件配信は許可しない)。EventSourceは接続中のURLを変更できないため、表示範囲の変更・追跡対象の追加削除はいずれも接続の張り直しで対応する。

既知のリスク(未解決): 本APIの前段にCDN(例: CloudFront)を配置する構成の場合、CDN側のResponse Completion Timeout(オリジンからのレスポンス完了までの上限時間)により、長時間張り続けるSSE接続が強制切断される可能性がある。定期的なハートビート(コメント行等)を送信しても、CDNの当該タイムアウトは「レスポンスが完了するまでの総時間」を制限するものであり、ハートビートの有無に関わらず一定時間で打ち切られる可能性がある点に注意(heartbeatによる回避を保証できない)。この点は現時点で未検証・未解決であり、クライアント側の再接続処理(本節冒頭の説明の通り)を前提とすることに加え、インフラ側でのCDN設定変更・タイムアウト延長・本エンドポイントのみCDNをバイパスする等の対応要否を別途検討する必要がある。

サンプルリクエスト

新API(表示範囲を見渡しながら、範囲外に出ても特定の機体を追い続ける例):

GET /api/v1/geo/events/telemetry?bbox=141.3806,43.1403,141.3960,43.1430&flightPlanIds=a2002e22-9207-4f8f-8118-925a35e17c41 HTTP/1.1
Accept: text/event-stream
Authorization: Bearer <token>

配信されるイベントの例(更新のあった機体1件ごとにGeoJSON Featureを1件配信):

event: message
data: <GeoJSON Featureを1行で。改行は入らない。内容は下記>

data:に載るFeatureを整形したもの:

{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
139.7671,
35.6812,
100
]
},
"properties": {
"uasId": "JU00012345",
"uasNickname": "PD4B",
"uasEntityId": "7c1e9a2b-3d4f-4b5a-8c6d-9e0f1a2b3c4d",
"flightPlanId": "a2002e22-9207-4f8f-8118-925a35e17c41",
"operatorId": "3f9a6b2c-8e1d-4a3b-9c5e-7d2f1b6a4e90",
"operatorName": "サンプルドローン株式会社",
"telemetryTime": "2023-05-02T12:00:00.000Z",
"speed": 20,
"speedUnit": "m/s",
"direction": 58,
"directionUnit": "degree",
"altitudeReference": "AGL",
"altitudeUnit": "m",
"altitudeMWgs84": 152.4,
"status": "ACTIVATED"
}
}

旧API: 該当なし(ポーリングのみのため、強いて言えば6.6の旧APIリクエストを一定間隔で繰り返し実行することが唯一の代替手段)

7. 旧USSとの主な仕様差異(申し送り事項)

Section titled “7. 旧USSとの主な仕様差異(申し送り事項)”

「6. 各APIの検索仕様」の対応表から横断的に見えてくる、旧USS GeoServer WFS APIとの主要な設計差異を整理する。

  • bbox(空間範囲)フィルタの明示化: 旧APIのCQLフィルタ仕様書群には空間範囲による絞り込みパターンが一切記載されておらず、地図ビューア側の実装(WFSネイティブのBBOXパラメータ等)に暗黙的に依存していたと推測される。新APIではbboxを検索条件として明示し、全ての一覧系検索APIで共通化した(当初はボディの必須プロパティとしていたが、ID直接指定のユースケースが出たため必須は解除した。下記および6.1・6.6参照)。
  • GET + cql_filter から POST + 検索ボディへ: 旧APIはGetFeatureリクエストのcql_filter文字列(CQL構文)で条件を組み立てる方式だったのに対し、新APIは構造化されたJSONリクエストボディに変更した(運航調整バックエンドAPIのPOST+/searchパターンに合わせた設計、docs/openapi/openapi_coordination_backend.yaml参照)。
  • is_managedフラグからエンドポイント分割へ: 旧APIの飛行計画取得(if1_operationalintents)・RemoteID取得(if5_remoteids)はis_managed(自USS管理/他USS管理)を検索条件・レスポンスの両方で扱っていたが、新APIでは飛行計画領域を自組織向け(6.1)・他Operator向け(6.2)の別エンドポイントに分割した。
  • 時点包含フィルタへの統一(currentTime/validAt: 飛行計画(if1)はもともと時点包含(start_time<=X AND end_time>=X)だったが、規制空域系レイヤー(if4start_date_time/end_date_timeif7valid_from/valid_to)は範囲内包(>=X AND <=Y)という異なる方式だった。新APIでは空域制限のvalidAtも時点包含方式に統一し、飛行計画・空域制限・現在位置の3系統すべてで同じ「指定時刻時点のスナップショット」という考え方に揃えた(6.3参照)。
  • DIDの新規追加: 旧USSには存在しなかったDID(人口集中地区、GSI提供)を、単一の静的PMTilesアーカイブ(レイヤー名did固定、HTTP Range Request配信)として新規に空域制限APIへ追加した。当初は個別タイル取得エンドポイント(GET .../did/{zoom}/{x}/{y})として設計していたが、PMTiles本来の配信方式(サーバー側処理を介さない静的Range Request配信)と食い違っていたため、単一静的ファイル配信に設計を修正した経緯がある(6.4)。
  • リアルタイム購読(SSE)の新規追加: 旧USSはポーリング取得のみだったのに対し、現在位置のプッシュ配信をSSEで新設した(6.7)。
  • 現在位置のID指定取得と「bboxとIDは和集合」の意味論: 当初、現在位置は一覧検索・SSEのいずれもbbox(表示範囲)のみを条件としており、飛行軌跡(flightPlanIdをパスで指定)や飛行計画領域検索(flightPlanId指定時はbbox省略可)と違って、特定の機体を名指しで取得する手段がなかった。フロントエンドから「地図の表示範囲と無関係に特定の機体を追い続けたい」という要望を受け、一覧検索(flightPlanIds/uasEntityIdsプロパティ)とSSE(同名のクエリパラメータ)の両方にID指定を追加し、ID指定時はbboxを省略可とした。 bboxとIDを併用した場合の意味論は和集合bbox範囲内の機体 + IDで名指しした機体)とする。AND(絞り込み)にすると「表示範囲外に出た追跡対象が消える」ため追跡用途で成立せず、複数機体を指定した場合はほぼ空集合になる。加えて、一覧検索とSSEで意味論を揃えることで、接続断からの再接続時に一覧検索で取得するスナップショットが購読中のストリームと同じ集合になることを保証できる(意味論が食い違うと、追跡対象が表示範囲外にいる間だけスナップショットから消え、次のイベントで復活するという不整合が生じる)。statuscurrentTimelimitはこの和集合に対してANDで適用する。 なお飛行計画領域検索(6.1・6.2)のflightPlanId/dipsFlightPlanIdは「指定した飛行計画のみ取得」という絞り込みの意味論のままであり、現在位置の一覧検索・SSEとは併用時の解釈が異なる。同種の要求(追跡中の計画領域を表示範囲外でも表示したい)が出た場合に、公開済み契約の意味変更としてフロントエンドの合意を取ってから統一する余地を残す。
  • bboxの必須解除はallOfanyOfで書く(破壊検知ツールの誤検知はラベルで通す): 既存スキーマの必須プロパティを任意化する場合、書き方によって生成コードが壊れる。素の$refbbox: {$ref: Bbox})のままrequiredから外すと、openapi-generatorは当該フィールドを空配列で初期化した非nullコンテナとして生成するため(private List<BigDecimal> bbox = new ArrayList<>())、BboxminItems: 4由来の@Size(min = 4, max = 4)に空配列が違反し、ID単独指定のリクエストがハンドラに到達する前に422で弾かれる。プロパティをインライン展開する書き方・$refに兄弟キーを足す書き方も同じ結果になる。allOfでラップした場合のみ@Nullableな非初期化フィールドとして生成され、意図どおり動く(6.1・6.2のFlightPlanAreaSearchRequestallOf合成であるためこの問題に当たっていない)。 一方で、既存スキーマへ後からallOf/anyOfを足す変更は、openapi-diff(2.1.7)が合成スキーマの変化を型変更(bbox (array -> array)(object -> object))と解釈して破壊的変更と誤判定する(requiredを緩める=受け付ける入力を広げる変更であり、実際には後方互換)。ゲートを緑にできる書き方はいずれも上記のとおり契約が壊れるため、生成コードの正しさを優先してallOfanyOfを採用し、誤検知はPRラベルbreaking-change-approvedで通す判断とした(ラベルは本来「利用者側の合意の記録」であるため、誤検知で付与する場合はPR本文に検証結果を残す)。
  • ID指定件数の上限と存在しないIDの扱い: flightPlanIds/uasEntityIdsは最初から配列とした(単一値で公開してから配列化するのは型変更=破壊的変更になるため、追加コストがほぼ無い時点で複数指定に対応させた)。上限は各100件で、SSEがクエリパラメータとして受けるためカンマ区切りのURL長がCDN/ロードバランサのURL長制限に収まる範囲に揃えている。存在しないID・飛行中でないIDを含んでも404やエラーとはせず、該当分が結果に現れないだけとする(追跡対象の飛行終了によって検索やSSE接続そのものが失敗しないようにするため)。空配列は「条件の指定なし」と同じ扱いとし、minItemsは設けない(追跡対象が0件の状態でもクライアントが同じリクエスト形を送れるようにするため。既存のstatusFlightPlanStatusFilter)にminItemsがないのと揃えた)。
  • 飛行軌跡と飛行実績の分離: 旧if3_flightrecordは「直近60秒」と「全期間」の両方を1つのレイヤー・CQLフィルタパターンの違いだけで提供していたが、新APIでは前者のみを「飛行軌跡」(監視用途)として独立させ、後者(事後の飛行実績確認)は明確にスコープ外とした(6.5)。
  • AMSL/WGS84高度の明確な分離: 旧if1_operationalintentsaltitude_amsl(HomePosition用)は、当初「海抜高度」として設計されたが、実体はWGS84楕円体高であったため後日ドキュメント上で訂正された経緯がある(真のAMSL=ジオイド基準の標高とは異なる)。新APIのFlightPlanAreaPropertiesでは、この混同を避けるためminAltitudeMAmsl/maxAltitudeMAmsl(真のAMSL)とminAltitudeMWgs84/maxAltitudeMWgs84(WGS84楕円体高)を明確に別プロパティとして追加した。いずれも領域あたりの代表値をカラムに保持する(登録・収集の時点でAGL高度と地表標高データから換算し、応答のたびに外部データを参照しない。5.1参照)。
  • 飛行計画領域の座標(Position)はAGL版・WGS84版の両方を提供: GeoJSON座標の3つ目の要素(高度)について、properties.altitudeReferenceAGL(対地高度)かWGS84(WGS84楕円体高)かを自己記述的に示し、同一の飛行計画・バッファ適用形状(同一flightPlanIddataTypeの組み合わせ)に対して両基準のFeatureをそれぞれ返却する。WGS84版は、バックエンド側が頂点ごとに AGL + 地表標高(ジオイド基準の標高)+ ジオイド高 を算出した楕円体高である(地表標高データは機能要求5.1.3.3により国土地理院DEM10B精度を最低保障・バイリニア補間。ジオイド高を加算しないと結果はAMSLになり、日本国内では約30〜40mの系統誤差となる)(地形に沿った3D表示を、クライアント側の地形データに頼らず実現できるようにするため)。Z値に用いる対地高度は、そのリング(線・面)が天面(天井)か床面かで決まり、areaTypedataTypeのいずれにも依存しない(天面はmaxAltitudeMAgl、床面はminAltitudeMAgl。床面を返すのはdataType=TOP_BOTTOM_3Dの下面リングのみのため、それ以外はすべて天面にあたる)。地形追従の有無もareaTypeによらない。AGL版は全頂点共通の単一値となるフラットな表現、WGS84版はareaTypeによらず頂点ごとに地表標高を反映した表現であり、地表が平坦な場所では結果として全頂点が同値になるだけである(フロントエンドから「areaTypeによって地形追従の有無が変わるのか」という照会を受けたため、OASのGeometryAirspaceRestrictionFeatureのdescriptionと、Polygon/Circleのレスポンス例にこの点を明記した)。また、dataType=OPERATIONAL_INTENTの垂直方向の範囲を3D表示できるよう、上面(天井)・下面(床面)を表す2枚のPolygonからなるMultiPolygonをdataType=TOP_BOTTOM_3Dとして別途提供する(WGS84版は各面が地形に追従するため平面にはならない)。高度関連プロパティが準拠する単位はaltitudeUnitで自己記述的に示す(現時点ではm固定)。minAltitudeMAmsl/minAltitudeMWgs84等は引き続き参考値として提供する。
  • Waypointごとの高度指定の廃止(垂直・時間方向バッファ、transitTimeの削除): DIPSへの通報は飛行計画全体で1つの高度しか扱えず、Waypointごとに高度をUTM側で入力・管理してもDIPSへ通報できず運航調整にも活用できないため、フロントエンドからの高度入力は飛行計画全体で1つ(最大高度)のみに変更した。これに伴い、Waypointごとの高度差・飛行時間を前提としたverticalBufferM(垂直方向バッファ)・timeBufferS(時間方向バッファ、旧if1_operationalintentsvertical_buffer/time_buffer相当)・transitTime(各WayPointの通過予定時刻、旧if1_operationalintentstransit_time相当)は不要となり削除した。UTM Step2中後期でASTMベースへの移行が検討されており、その際にWaypointごとの高度指定(および関連プロパティ)を復活させる想定である。
  • 空域制限は天面(ceiling)のみを提供し、床面は常に地表面に沿わせてクライアント側で表示する: 飛行計画領域と同じ天面・床面ペア方式(dataType=TOP_BOTTOM_3DのMultiPolygon 2リング)は、空域制限にはそのまま適用できない。空域制限はgeometryType=MULTIPOLYGON(1つの制限が複数の分離した区域からなる)ケースがあり、天面・床面をペアで持たせようとすると区域数に応じて要素数が可変になり、「どの要素が天面/床面か」「どの天面がどの床面と対になるか」を配列の順序だけから判別する方法がない(GeoJSONのMultiPolygon.coordinatesはグループ化・入れ子を表現できないため)。空域制限は地表から立ち上がるものとして扱い、床面は返却せず、常に地表であることを前提にクライアント側で地表面に沿わせて表示する。天面のみをAGL/WGS84両方のFeatureとして提供するのを基本形とし(2件にならない場合は5.2のaltitudeReference行を参照)、WGS84版は飛行計画領域と同様に実体化列(top_bottom_3d_geometry_wgs84geometry_wgs84)から生成する(airspace-er.mdの「WGS84基準の形状も実体化列で持つ」、5.2参照)。天面の高度は取得元が提供する値であり、取得元が高度を持たない場合と種別により高度の概念がない場合(レッドゾーン・イエローゾーン等)はminAltitudeMAgl/maxAltitudeMAglとも未設定になる(5.2参照)。
  • 途絶えた機体を現在位置から外すのはAPI側の責務とする: CURRENT_TELEMETRYは機体ごとに最新1件を上書きし続けるだけで、飛行が終わってテレメトリが途絶えても最後の1件が残る(telemetry-er.mdの「飛行終了後のカレントはデータモデルでは消さない」)。現在位置一覧・SSEはobserved_atが現在時刻から60秒以内のものだけを返し、それより古いものは返さない。旧USSも表示用のView(crid.if2_telemetry)がcurrent_timestamp - timestamp < 60で同じ制限をかけており、その方式を踏襲したものである。飛行軌跡が直近60秒に限られること(6.5)とも窓の長さを揃えている。
  • テレメトリもAGL/WGS84の両基準を提供する(旧USS由来のAGL固定の是正): 当初、テレメトリのAPI(飛行軌跡・現在位置一覧・SSE)はaltitudeReferenceAGLのみとしていたが、これは旧USSのif2_telemetryが対地高度を返していた出力形をそのまま踏襲したものであり、設計判断に基づくものではなかった。機能要求5.1.3.2「システム内の標高基準は楕円体高度とする」・5.1.3.3「ユーザーとのやり取りは対地高度を基準とする」は両基準を扱うことを前提としており、またテレメトリ入力(ASTM F3411 Remote ID)で常時得られるのは測地高度(楕円体高)で、対地高度のほうが地表標高データによる導出値である(主従が逆転していた)。フロントエンドから「AGLの機体位置をWGS84基準の飛行計画領域と突き合わせるには標高データによる換算が必要で、使用する標高データの違いで機体が領域からはみ出て見える」という指摘を受けたことを機に、両基準を提供する方針へ改めた。
  • 高度基準の表現方式はジオメトリの形で決める: 頂点ごとにZ値が変わるジオメトリ(LineString・Polygon)は、基準ごとにgeometryのZ値のみが異なるFeatureを分けて返す(飛行計画領域・空域制限・飛行軌跡)。単一点のジオメトリ(Point)はFeatureを分けず、他基準の高度を数値プロパティとして併記する(現在位置一覧・SSEのaltitudeMWgs84)。Pointを二重化しない理由は、現在位置は1機=1点をSSEで逐次配信するため配信量が倍になり、クライアント側で同一機体の重複除去(マーカーの二重表示防止)が必要になること、および点であればプロパティで同じ情報を表現できることによる。飛行軌跡はflightPlanId指定で返却が最大2件にとどまるため、二重化のコストが小さい。
  • 対地高度が得られない場合の応答方針: 対地高度は地表標高データ(DEM)参照による導出値であり、参照失敗・非対応地域では算出できない。この場合、現在位置(一覧・SSE)は当該FeatureのみaltitudeReference=WGS84としてgeometryのZ値に測地高度を入れて返す(位置情報そのものを落とさない)。飛行軌跡はAGLのFeatureを返さずWGS84の1件のみとする(欠測した頂点を間引くと軌跡の形状が変わるため)。対地高度の列と充填の契機はtelemetry-er.mdの「対地高度は受信時に充填する」が定める。取り込みのLambdaが高度変換を同梱し、受信時に導出して書き込むため、読み出し側では充填しない。DEMが無い地点の行はaltitude_agl_mがNULLのまま固定されるので、本節のWGS84へのフォールバックはその機体に対して継続的に起きる。
  • RFC 7946 §4(座標の第3要素は楕円体高)との差異は意図的な逸脱として維持する: RFC 7946 §4は座標の第3要素を「WGS84楕円体高」と規定する(SHALL)が、本APIはaltitudeReferenceで基準を自己記述し、AGL基準のFeatureでは対地高度をZ値に入れる。これは同規定からの逸脱であり、application/geo+jsonを名乗る以上、第3要素を楕円体高として解釈するクライアント(3D地図ライブラリ等)では高度がずれうる。設計・実装が既にこの前提で確定しており、Z値を楕円体高に統一するには飛行計画領域・空域制限を含めた根本的な見直しが必要になるため、逸脱を維持し、PositionAltitudeReferenceのdescriptionに差異を明記する方針とした(クライアントは必ずaltitudeReferenceを確認して解釈する)。
  • 地表標高データ(DEM)の参照手段はドメイン間で共有する: AGL⇔楕円体高の換算に用いる地表標高データは、機能要求5.1.3.3により国土地理院DEM10B精度を最低保障・バイリニア補間と規定されている。飛行計画領域・空域制限・テレメトリで別々のデータソースを持つ必要はなく、1つのDEM参照手段(データソース・キャッシュ方式)を共有する(telemetry-er.mdのDEM参照手段の未決事項と共通の依存として扱う)。換算に用いるDEMが領域側とテレメトリ側で異なると、同じ空間を表す値の間に系統的なズレが生じるため、共有は表示整合の前提でもある。
  • 飛行軌跡への頂点ごとの計測時刻(telemetryTimes)追加: TelemetryTrackPropertiesは当初latestTelemetryTime(直近値)のみを保持し、geometry(LineString)の各頂点がいつの位置かを示す手段がなかった。フロントエンド側で各頂点が直近60秒以内かどうかを判定するために、各頂点の計測時刻が必要という要望を受け、geometryの頂点順と1:1対応するtelemetryTimes(ISO8601日時文字列の配列、古い順)を追加した(5.3参照)。
  • limitによる切り詰めをクライアントが検知可能にする新規追加: 旧APIのmaxFeatures(WFS標準機能)はレスポンス自体に「全件数」や「切り詰められたか」を示す情報を含まず、クライアントは返却件数がmaxFeaturesちょうどであっても、検索条件に一致する全件を取得できたのか、上限で打ち切られたのかを区別できなかった。新APIではlimitを持つ全ての検索系エンドポイント(飛行計画領域・飛行計画領域(他Operator)・空域制限・現在位置一覧のFeatureCollection)のレスポンスにtotalCountlimit適用前の全件数)・truncatedlimitにより切り詰められたか)を追加し、クライアントが打ち切りを確実に検知し、bbox絞り込み等の再検索が必要かを判断できるようにした。
  • 時刻プロパティの精度方針(機能要求5.1.1.2「タイムスタンプは最低でも0.1秒の精度」への対応): utm-design-docsの機能要求にある「タイムスタンプ」は、システムが記録した事象発生時刻(本APIではtelemetryTime/latestTelemetryTime/telemetryTimes)を指すものと解釈し、この3プロパティのみミリ秒(小数点以下3桁)を含むISO8601形式で返却する。一方、plannedStartAt/plannedEndAt(飛行計画の予定開始・終了)やvalidAt/validFrom/validTo(空域制限の有効期間)は「予定・有効期間」を表す日時であり、DIPS側の日時仕様(飛行計画情報参照APIstartTime/finishTimeは分単位yyyyMMdd□HHmm、飛行禁止エリア情報取得APIstartTime/finishTimeは秒単位yyyy-MM-ddTHH:mm:ss)を踏まえても小数点秒を持たないため、同要求の対象外として秒単位のまま扱う。
  • DIPS由来の日時とタイムゾーン: DIPSの飛行禁止エリア情報取得API(startTime/finishTime)はレスポンスの日時にタイムゾーン指定子(Z/+09:00等)を含まず、仕様書上も明記がないが、DIPSへの過去の確認により日本時間(JST)であることを確認済み。新APIではAirspaceRestrictionProperties.validFrom/validToとしてUTCに正規化した値を返却する(5.2参照)。
  • DIPS飛行計画ID(dipsFlightPlanId)の検索・レスポンス対応: UTMのflightPlanId(UUID)とは別に、DIPSへの通報後にDIPS側で払い出される飛行計画ID(例: AAAAAAAAAAAAAAAAAAA.FP20221125042709013.001MAP-GEO-009-001/if12_dips_flight_planflight_plan_idと同種のID形式)でも検索・表示できるようにするため、自組織向け(FlightPlanAreaSearchRequest/FlightPlanAreaProperties、6.1参照)・他Operator向け(OtherFlightPlanAreaSearchRequest/OtherFlightPlanAreaProperties、6.2参照)の両方にdipsFlightPlanIdを追加した。他Operator向けにも公開する点はcreatedBy/uasId等の内部IDとは扱いを分けている(DIPSという外部システム上の識別子であり内部IDではないため)。 データモデル上はDIPS_REPORT.dips_receipt_noFLIGHT_PLANに対する最新のDIPS_REPORTレコードの値。定義はdocs/data-model/flight-plan-er.md参照)が対応する。カラム名は「受付番号」だが、格納する値はDIPS飛行計画登録APIレスポンスのflightPlanIdそのものであり、新規カラムの追加は不要(docs/data-model/flight-plan-field-mapping.mdの「飛行計画ID(DIPS)」項目・registerFlightPlanのレスポンス項目dipsFlightPlanIdと同一の値・出自)。