drone-camera 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +157 -2
- package/index.d.ts +51 -0
- package/index.d.ts.map +1 -0
- package/index.js +20474 -0
- package/index.js.map +1 -0
- package/index.umd.cjs +1361 -0
- package/index.umd.cjs.map +1 -0
- package/lib/drone-capture-manifest.d.ts +169 -0
- package/lib/drone-capture-manifest.d.ts.map +1 -0
- package/lib/drone-capture-panel.d.ts +135 -0
- package/lib/drone-capture-panel.d.ts.map +1 -0
- package/lib/drone-capture.d.ts +380 -0
- package/lib/drone-capture.d.ts.map +1 -0
- package/lib/drone-cesium-mission.d.ts +120 -0
- package/lib/drone-cesium-mission.d.ts.map +1 -0
- package/lib/drone-cesium-rig.d.ts +50 -0
- package/lib/drone-cesium-rig.d.ts.map +1 -0
- package/lib/drone-cesium.d.ts +519 -0
- package/lib/drone-cesium.d.ts.map +1 -0
- package/lib/drone-control.d.ts +188 -0
- package/lib/drone-control.d.ts.map +1 -0
- package/lib/drone-engine.d.ts +70 -0
- package/lib/drone-engine.d.ts.map +1 -0
- package/lib/drone-exif.d.ts +64 -0
- package/lib/drone-exif.d.ts.map +1 -0
- package/lib/drone-fly.d.ts +545 -0
- package/lib/drone-fly.d.ts.map +1 -0
- package/lib/drone-gallery.d.ts +146 -0
- package/lib/drone-gallery.d.ts.map +1 -0
- package/lib/drone-husky-model.d.ts +22 -0
- package/lib/drone-husky-model.d.ts.map +1 -0
- package/lib/drone-image-utils.d.ts +67 -0
- package/lib/drone-image-utils.d.ts.map +1 -0
- package/lib/drone-image-viewer.d.ts +97 -0
- package/lib/drone-image-viewer.d.ts.map +1 -0
- package/lib/drone-lights.d.ts +194 -0
- package/lib/drone-lights.d.ts.map +1 -0
- package/lib/drone-minimap.d.ts +155 -0
- package/lib/drone-minimap.d.ts.map +1 -0
- package/lib/drone-panel.d.ts +265 -0
- package/lib/drone-panel.d.ts.map +1 -0
- package/lib/drone-panorama-viewer.d.ts +162 -0
- package/lib/drone-panorama-viewer.d.ts.map +1 -0
- package/lib/drone-panorama.d.ts +242 -0
- package/lib/drone-panorama.d.ts.map +1 -0
- package/lib/drone-photogrammetry.d.ts +207 -0
- package/lib/drone-photogrammetry.d.ts.map +1 -0
- package/lib/drone-radar.d.ts +136 -0
- package/lib/drone-radar.d.ts.map +1 -0
- package/lib/drone-reconstruction-preview.d.ts +84 -0
- package/lib/drone-reconstruction-preview.d.ts.map +1 -0
- package/lib/drone-rig.d.ts +385 -0
- package/lib/drone-rig.d.ts.map +1 -0
- package/lib/drone-sim.d.ts +883 -0
- package/lib/drone-sim.d.ts.map +1 -0
- package/lib/drone-stitch.d.ts +84 -0
- package/lib/drone-stitch.d.ts.map +1 -0
- package/lib/drone-world.d.ts +194 -0
- package/lib/drone-world.d.ts.map +1 -0
- package/lib/mission-editor.d.ts +116 -0
- package/lib/mission-editor.d.ts.map +1 -0
- package/lib/mission-panel.d.ts +173 -0
- package/lib/mission-panel.d.ts.map +1 -0
- package/package.json +61 -4
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全景拍摄(180° / 360°)—— 大疆式网格扫描。
|
|
3
|
+
*
|
|
4
|
+
* 真机全景不是一个快门拍下来的:机体与云台按**预设网格**转到一串方位,逐张曝光,
|
|
5
|
+
* 相机内部把这一组照片拼成一张全景图。本模块复刻前半段(网格扫描 + 逐张落库),
|
|
6
|
+
* 拼接交给外部(见文件末尾的 `PanoramaStitcher`)—— 库内不做图像配准与融合。
|
|
7
|
+
*
|
|
8
|
+
* ── 网格怎么施加:水平靠**机体原地自转**,垂直靠云台俯仰 ──────────────────
|
|
9
|
+
*
|
|
10
|
+
* ⚠️ 这是本模块唯一容易做错的地方。Mini 4 Pro 的云台 Pan(水平转)机械行程只有
|
|
11
|
+
* **±30°**(本库 `DRONE_SPEC.gimbalYawRange` 按 ±5° 建模),而 180° 全景需要 ±90° 水平
|
|
12
|
+
* 视野 —— 云台根本转不出来。所以真机的做法是:
|
|
13
|
+
*
|
|
14
|
+
* - **水平**:飞行器定点悬停、**空间坐标不动、原地自转机身**(Yaw),每转到一个方位停下来;
|
|
15
|
+
* - **垂直**:云台只做俯仰分层(上 / 中 / 下),每层一张;
|
|
16
|
+
* - 180°:7 个方位 × 3 个俯仰 = 21 张;
|
|
17
|
+
* - 球形 360°:8 个方位;垂直层数按相机实际垂直视场自动计算,另拍天顶与天底。
|
|
18
|
+
*
|
|
19
|
+
* 一句话:**水平广角靠机身原地自转,垂直分层靠云台俯仰**。因此本模块的扫描循环
|
|
20
|
+
* 是「先转机身到这一列 → 再按行拍俯仰」,而不是"只转取景相机"。老款 Mavic 2 有大角度
|
|
21
|
+
* 云台 Pan,可以云台自己转着拍;Mini 系列不行。
|
|
22
|
+
*
|
|
23
|
+
* ── 三条设计约束 ──────────────────────────────────────────────────────
|
|
24
|
+
*
|
|
25
|
+
* - **只依赖 `CaptureService`**:转机身走 `spinBodyTo`(后端把目标航向交给飞控内核)、
|
|
26
|
+
* 俯仰覆盖走 `setCaptureView`(见 `captureVirtualImage` 的 `options.view`)。
|
|
27
|
+
* 模块本身既拿不到也不该拿渲染后端,换渲染器时一行都不用改。
|
|
28
|
+
* - **每张都带全景定位**:写进 `CapturedImage.metadata.panorama`(组 id / 模式 / 序号 /
|
|
29
|
+
* 总数 / 行列 / 该张的机身航向偏移与俯仰)。组内照片因此可被后端按 `group` 聚合、
|
|
30
|
+
* 按 `index` 排序,单独一张也仍是完整的影像条目(有位姿、有内参、可单独校验)。
|
|
31
|
+
* - **串行**:渲染后端的拍照是"一帧一张"的(上一张未取回时 `requestPhoto()` 会拒),
|
|
32
|
+
* 所以扫描必须等一张落地再动下一个方位,否则会丢帧。
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* const pano = new PanoramaCapture(captureService)
|
|
36
|
+
* pano.subscribe((p) => console.log(`${p.index}/${p.total}`))
|
|
37
|
+
* const result = await pano.start(session.id, 'pano-360') // 垂直层数按实际视场自适应
|
|
38
|
+
* pano.cancel() // 中途可停
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
import type { CaptureService, CapturedImage } from './drone-capture';
|
|
42
|
+
/** 全景模式 */
|
|
43
|
+
export type PanoramaMode = 'pano-wide' | 'pano-180' | 'pano-360';
|
|
44
|
+
/** 网格里的一个拍摄点 */
|
|
45
|
+
export interface PanoramaShotSpec {
|
|
46
|
+
/** 组内序号(1 起,按扫描顺序:先扫完一个机身方位,再转下一个) */
|
|
47
|
+
index: number;
|
|
48
|
+
/** 网格行列(0 起;row = 俯仰层, col = 机身水平方位) */
|
|
49
|
+
row: number;
|
|
50
|
+
col: number;
|
|
51
|
+
/** 该张的**机身航向偏移**(度,相对本组起始航向;正值 = 向右/顺时针) */
|
|
52
|
+
bodyYaw: number;
|
|
53
|
+
/** 该张的取景俯仰(度,相对水平面的绝对值) */
|
|
54
|
+
pitch: number;
|
|
55
|
+
}
|
|
56
|
+
/** 全景预设 */
|
|
57
|
+
export interface PanoramaPreset {
|
|
58
|
+
mode: PanoramaMode;
|
|
59
|
+
label: string;
|
|
60
|
+
/** 纵向拍摄层数(含球形模式单独补拍的天顶/天底) */
|
|
61
|
+
rows: number;
|
|
62
|
+
/** 机身水平方位数(每一列要原地自转一次) */
|
|
63
|
+
cols: number;
|
|
64
|
+
/** 环拍网格每层的取景俯仰(度);按从上到下排列 */
|
|
65
|
+
rowPitches: number[];
|
|
66
|
+
/** 第一列的机身偏航(度,相对起始航向) */
|
|
67
|
+
bodyYawStart: number;
|
|
68
|
+
/** 每列之间的机身偏航步进(度) */
|
|
69
|
+
bodyYawStep: number;
|
|
70
|
+
/**
|
|
71
|
+
* 扫描结束时机身应停在的偏航(度,相对起始航向)。
|
|
72
|
+
* 180° 网格停在 +90°(就是最后一列);球形 360° 补完天底后回到起始航向。
|
|
73
|
+
*/
|
|
74
|
+
finalBodyYaw: number;
|
|
75
|
+
/** 全部拍摄点(按扫描顺序:列优先) */
|
|
76
|
+
shots: PanoramaShotSpec[];
|
|
77
|
+
total: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 广角采用 3×3 网格(9 张);180° 采用 7×3 网格(21 张);
|
|
81
|
+
* 球形 360° 采用 8 个方位;俯仰层数按相机实际垂直视场自动计算,并补天顶/天底。
|
|
82
|
+
*
|
|
83
|
+
* - 广角:机身方位 -30°/0°/+30°,每个方位拍 +20°/0°/-20°,共 9 张;
|
|
84
|
+
* - 180°:机身从 -90° 转到 +90°(共 180°),7 个方位 × 3 层 = 21 张,拍完就停在 +90°;
|
|
85
|
+
* - 360° 球形:8 个方位(0°~315°,步进 45°);俯仰层根据实际垂直视场布满 -90°~+90°,
|
|
86
|
+
* 相邻层中心距不超过垂直 FOV 的 60%,再补天顶/天底;拍完机身回到起始航向。
|
|
87
|
+
*
|
|
88
|
+
* 垂直环拍步长按实际垂直 FOV 计算:中心间距最大为 FOV×0.6,保留至少 40% 理论重叠,
|
|
89
|
+
* 避免宽屏窄垂直视场下固定步长留下整圈未覆盖纬度带。
|
|
90
|
+
* 额外的天顶与天底照片覆盖球面两极,而不是依赖合成器把最近边缘像素拉伸过去。
|
|
91
|
+
* 360° 用 45° 方位步进;默认 Cesium 水平视场约 60°,仍有约 15° 水平重叠。
|
|
92
|
+
*/
|
|
93
|
+
export declare const PANORAMA_PRESETS: Record<PanoramaMode, PanoramaPreset>;
|
|
94
|
+
/** 供 UI 渲染的稳定顺序 */
|
|
95
|
+
export declare const PANORAMA_MODE_LIST: PanoramaMode[];
|
|
96
|
+
/** 全景扫描状态 */
|
|
97
|
+
export type PanoramaState = 'idle' | 'running' | 'done' | 'cancelled' | 'failed';
|
|
98
|
+
/** 扫描进度(面板订阅它做展示) */
|
|
99
|
+
export interface PanoramaProgress {
|
|
100
|
+
state: PanoramaState;
|
|
101
|
+
mode: PanoramaMode;
|
|
102
|
+
/** 已完成张数 */
|
|
103
|
+
index: number;
|
|
104
|
+
total: number;
|
|
105
|
+
/** 当前(或刚完成)的网格位置 */
|
|
106
|
+
row: number;
|
|
107
|
+
col: number;
|
|
108
|
+
/** 当前列的机身航向偏移(度,相对起始航向) */
|
|
109
|
+
bodyYaw: number;
|
|
110
|
+
pitch: number;
|
|
111
|
+
/** 组 id(开始拍摄后才有) */
|
|
112
|
+
group: string | null;
|
|
113
|
+
message?: string;
|
|
114
|
+
}
|
|
115
|
+
/** 一组全景照片(交给拼接器) */
|
|
116
|
+
export interface PanoramaGroup {
|
|
117
|
+
id: string;
|
|
118
|
+
mode: PanoramaMode;
|
|
119
|
+
sessionId: string;
|
|
120
|
+
/** 按组内序号排序 */
|
|
121
|
+
images: CapturedImage[];
|
|
122
|
+
}
|
|
123
|
+
/** 拼接产物(库里只搬运,不解释) */
|
|
124
|
+
export interface PanoramaStitchResult {
|
|
125
|
+
/** 可直接显示的地址(blob: / http: / data:);以字符串打开时按标准整球解释 */
|
|
126
|
+
url?: string;
|
|
127
|
+
/** 可选的覆盖热力图:红=无照片覆盖,黄=单张覆盖,绿=多张重叠 */
|
|
128
|
+
diagnosticUrl?: string;
|
|
129
|
+
/** 覆盖热力图像素占比;未覆盖区域必须由拼接器补边,存在视差风险区域通常只被一张照片覆盖 */
|
|
130
|
+
diagnosticCoverage?: {
|
|
131
|
+
uncovered: number;
|
|
132
|
+
single: number;
|
|
133
|
+
overlap: number;
|
|
134
|
+
};
|
|
135
|
+
/** 也可以直接给二进制,由宿主决定怎么用 */
|
|
136
|
+
blob?: Blob;
|
|
137
|
+
width?: number;
|
|
138
|
+
height?: number;
|
|
139
|
+
name?: string;
|
|
140
|
+
/**
|
|
141
|
+
* 有效覆盖比例(0~1) —— 拼接后画面里"真的有像素"的部分占比。
|
|
142
|
+
* 库内自带拼接器(见 drone-stitch)会填;宿主自己的拼接器可以不填。
|
|
143
|
+
* 拿它判断"这组是不是拍漏了"(比如中途没转到位,角落空一块)。
|
|
144
|
+
*/
|
|
145
|
+
coverage?: number;
|
|
146
|
+
/** 局部全景带的球面范围;缺省表示标准 360°×180° 整球。 */
|
|
147
|
+
equirectangular?: {
|
|
148
|
+
thetaStart: number;
|
|
149
|
+
spanTheta: number;
|
|
150
|
+
phiTop: number;
|
|
151
|
+
spanPhi: number;
|
|
152
|
+
wrapsTheta: boolean;
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* 拼接器接口 —— **库内不提供实现**,由宿主注入(后端服务、WASM 拼接库、离线工具都行)。
|
|
157
|
+
* 整组拍完(未取消)后自动调用一次;返回 null 表示"这次不拼"。
|
|
158
|
+
*/
|
|
159
|
+
export interface PanoramaStitcher {
|
|
160
|
+
/** 把一组已拍照片拼成等距柱状全景(按位姿反投影;覆盖不足返回 null) */
|
|
161
|
+
stitch(group: PanoramaGroup): Promise<PanoramaStitchResult | null>;
|
|
162
|
+
}
|
|
163
|
+
/** 一次扫描的最终结果 */
|
|
164
|
+
export interface PanoramaResult {
|
|
165
|
+
group: string;
|
|
166
|
+
mode: PanoramaMode;
|
|
167
|
+
total: number;
|
|
168
|
+
/** 实际入库张数(成片失败会少于 total) */
|
|
169
|
+
captured: number;
|
|
170
|
+
cancelled: boolean;
|
|
171
|
+
/** 没能完成的原因(机体没起飞 / 后端不支持自转 / 机身转不到位),成功时为 undefined */
|
|
172
|
+
error?: string;
|
|
173
|
+
/** 拼接产物(注入过拼接器且未取消时才有) */
|
|
174
|
+
stitched?: PanoramaStitchResult | null;
|
|
175
|
+
}
|
|
176
|
+
/** `PanoramaCapture` 构造选项 */
|
|
177
|
+
export interface PanoramaCaptureOptions {
|
|
178
|
+
/**
|
|
179
|
+
* 每张之间的间隔(毫秒),默认 0(拍完立即转下一个方位)。
|
|
180
|
+
* 想更贴近真机节奏、或给渲染后端留稳定时间时调大(真机每张约 0.5~1s)。
|
|
181
|
+
*/
|
|
182
|
+
shotIntervalMs?: number;
|
|
183
|
+
/**
|
|
184
|
+
* 等待机身转到位的最长时间(毫秒),默认 8000。
|
|
185
|
+
* 超时即判定"转不过去"(没起飞、正在返航、速度倍率为 0),以失败收尾而不是硬拍。
|
|
186
|
+
*/
|
|
187
|
+
spinTimeoutMs?: number;
|
|
188
|
+
/** 拼接器(可选) */
|
|
189
|
+
stitcher?: PanoramaStitcher | null;
|
|
190
|
+
/** 整组拍完并完成拼接后的回调(宿主落盘 / 提示用) */
|
|
191
|
+
onStitched?: (result: PanoramaStitchResult | null, group: PanoramaGroup) => void;
|
|
192
|
+
}
|
|
193
|
+
/** 根据相机垂直 FOV 生成覆盖两极的俯仰层,相邻层中心距不超过 FOV 的 60%。 */
|
|
194
|
+
export declare function sphericalPitchGrid(verticalFovDeg: number): number[];
|
|
195
|
+
/**
|
|
196
|
+
* 全景扫描器:先转机身到方位、再按俯仰层逐张取景拍摄,把每张登记进 `CaptureService` 的会话。
|
|
197
|
+
*
|
|
198
|
+
* 只依赖 `CaptureService` —— 转机身走 `spinBodyTo` / `getBodyHeading`,俯仰覆盖由服务在每张
|
|
199
|
+
* 内部设置并复位(见 `CaptureService.captureVirtualImage` 的 `options.view`),
|
|
200
|
+
* 这里既拿不到也不该拿渲染后端,于是换渲染器时本模块一行都不用改。
|
|
201
|
+
*/
|
|
202
|
+
export declare class PanoramaCapture {
|
|
203
|
+
private readonly capture;
|
|
204
|
+
private readonly listeners;
|
|
205
|
+
private options;
|
|
206
|
+
/** 取消令牌:自增即让正在跑的扫描退出 */
|
|
207
|
+
private token;
|
|
208
|
+
private current;
|
|
209
|
+
/** 构造全景扫描器:按俯仰分层 × 机体自转覆盖 360° */
|
|
210
|
+
constructor(capture: CaptureService, options?: PanoramaCaptureOptions);
|
|
211
|
+
/** 是否正在扫描 */
|
|
212
|
+
get running(): boolean;
|
|
213
|
+
/** 当前进度快照(未拍摄过返回 null) */
|
|
214
|
+
get progress(): PanoramaProgress | null;
|
|
215
|
+
/** 订阅进度变化;返回退订函数 */
|
|
216
|
+
subscribe(listener: (progress: PanoramaProgress) => void): () => void;
|
|
217
|
+
/** 设置 / 替换拼接器(传 null 关闭) */
|
|
218
|
+
setStitcher(stitcher: PanoramaStitcher | null): void;
|
|
219
|
+
/** 取预设(UI 展示行列数 / 张数用) */
|
|
220
|
+
static preset(mode: PanoramaMode, verticalFovDeg?: number): PanoramaPreset;
|
|
221
|
+
/**
|
|
222
|
+
* 开始一次扫描。已在扫描中、或会话不存在时返回 null(不排队,避免误触连发)。
|
|
223
|
+
*
|
|
224
|
+
* 成片失败(如后端某一帧相机未就绪)只计入 `captured` 的缺口,不中断整组 ——
|
|
225
|
+
* 少一张的代价远小于让用户重拍一整组;但**机身转不到位**是另一回事:那说明网格根本没
|
|
226
|
+
* 施加成功(没起飞 / 正在返航 / 速度倍率为 0),继续拍只会得到一堆同一方位的废片,
|
|
227
|
+
* 所以立即以失败收尾。
|
|
228
|
+
*/
|
|
229
|
+
start(sessionId: string, mode: PanoramaMode): Promise<PanoramaResult | null>;
|
|
230
|
+
/** 请求停止当前扫描(当前那一张会拍完再退出) */
|
|
231
|
+
cancel(): void;
|
|
232
|
+
/** 按组 id 从会话里聚合已拍的照片(按序号排序)—— 拼接器与导出都用它 */
|
|
233
|
+
buildGroup(sessionId: string, group: string, mode: PanoramaMode): PanoramaGroup | null;
|
|
234
|
+
/**
|
|
235
|
+
* 等机身转到目标方位(轮询真值,而不是假设"下一条命令必然到位")。
|
|
236
|
+
* 轮询间隔 16 ms、每个方位最多等 `spinTimeoutMs` —— 一帧的转角只有 1~2°,
|
|
237
|
+
* 所以这里的等待粒度对结果没有影响,只影响进度播报的平滑度。
|
|
238
|
+
*/
|
|
239
|
+
private awaitHeading;
|
|
240
|
+
private setProgress;
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=drone-panorama.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drone-panorama.d.ts","sourceRoot":"","sources":["../../src/lib/drone-camera/drone-panorama.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Photogrammetry helpers that do not depend on Cesium, Three, the DOM, or Node.
|
|
3
|
+
*
|
|
4
|
+
* The capture side stores Cesium positions in ECEF and local positions in ENU.
|
|
5
|
+
* This module keeps that convention explicit so a reconstruction worker can use
|
|
6
|
+
* the same values as the browser without importing a renderer.
|
|
7
|
+
*/
|
|
8
|
+
export type Vector3 = [number, number, number];
|
|
9
|
+
export type Quaternion = [number, number, number, number];
|
|
10
|
+
export interface CameraPoseLike {
|
|
11
|
+
position: Vector3;
|
|
12
|
+
rotation: Quaternion;
|
|
13
|
+
coordinateFrame: 'ecef' | 'local-enu' | 'project-local' | string;
|
|
14
|
+
}
|
|
15
|
+
export interface ColmapCameraPose {
|
|
16
|
+
/** Camera centre in the reconstruction local frame, metres. */
|
|
17
|
+
position: Vector3;
|
|
18
|
+
/** Camera-local-to-world quaternion in COLMAP/OpenCV axes, [x,y,z,w]. */
|
|
19
|
+
rotation: Quaternion;
|
|
20
|
+
/** World-to-camera quaternion for COLMAP images.txt, [w,x,y,z]. */
|
|
21
|
+
qvec: [number, number, number, number];
|
|
22
|
+
/** World-to-camera translation for COLMAP images.txt: -R * position. */
|
|
23
|
+
tvec: Vector3;
|
|
24
|
+
coordinateFrame: 'local-enu' | 'project-local';
|
|
25
|
+
rotationConvention: 'camera-local-to-world; COLMAP +X right, +Y down, +Z forward';
|
|
26
|
+
}
|
|
27
|
+
/** WGS84 geodetic coordinate. Angles are degrees and altitude is metres. */
|
|
28
|
+
export interface GeodeticCoordinate {
|
|
29
|
+
longitude: number;
|
|
30
|
+
latitude: number;
|
|
31
|
+
altitude?: number;
|
|
32
|
+
}
|
|
33
|
+
/** WGS84 ellipsoid constants used by all ECEF/ENU conversions. */
|
|
34
|
+
export declare const WGS84: {
|
|
35
|
+
readonly semiMajorAxis: 6378137;
|
|
36
|
+
readonly inverseFlattening: 298.257223563;
|
|
37
|
+
readonly flattening: number;
|
|
38
|
+
readonly eccentricitySquared: number;
|
|
39
|
+
};
|
|
40
|
+
export interface EcefEnuFrame {
|
|
41
|
+
/** Origin expressed as the input geodetic coordinate. */
|
|
42
|
+
readonly origin: GeodeticCoordinate;
|
|
43
|
+
/** Origin expressed in ECEF metres. */
|
|
44
|
+
readonly ecefOrigin: Vector3;
|
|
45
|
+
/** Unit axes expressed in ECEF: east, north, up. */
|
|
46
|
+
readonly east: Vector3;
|
|
47
|
+
readonly north: Vector3;
|
|
48
|
+
readonly up: Vector3;
|
|
49
|
+
/** Quaternion rotating ENU vectors into ECEF vectors, [x,y,z,w]. */
|
|
50
|
+
readonly enuToEcefRotation: Quaternion;
|
|
51
|
+
}
|
|
52
|
+
/** Convert WGS84 longitude/latitude/altitude to Earth-centred Earth-fixed metres. */
|
|
53
|
+
export declare function geodeticToEcef(coordinate: GeodeticCoordinate): Vector3;
|
|
54
|
+
/** Convert ECEF metres to WGS84 longitude/latitude/altitude. */
|
|
55
|
+
export declare function ecefToGeodetic(position: Vector3): GeodeticCoordinate;
|
|
56
|
+
/** Build an ENU frame at a WGS84 geodetic origin. ENU is [east, north, up]. */
|
|
57
|
+
export declare function createEcefEnuFrame(origin: GeodeticCoordinate): EcefEnuFrame;
|
|
58
|
+
/** Convert an ECEF point to ENU metres relative to a frame. */
|
|
59
|
+
export declare function ecefToEnu(position: Vector3, frame: EcefEnuFrame): Vector3;
|
|
60
|
+
/** Convert ENU metres relative to a frame to an ECEF point. */
|
|
61
|
+
export declare function enuToEcef(position: Vector3, frame: EcefEnuFrame): Vector3;
|
|
62
|
+
/** Convert an ENU orientation quaternion to the same orientation in ECEF. */
|
|
63
|
+
export declare function enuQuaternionToEcef(rotation: Quaternion, frame: EcefEnuFrame): Quaternion;
|
|
64
|
+
/** Convert an ECEF orientation quaternion to the same orientation in ENU. */
|
|
65
|
+
export declare function ecefQuaternionToEnu(rotation: Quaternion, frame: EcefEnuFrame): Quaternion;
|
|
66
|
+
/**
|
|
67
|
+
* Camera-local axis conventions used by common reconstruction/rendering tools.
|
|
68
|
+
* `colmap` and `opencv` use +X right, +Y down, +Z forward. Three's camera uses
|
|
69
|
+
* +X right, +Y up, -Z forward. Cesium's camera uses +X right, +Y up, -Z forward
|
|
70
|
+
* for its view direction; Cesium HPR values still need their own heading/pitch
|
|
71
|
+
* semantics and should not be written directly as a COLMAP quaternion.
|
|
72
|
+
*/
|
|
73
|
+
export type CameraAxisConvention = 'colmap' | 'opencv' | 'three' | 'cesium';
|
|
74
|
+
export interface CameraWorldBasis {
|
|
75
|
+
/** Camera +X axis in the world (usually the view's right vector). */
|
|
76
|
+
right: Vector3;
|
|
77
|
+
/** Camera visual up axis in the world. */
|
|
78
|
+
up: Vector3;
|
|
79
|
+
/** Camera optical forward direction in the world. */
|
|
80
|
+
forward: Vector3;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build a camera-local-to-world quaternion from rendered camera basis vectors.
|
|
84
|
+
* This is useful for Cesium, where `directionWC`/`upWC` are available at the
|
|
85
|
+
* exact frame that is copied to a PNG. The returned quaternion uses the chosen
|
|
86
|
+
* camera convention and is safe to write to a manifest.
|
|
87
|
+
*/
|
|
88
|
+
export declare function cameraQuaternionFromBasis(basis: CameraWorldBasis, convention?: CameraAxisConvention): Quaternion;
|
|
89
|
+
/** Convert a camera pose quaternion while preserving its optical axis meaning. */
|
|
90
|
+
export declare function convertCameraQuaternion(rotation: Quaternion, from: CameraAxisConvention, to: CameraAxisConvention): Quaternion;
|
|
91
|
+
/**
|
|
92
|
+
* Convert a captured pose into the local camera convention expected by a
|
|
93
|
+
* COLMAP/OpenCV reconstruction worker. This is the explicit ECEF→ENU and
|
|
94
|
+
* camera-axis boundary; callers must not write Cesium HPR values directly to
|
|
95
|
+
* a COLMAP pose file.
|
|
96
|
+
*/
|
|
97
|
+
export declare function cameraPoseToColmap(pose: CameraPoseLike, options?: {
|
|
98
|
+
enuFrame?: EcefEnuFrame;
|
|
99
|
+
sourceCameraConvention?: CameraAxisConvention;
|
|
100
|
+
}): ColmapCameraPose;
|
|
101
|
+
/** Minimal 3D Tiles JSON shape used by validation and loading helpers. */
|
|
102
|
+
export interface TilesetNode {
|
|
103
|
+
boundingVolume?: {
|
|
104
|
+
box?: unknown;
|
|
105
|
+
region?: unknown;
|
|
106
|
+
sphere?: unknown;
|
|
107
|
+
};
|
|
108
|
+
geometricError?: number;
|
|
109
|
+
refine?: 'ADD' | 'REPLACE' | string;
|
|
110
|
+
transform?: number[];
|
|
111
|
+
content?: {
|
|
112
|
+
uri?: string;
|
|
113
|
+
url?: string;
|
|
114
|
+
[key: string]: unknown;
|
|
115
|
+
};
|
|
116
|
+
/** 3D Tiles 1.1 may attach more than one content payload to a node. */
|
|
117
|
+
contents?: Array<{
|
|
118
|
+
uri?: string;
|
|
119
|
+
url?: string;
|
|
120
|
+
[key: string]: unknown;
|
|
121
|
+
}>;
|
|
122
|
+
children?: TilesetNode[];
|
|
123
|
+
[key: string]: unknown;
|
|
124
|
+
}
|
|
125
|
+
export interface TilesetJson {
|
|
126
|
+
asset?: {
|
|
127
|
+
version?: string;
|
|
128
|
+
[key: string]: unknown;
|
|
129
|
+
};
|
|
130
|
+
geometricError?: number;
|
|
131
|
+
root?: TilesetNode;
|
|
132
|
+
properties?: Record<string, unknown>;
|
|
133
|
+
[key: string]: unknown;
|
|
134
|
+
}
|
|
135
|
+
export interface TilesetValidationStats {
|
|
136
|
+
nodes: number;
|
|
137
|
+
contentUris: number;
|
|
138
|
+
boundingVolumes: number;
|
|
139
|
+
maxDepth: number;
|
|
140
|
+
}
|
|
141
|
+
export interface TilesetValidationResult {
|
|
142
|
+
valid: boolean;
|
|
143
|
+
errors: string[];
|
|
144
|
+
warnings: string[];
|
|
145
|
+
stats: TilesetValidationStats;
|
|
146
|
+
}
|
|
147
|
+
/** Validate the structural parts Cesium needs before attempting a tileset load. */
|
|
148
|
+
export declare function validateTileset(tileset: unknown): TilesetValidationResult;
|
|
149
|
+
export interface CesiumTilesetLoader<T> {
|
|
150
|
+
/** Adapter supplied by the host, typically Cesium3DTileset.fromUrl. */
|
|
151
|
+
load(url: string): Promise<T> | T;
|
|
152
|
+
}
|
|
153
|
+
export interface CesiumTilesetLoadResult<T> {
|
|
154
|
+
url: string;
|
|
155
|
+
tileset: T;
|
|
156
|
+
validation?: TilesetValidationResult;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Load a tileset through an injected Cesium adapter. No Cesium symbol is
|
|
160
|
+
* imported or referenced, so this helper also works in workers and tests.
|
|
161
|
+
*/
|
|
162
|
+
export declare function loadCesiumTileset<T>(url: string, loader: CesiumTilesetLoader<T> | ((url: string) => Promise<T> | T), options?: {
|
|
163
|
+
validate?: (url: string) => Promise<TilesetValidationResult> | TilesetValidationResult;
|
|
164
|
+
}): Promise<CesiumTilesetLoadResult<T>>;
|
|
165
|
+
/** Verbose alias for applications that prefer the generic name. */
|
|
166
|
+
export declare const loadTilesetForCesium: typeof loadCesiumTileset;
|
|
167
|
+
export interface ReconstructionTaskPaths {
|
|
168
|
+
captureDir: string;
|
|
169
|
+
imagesDir: string;
|
|
170
|
+
manifestPath: string;
|
|
171
|
+
validationPath: string;
|
|
172
|
+
reconstructionDir: string;
|
|
173
|
+
colmapDir: string;
|
|
174
|
+
sparseDir: string;
|
|
175
|
+
denseDir: string;
|
|
176
|
+
meshDir: string;
|
|
177
|
+
outputDir: string;
|
|
178
|
+
tilesetPath: string;
|
|
179
|
+
reportPath: string;
|
|
180
|
+
}
|
|
181
|
+
export interface ReconstructionTask {
|
|
182
|
+
captureId: string;
|
|
183
|
+
createdAt: string;
|
|
184
|
+
paths: ReconstructionTaskPaths;
|
|
185
|
+
coordinateFrame: 'ecef' | 'local-enu' | 'project-local';
|
|
186
|
+
status: 'created' | 'running' | 'succeeded' | 'failed';
|
|
187
|
+
}
|
|
188
|
+
export interface ReconstructionReport {
|
|
189
|
+
captureId: string;
|
|
190
|
+
status: 'succeeded' | 'failed' | 'partial';
|
|
191
|
+
stage: 'validate-images' | 'feature-extraction' | 'matching' | 'sfm' | 'dense' | 'mesh' | 'tiles' | 'load';
|
|
192
|
+
startedAt: string;
|
|
193
|
+
finishedAt?: string;
|
|
194
|
+
registeredImages?: number;
|
|
195
|
+
totalImages?: number;
|
|
196
|
+
tilesetUrl?: string;
|
|
197
|
+
errors: string[];
|
|
198
|
+
warnings: string[];
|
|
199
|
+
}
|
|
200
|
+
/** Create deterministic task directories without touching the filesystem. */
|
|
201
|
+
export declare function createReconstructionTask(dataRoot: string, captureId: string, options?: {
|
|
202
|
+
coordinateFrame?: ReconstructionTask['coordinateFrame'];
|
|
203
|
+
createdAt?: string;
|
|
204
|
+
}): ReconstructionTask;
|
|
205
|
+
/** Basic consistency checks for a reconstruction report loaded from disk. */
|
|
206
|
+
export declare function validateReconstructionReport(report: unknown): string[];
|
|
207
|
+
//# sourceMappingURL=drone-photogrammetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drone-photogrammetry.d.ts","sourceRoot":"","sources":["../../src/lib/drone-camera/drone-photogrammetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import type { DroneWorld } from './drone-world';
|
|
3
|
+
/**
|
|
4
|
+
* 测距雷达(简化版 DJI 全向视觉避障感知):
|
|
5
|
+
*
|
|
6
|
+
* 真机 Mini 4 Pro 的视觉系统是"机身四角 + 下视 + 上视"的多目布局,这里做两组:
|
|
7
|
+
* - 前视:机头前脸、云台左右两侧的一对镜头(官方精密测距 0.5~18 m,FOV 90°×72°);
|
|
8
|
+
* - 上视:机背顶部、电池前方的一对视觉孔(官方精密测距 0.5~15 m,FOV 左右 90°/前后 72°),
|
|
9
|
+
* 用来判断机体上方有没有障碍物。
|
|
10
|
+
*
|
|
11
|
+
* ⚠️ 关键设计:视觉传感器是"有视场的相机",不是一条无粗细的射线,而且镜头可以转向 ——
|
|
12
|
+
*
|
|
13
|
+
* 1. **可转瞄准(aim)**:默认 `forward` —— 前视镜头转向机体【正前方】、上视镜头转向
|
|
14
|
+
* 【正上方】(带平滑转动过渡,启动时能看到镜头"转过去"的过程);
|
|
15
|
+
* 另有 `sensor` 模式 = 沿玻璃面法线(与画面里的镜头/孔面完全一致)。
|
|
16
|
+
* ⚠️ 玻璃面法线 ≠ 摄像头光轴:机背孔贴在斜坡上,若直接沿法线看,上视会变成
|
|
17
|
+
* "朝后上方仰 35°",正上方反而是盲区 —— 所以默认用 forward。
|
|
18
|
+
*
|
|
19
|
+
* 2. **锥形视场检测(coneCast)**:判定在椭圆锥内做(不是打几条采样射线),
|
|
20
|
+
* 同侧两条镜头的视场在中线上重叠(各外张 20°、半张角 22.5°,合起来正好官方
|
|
21
|
+
* 水平/左右 90°),因此正前方、正上方中线上的细柱不会被"两条射线之间的缝"漏掉。
|
|
22
|
+
*
|
|
23
|
+
* 起点仍逐帧取自模型玻璃网格的几何中心(与画面里的镜头/孔重合)。
|
|
24
|
+
* 可视化:主射线(亮)+ 视场锥边界(淡),命中点标记球;近红 → 中黄 → 远距组色
|
|
25
|
+
* (前视绿 / 上视蓝)。未上电时整组隐藏。
|
|
26
|
+
*
|
|
27
|
+
* 注意:这里只做"传感器测量 + 可视化",刹停保护仍由仿真内核的
|
|
28
|
+
* AABB 避障(drone-sim.applyObstacleBrake)负责,两层互不干扰。
|
|
29
|
+
*/
|
|
30
|
+
export interface RadarHit {
|
|
31
|
+
/** 传感器到命中物的距离(米,沿瞄准轴量到障碍物近端) */
|
|
32
|
+
distance: number;
|
|
33
|
+
/** 命中物标签(建筑 A / 灯杆 / 天桥…) */
|
|
34
|
+
label: string;
|
|
35
|
+
}
|
|
36
|
+
/** 瞄准模式:forward = 镜头转去看正前方/正上方;sensor = 沿玻璃面法线(镜头本体朝向) */
|
|
37
|
+
export type RadarAim = 'forward' | 'sensor';
|
|
38
|
+
export interface RadarSnapshot {
|
|
39
|
+
/** 雷达是否在工作(上电后可用) */
|
|
40
|
+
detecting: boolean;
|
|
41
|
+
/** 前视·左传感器命中,null = 视场内无障碍物 */
|
|
42
|
+
left: RadarHit | null;
|
|
43
|
+
/** 前视·右传感器命中 */
|
|
44
|
+
right: RadarHit | null;
|
|
45
|
+
/** 前视量程(米),按官方 0.5~18 m */
|
|
46
|
+
range: number;
|
|
47
|
+
/** 上视·左传感器命中(机背左孔) */
|
|
48
|
+
upLeft: RadarHit | null;
|
|
49
|
+
/** 上视·右传感器命中(机背右孔) */
|
|
50
|
+
upRight: RadarHit | null;
|
|
51
|
+
/** 上视量程(米),按官方 0.5~15 m */
|
|
52
|
+
upRange: number;
|
|
53
|
+
/** 当前瞄准模式 */
|
|
54
|
+
aim: RadarAim;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 测距雷达(见文件头):四台视觉传感器(前视双摄 + 上视双孔),每帧做锥形视场检测并更新可视化。
|
|
58
|
+
* 只做"传感器测量 + 可视化";刹停保护由 drone-sim 的 AABB 避障负责,两层互不干扰。
|
|
59
|
+
*/
|
|
60
|
+
export declare class DroneRadar {
|
|
61
|
+
private readonly group;
|
|
62
|
+
private readonly disposables;
|
|
63
|
+
/** 每条传感器 5 条线(主射线 + 4 条锥边界),索引 = sensorIndex * 5 + slot */
|
|
64
|
+
private readonly beams;
|
|
65
|
+
private readonly sensors;
|
|
66
|
+
private aim;
|
|
67
|
+
/**
|
|
68
|
+
* 射线可视化的显示开关(页面"雷达射线"勾选框)。
|
|
69
|
+
* 默认 false = 不显示(读数照常工作),用户勾选后才画。
|
|
70
|
+
* ⚠️ 必须存成状态字段:update() 每帧都会刷新 group.visible,
|
|
71
|
+
* 若直接写死 true,会把 setVisible(false) 覆盖掉,开关就"点了没反应"。
|
|
72
|
+
*/
|
|
73
|
+
private beamsVisible;
|
|
74
|
+
private readonly base;
|
|
75
|
+
private readonly origin;
|
|
76
|
+
private readonly targetAxis;
|
|
77
|
+
private readonly axis;
|
|
78
|
+
private readonly u1;
|
|
79
|
+
private readonly u2;
|
|
80
|
+
private readonly refU1World;
|
|
81
|
+
private readonly refU2World;
|
|
82
|
+
private readonly tmp;
|
|
83
|
+
private readonly tmp2;
|
|
84
|
+
private readonly rotation;
|
|
85
|
+
private snapshot;
|
|
86
|
+
/** 绑定雷达扫描可视化(光束挂机体下方,随障碍物真值偏转) */
|
|
87
|
+
constructor(scene: THREE.Scene);
|
|
88
|
+
/** 前视量程(米),按官方 0.5~18 m */
|
|
89
|
+
get range(): number;
|
|
90
|
+
/** 上视量程(米),按官方 0.5~15 m */
|
|
91
|
+
get upRange(): number;
|
|
92
|
+
/** 当前读数(每帧刷新;Vue 100ms 轮询取用) */
|
|
93
|
+
getSnapshot(): RadarSnapshot;
|
|
94
|
+
/**
|
|
95
|
+
* 瞄准模式:forward = 镜头转去看正前方(上视 = 正上方);sensor = 沿玻璃面法线。
|
|
96
|
+
* 切换后镜头会平滑转过去(不是瞬移)。
|
|
97
|
+
*/
|
|
98
|
+
setAim(aim: RadarAim): void;
|
|
99
|
+
/** 当前瞄准模式(forward / sensor) */
|
|
100
|
+
getAim(): RadarAim;
|
|
101
|
+
/**
|
|
102
|
+
* 从模型里读出两组视觉玻璃网格(前视双摄 + 机背上视双孔),
|
|
103
|
+
* 记录其几何中心与镜面法线。开机时调用一次即可。
|
|
104
|
+
*/
|
|
105
|
+
bindSensors(model: THREE.Object3D): void;
|
|
106
|
+
/** 是否两组都成功绑定到模型(探针用) */
|
|
107
|
+
isBoundToSensors(): boolean;
|
|
108
|
+
/** 每个传感器的绑定情况(探针用) */
|
|
109
|
+
debugInfo(): Array<{
|
|
110
|
+
group: string;
|
|
111
|
+
position: string;
|
|
112
|
+
nodeName: string;
|
|
113
|
+
bound: boolean;
|
|
114
|
+
aimDeg: number[];
|
|
115
|
+
}>;
|
|
116
|
+
/**
|
|
117
|
+
* 每帧更新:先让镜头朝目标方向平滑转动,再做锥形视场检测。
|
|
118
|
+
* 起点逐帧取自视觉玻璃网格的世界矩阵(与画面里的镜头/孔完全重合)。
|
|
119
|
+
*/
|
|
120
|
+
update(model: THREE.Object3D, world: DroneWorld, delta: number, detecting: boolean): void;
|
|
121
|
+
/** 更新一条传感器的可视化:主射线 + 4 条视场锥边界 + 命中标记 */
|
|
122
|
+
private updateSensorVisual;
|
|
123
|
+
private writeBeam;
|
|
124
|
+
/** 距离分档配色:近红 / 中黄 / 远距用组色(未命中按远距) */
|
|
125
|
+
private levelColor;
|
|
126
|
+
/**
|
|
127
|
+
* 页面调试开关:隐藏/显示射线可视化(读数照常)。
|
|
128
|
+
* 只记录状态并立即生效;随后每帧的 update() 会沿用这个状态,不会被覆盖。
|
|
129
|
+
*/
|
|
130
|
+
setVisible(visible: boolean): void;
|
|
131
|
+
/** 当前射线可视化是否显示(探针用) */
|
|
132
|
+
isBeamsVisible(): boolean;
|
|
133
|
+
/** 释放几何/材质并复位读数 */
|
|
134
|
+
destroy(): void;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=drone-radar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drone-radar.d.ts","sourceRoot":"","sources":["../../src/lib/drone-camera/drone-radar.ts"],"names":[],"mappings":"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"}
|