@lumikmz/kmz 0.6.2 → 0.6.3
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/dist/index.d.mts +13 -1
- package/dist/index.mjs +35 -3
- package/package.json +1 -1
- package/src/plan/plan-mapping2d.ts +38 -3
- package/src/plan/plan.test.ts +18 -0
- package/src/types/action.ts +13 -0
package/dist/index.d.mts
CHANGED
|
@@ -575,8 +575,20 @@ interface MegaphoneParam {
|
|
|
575
575
|
}
|
|
576
576
|
type MegaphoneAction = ActionBase<"megaphone", MegaphoneParam>;
|
|
577
577
|
/** M4D/M4TD only — starts gimbal swing in smart-oblique mode. */
|
|
578
|
+
interface SmartObliquePoint {
|
|
579
|
+
/** seconds before this pose starts; DJI exports currently use 0. */
|
|
580
|
+
smartObliqueRunningTime: number;
|
|
581
|
+
/** seconds to hold this pose for smart-oblique shooting. */
|
|
582
|
+
smartObliqueStayTime: number;
|
|
583
|
+
smartObliqueEulerPitch: Degrees;
|
|
584
|
+
smartObliqueEulerRoll: Degrees;
|
|
585
|
+
smartObliqueEulerYaw: Degrees;
|
|
586
|
+
}
|
|
578
587
|
interface StartSmartObliqueParam {
|
|
588
|
+
/** Observed in DJI exports; older generated files may omit it. */
|
|
589
|
+
smartObliqueCycleMode?: "unlimited";
|
|
579
590
|
payloadPositionIndex: number;
|
|
591
|
+
smartObliquePoint?: SmartObliquePoint[];
|
|
580
592
|
}
|
|
581
593
|
type StartSmartObliqueAction = ActionBase<"startSmartOblique", StartSmartObliqueParam>;
|
|
582
594
|
/** M4D/M4TD only — stops gimbal swing in smart-oblique mode. */
|
|
@@ -931,4 +943,4 @@ declare function validate(doc: Template | Waylines): Issue[];
|
|
|
931
943
|
/** Great-circle distance between two WGS-84 coordinates, in meters. */
|
|
932
944
|
declare function haversineMeters(a: LngLat, b: LngLat): number;
|
|
933
945
|
//#endregion
|
|
934
|
-
export { AccurateShootAction, AccurateShootParam, Action, ActionActuatorFunc, ActionGroup, ActionGroupMode, ActionTrigger, ActionTriggerType, AircraftPathMode, AutoRerouteInfo, CoordinateMode, CustomDirNameAction, CustomDirNameParam, Degrees, DroneEnum, DroneInfo, ExecuteHeightMode, ExecuteRCLostAction, ExitOnRCLost, FinishAction, FlyToWaylineMode, FocusAction, FocusMode, FocusParam, GimbalAngleLockAction, GimbalAngleLockParam, GimbalAngleUnlockAction, GimbalEvenlyRotateAction, GimbalEvenlyRotateParam, GimbalHeadingYawBase, GimbalPitchMode, GimbalRotateAction, GimbalRotateMode, GimbalRotateParam, HoverAction, HoverParam, Issue, KmzError, LensType, LidarReturnMode, LidarScanningMode, LngLat, LngLatHeight, Mapping2dFolder, Mapping2dPlacemark, Mapping2dTemplate, Mapping3dFolder, Mapping3dPlacemark, Mapping3dTemplate, MappingHeadingMode, MappingHeadingParam, MappingStripFolder, MappingStripPlacemark, MappingStripTemplate, MegaphoneAction, MegaphoneParam, MeteringMode, Meters, MetersPerSecond, MissionConfig, OrientedPhotoMode, OrientedShootAction, OrientedShootParam, Overlap, PanoShotAction, PanoShotParam, PanoShotSubMode, PayloadEnum, PayloadInfo, PayloadParam, type PlanOptions, PlannerError, PositioningType, RecordPointCloudAction, RecordPointCloudOperate, RecordPointCloudParam, RotateYawAction, RotateYawParam, SearchlightAction, SearchlightParam, SetFocusTypeAction, SetFocusTypeParam, ShootType, StartActionGroup, StartRecordAction, StartRecordParam, StartSmartObliqueAction, StartSmartObliqueParam, StartTimeLapseAction, StartTimeLapseParam, StopRecordAction, StopRecordParam, StopSmartObliqueAction, StopSmartObliqueParam, StopTimeLapseAction, StopTimeLapseParam, TakePhotoAction, TakePhotoParam, Template, TemplateHeightMode, TemplatePolygon, TemplateType, TemplateWaypointPlacemark, WaylineCoordinateSysParam, Waylines, WaylinesFolder, WaylinesPlacemark, WaypointFolder, WaypointHeadingMode, WaypointHeadingParam, WaypointHeadingPathMode, WaypointTemplate, WaypointTurnMode, WaypointTurnParam, ZoomAction, ZoomParam, degrees, haversineMeters, meters, metersPerSecond, plan, validate };
|
|
946
|
+
export { AccurateShootAction, AccurateShootParam, Action, ActionActuatorFunc, ActionGroup, ActionGroupMode, ActionTrigger, ActionTriggerType, AircraftPathMode, AutoRerouteInfo, CoordinateMode, CustomDirNameAction, CustomDirNameParam, Degrees, DroneEnum, DroneInfo, ExecuteHeightMode, ExecuteRCLostAction, ExitOnRCLost, FinishAction, FlyToWaylineMode, FocusAction, FocusMode, FocusParam, GimbalAngleLockAction, GimbalAngleLockParam, GimbalAngleUnlockAction, GimbalEvenlyRotateAction, GimbalEvenlyRotateParam, GimbalHeadingYawBase, GimbalPitchMode, GimbalRotateAction, GimbalRotateMode, GimbalRotateParam, HoverAction, HoverParam, Issue, KmzError, LensType, LidarReturnMode, LidarScanningMode, LngLat, LngLatHeight, Mapping2dFolder, Mapping2dPlacemark, Mapping2dTemplate, Mapping3dFolder, Mapping3dPlacemark, Mapping3dTemplate, MappingHeadingMode, MappingHeadingParam, MappingStripFolder, MappingStripPlacemark, MappingStripTemplate, MegaphoneAction, MegaphoneParam, MeteringMode, Meters, MetersPerSecond, MissionConfig, OrientedPhotoMode, OrientedShootAction, OrientedShootParam, Overlap, PanoShotAction, PanoShotParam, PanoShotSubMode, PayloadEnum, PayloadInfo, PayloadParam, type PlanOptions, PlannerError, PositioningType, RecordPointCloudAction, RecordPointCloudOperate, RecordPointCloudParam, RotateYawAction, RotateYawParam, SearchlightAction, SearchlightParam, SetFocusTypeAction, SetFocusTypeParam, ShootType, SmartObliquePoint, StartActionGroup, StartRecordAction, StartRecordParam, StartSmartObliqueAction, StartSmartObliqueParam, StartTimeLapseAction, StartTimeLapseParam, StopRecordAction, StopRecordParam, StopSmartObliqueAction, StopSmartObliqueParam, StopTimeLapseAction, StopTimeLapseParam, TakePhotoAction, TakePhotoParam, Template, TemplateHeightMode, TemplatePolygon, TemplateType, TemplateWaypointPlacemark, WaylineCoordinateSysParam, Waylines, WaylinesFolder, WaylinesPlacemark, WaypointFolder, WaypointHeadingMode, WaypointHeadingParam, WaypointHeadingPathMode, WaypointTemplate, WaypointTurnMode, WaypointTurnParam, ZoomAction, ZoomParam, degrees, haversineMeters, meters, metersPerSecond, plan, validate };
|
package/dist/index.mjs
CHANGED
|
@@ -734,9 +734,10 @@ function emitOrtho(folder, origin, enuWps, shootInterval, options) {
|
|
|
734
734
|
* Single-pass smart-oblique / quick-ortho (smartObliqueEnable=true):
|
|
735
735
|
* The aircraft flies one grid while the gimbal swings (startSmartOblique/stopSmartOblique).
|
|
736
736
|
*/
|
|
737
|
-
function emitSmartOblique(folder, origin, enuWps, options) {
|
|
737
|
+
function emitSmartOblique(folder, origin, enuWps, shootInterval, options) {
|
|
738
738
|
const lastIndex = enuWps.length - 1;
|
|
739
739
|
const pitch = folder.Placemark.smartObliqueGimbalPitch ?? degrees(-45);
|
|
740
|
+
const smartObliquePoints = buildSmartObliquePoints(Number(pitch), shootInterval);
|
|
740
741
|
const placemarks = enuWps.map((enu, index) => {
|
|
741
742
|
const coord = enuToLngLat(enu, origin);
|
|
742
743
|
const isLast = index === lastIndex;
|
|
@@ -761,8 +762,16 @@ function emitSmartOblique(folder, origin, enuWps, options) {
|
|
|
761
762
|
actionTrigger: { actionTriggerType: "reachPoint" },
|
|
762
763
|
action: [{
|
|
763
764
|
actionId: 0,
|
|
764
|
-
actionActuatorFunc: "
|
|
765
|
+
actionActuatorFunc: "gimbalAngleLock",
|
|
765
766
|
actionActuatorFuncParam: { payloadPositionIndex: 0 }
|
|
767
|
+
}, {
|
|
768
|
+
actionId: 1,
|
|
769
|
+
actionActuatorFunc: "startSmartOblique",
|
|
770
|
+
actionActuatorFuncParam: {
|
|
771
|
+
smartObliqueCycleMode: "unlimited",
|
|
772
|
+
payloadPositionIndex: 0,
|
|
773
|
+
smartObliquePoint: smartObliquePoints
|
|
774
|
+
}
|
|
766
775
|
}]
|
|
767
776
|
}];
|
|
768
777
|
else if (isLast) placemark.actionGroup = [{
|
|
@@ -775,6 +784,9 @@ function emitSmartOblique(folder, origin, enuWps, options) {
|
|
|
775
784
|
actionId: 0,
|
|
776
785
|
actionActuatorFunc: "stopSmartOblique",
|
|
777
786
|
actionActuatorFuncParam: { payloadPositionIndex: 0 }
|
|
787
|
+
}, {
|
|
788
|
+
actionId: 1,
|
|
789
|
+
actionActuatorFunc: "gimbalAngleUnlock"
|
|
778
790
|
}]
|
|
779
791
|
}];
|
|
780
792
|
return placemark;
|
|
@@ -788,6 +800,26 @@ function emitSmartOblique(folder, origin, enuWps, options) {
|
|
|
788
800
|
Placemark: placemarks
|
|
789
801
|
};
|
|
790
802
|
}
|
|
803
|
+
function buildSmartObliquePoints(pitchDeg, shootInterval) {
|
|
804
|
+
const stayTime = Math.max(.1, shootInterval);
|
|
805
|
+
const obliquePitch = -Math.abs(pitchDeg || 45);
|
|
806
|
+
return [
|
|
807
|
+
smartObliquePoint(-90, 0, 0),
|
|
808
|
+
smartObliquePoint(obliquePitch, 45, stayTime),
|
|
809
|
+
smartObliquePoint(obliquePitch, -45, stayTime),
|
|
810
|
+
smartObliquePoint(-120, 50, stayTime),
|
|
811
|
+
smartObliquePoint(-120, -50, stayTime)
|
|
812
|
+
];
|
|
813
|
+
}
|
|
814
|
+
function smartObliquePoint(pitchDeg, yawDeg, stayTime) {
|
|
815
|
+
return {
|
|
816
|
+
smartObliqueRunningTime: 0,
|
|
817
|
+
smartObliqueStayTime: stayTime,
|
|
818
|
+
smartObliqueEulerPitch: degrees(pitchDeg),
|
|
819
|
+
smartObliqueEulerRoll: degrees(0),
|
|
820
|
+
smartObliqueEulerYaw: degrees(yawDeg)
|
|
821
|
+
};
|
|
822
|
+
}
|
|
791
823
|
function planMapping2d(template, options) {
|
|
792
824
|
if (options?.lineSpacing == null) throw new PlannerError("mapping2d requires options.lineSpacing — calculate 2·h·tan(HFOV/2)·(1−sideOverlap) in the demo and pass it in.");
|
|
793
825
|
const standoff = template.Folder.Placemark.smartObliqueEnable === true ? smartObliqueStandoff(template.Folder) : 0;
|
|
@@ -795,7 +827,7 @@ function planMapping2d(template, options) {
|
|
|
795
827
|
const shootInterval = options.shootInterval ?? 2;
|
|
796
828
|
if (folder.Placemark.smartObliqueEnable === true) return {
|
|
797
829
|
missionConfig: template.missionConfig,
|
|
798
|
-
Folder: [emitSmartOblique(folder, origin, enuWps, options)]
|
|
830
|
+
Folder: [emitSmartOblique(folder, origin, enuWps, shootInterval, options)]
|
|
799
831
|
};
|
|
800
832
|
return {
|
|
801
833
|
missionConfig: template.missionConfig,
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { degrees, meters, type Meters } from "../types/branded.js";
|
|
2
|
-
import type { Action } from "../types/action.js";
|
|
2
|
+
import type { Action, SmartObliquePoint } from "../types/action.js";
|
|
3
3
|
import type { ExecuteHeightMode } from "../types/enums.js";
|
|
4
4
|
import type { Mapping2dFolder, Mapping2dTemplate } from "../types/template.js";
|
|
5
5
|
import type { StartActionGroup } from "../types/waylines.js";
|
|
@@ -466,10 +466,12 @@ function emitSmartOblique(
|
|
|
466
466
|
folder: Mapping2dFolder,
|
|
467
467
|
origin: { lng: number; lat: number },
|
|
468
468
|
enuWps: readonly EnuPoint[],
|
|
469
|
+
shootInterval: number,
|
|
469
470
|
options?: PlanOptions,
|
|
470
471
|
): WaylinesFolder {
|
|
471
472
|
const lastIndex = enuWps.length - 1;
|
|
472
473
|
const pitch = folder.Placemark.smartObliqueGimbalPitch ?? degrees(-45);
|
|
474
|
+
const smartObliquePoints = buildSmartObliquePoints(Number(pitch), shootInterval);
|
|
473
475
|
|
|
474
476
|
const placemarks: WaylinesPlacemark[] = enuWps.map((enu, index) => {
|
|
475
477
|
const coord = enuToLngLat(enu, origin);
|
|
@@ -501,9 +503,18 @@ function emitSmartOblique(
|
|
|
501
503
|
action: [
|
|
502
504
|
{
|
|
503
505
|
actionId: 0,
|
|
504
|
-
actionActuatorFunc: "
|
|
506
|
+
actionActuatorFunc: "gimbalAngleLock",
|
|
505
507
|
actionActuatorFuncParam: { payloadPositionIndex: 0 },
|
|
506
508
|
},
|
|
509
|
+
{
|
|
510
|
+
actionId: 1,
|
|
511
|
+
actionActuatorFunc: "startSmartOblique",
|
|
512
|
+
actionActuatorFuncParam: {
|
|
513
|
+
smartObliqueCycleMode: "unlimited",
|
|
514
|
+
payloadPositionIndex: 0,
|
|
515
|
+
smartObliquePoint: smartObliquePoints,
|
|
516
|
+
},
|
|
517
|
+
},
|
|
507
518
|
],
|
|
508
519
|
},
|
|
509
520
|
];
|
|
@@ -521,6 +532,7 @@ function emitSmartOblique(
|
|
|
521
532
|
actionActuatorFunc: "stopSmartOblique",
|
|
522
533
|
actionActuatorFuncParam: { payloadPositionIndex: 0 },
|
|
523
534
|
},
|
|
535
|
+
{ actionId: 1, actionActuatorFunc: "gimbalAngleUnlock" },
|
|
524
536
|
],
|
|
525
537
|
},
|
|
526
538
|
];
|
|
@@ -538,6 +550,29 @@ function emitSmartOblique(
|
|
|
538
550
|
};
|
|
539
551
|
}
|
|
540
552
|
|
|
553
|
+
function buildSmartObliquePoints(pitchDeg: number, shootInterval: number): SmartObliquePoint[] {
|
|
554
|
+
const stayTime = Math.max(0.1, shootInterval);
|
|
555
|
+
const obliquePitch = -Math.abs(pitchDeg || 45);
|
|
556
|
+
|
|
557
|
+
return [
|
|
558
|
+
smartObliquePoint(-90, 0, 0),
|
|
559
|
+
smartObliquePoint(obliquePitch, 45, stayTime),
|
|
560
|
+
smartObliquePoint(obliquePitch, -45, stayTime),
|
|
561
|
+
smartObliquePoint(-120, 50, stayTime),
|
|
562
|
+
smartObliquePoint(-120, -50, stayTime),
|
|
563
|
+
];
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function smartObliquePoint(pitchDeg: number, yawDeg: number, stayTime: number): SmartObliquePoint {
|
|
567
|
+
return {
|
|
568
|
+
smartObliqueRunningTime: 0,
|
|
569
|
+
smartObliqueStayTime: stayTime,
|
|
570
|
+
smartObliqueEulerPitch: degrees(pitchDeg),
|
|
571
|
+
smartObliqueEulerRoll: degrees(0),
|
|
572
|
+
smartObliqueEulerYaw: degrees(yawDeg),
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
541
576
|
export function planMapping2d(template: Mapping2dTemplate, options?: PlanOptions): Waylines {
|
|
542
577
|
if (options?.lineSpacing == null) {
|
|
543
578
|
throw new PlannerError(
|
|
@@ -556,7 +591,7 @@ export function planMapping2d(template: Mapping2dTemplate, options?: PlanOptions
|
|
|
556
591
|
if (folder.Placemark.smartObliqueEnable === true) {
|
|
557
592
|
return {
|
|
558
593
|
missionConfig: template.missionConfig,
|
|
559
|
-
Folder: [emitSmartOblique(folder, origin, enuWps, options)],
|
|
594
|
+
Folder: [emitSmartOblique(folder, origin, enuWps, shootInterval, options)],
|
|
560
595
|
};
|
|
561
596
|
}
|
|
562
597
|
// 正射 and 正射+智能摆拍 share the nadir grid; the centroid detour is driven by
|
package/src/plan/plan.test.ts
CHANGED
|
@@ -370,8 +370,26 @@ describe("plan", () => {
|
|
|
370
370
|
const funcs = wl.Folder[0]!.Placemark.flatMap((p) =>
|
|
371
371
|
(p.actionGroup ?? []).flatMap((g) => g.action.map((a) => a.actionActuatorFunc)),
|
|
372
372
|
);
|
|
373
|
+
expect(funcs.filter((fn) => fn === "startSmartOblique")).toHaveLength(1);
|
|
374
|
+
expect(funcs.filter((fn) => fn === "stopSmartOblique")).toHaveLength(1);
|
|
375
|
+
expect(funcs).toContain("gimbalAngleLock");
|
|
373
376
|
expect(funcs).toContain("startSmartOblique");
|
|
374
377
|
expect(funcs).toContain("stopSmartOblique");
|
|
378
|
+
expect(funcs).toContain("gimbalAngleUnlock");
|
|
379
|
+
|
|
380
|
+
const start = wl.Folder[0]!.Placemark.flatMap((p) => p.actionGroup ?? [])
|
|
381
|
+
.flatMap((g) => g.action)
|
|
382
|
+
.find((a) => a.actionActuatorFunc === "startSmartOblique");
|
|
383
|
+
expect(start?.actionActuatorFunc).toBe("startSmartOblique");
|
|
384
|
+
if (start?.actionActuatorFunc === "startSmartOblique") {
|
|
385
|
+
expect(start.actionActuatorFuncParam.smartObliqueCycleMode).toBe("unlimited");
|
|
386
|
+
expect(start.actionActuatorFuncParam.smartObliquePoint).toHaveLength(5);
|
|
387
|
+
expect(
|
|
388
|
+
start.actionActuatorFuncParam.smartObliquePoint?.map((p) =>
|
|
389
|
+
Number(p.smartObliqueEulerPitch),
|
|
390
|
+
),
|
|
391
|
+
).toEqual([-90, -45, -45, -120, -120]);
|
|
392
|
+
}
|
|
375
393
|
|
|
376
394
|
// The camera swings omnidirectionally, so the polygon is dilated by the
|
|
377
395
|
// stand-off and the grid overflies the boundary on EVERY side. Polygon spans
|
package/src/types/action.ts
CHANGED
|
@@ -253,8 +253,21 @@ export interface MegaphoneParam {
|
|
|
253
253
|
export type MegaphoneAction = ActionBase<"megaphone", MegaphoneParam>;
|
|
254
254
|
|
|
255
255
|
/** M4D/M4TD only — starts gimbal swing in smart-oblique mode. */
|
|
256
|
+
export interface SmartObliquePoint {
|
|
257
|
+
/** seconds before this pose starts; DJI exports currently use 0. */
|
|
258
|
+
smartObliqueRunningTime: number;
|
|
259
|
+
/** seconds to hold this pose for smart-oblique shooting. */
|
|
260
|
+
smartObliqueStayTime: number;
|
|
261
|
+
smartObliqueEulerPitch: Degrees;
|
|
262
|
+
smartObliqueEulerRoll: Degrees;
|
|
263
|
+
smartObliqueEulerYaw: Degrees;
|
|
264
|
+
}
|
|
265
|
+
|
|
256
266
|
export interface StartSmartObliqueParam {
|
|
267
|
+
/** Observed in DJI exports; older generated files may omit it. */
|
|
268
|
+
smartObliqueCycleMode?: "unlimited";
|
|
257
269
|
payloadPositionIndex: number;
|
|
270
|
+
smartObliquePoint?: SmartObliquePoint[];
|
|
258
271
|
}
|
|
259
272
|
export type StartSmartObliqueAction = ActionBase<"startSmartOblique", StartSmartObliqueParam>;
|
|
260
273
|
|