@lumikmz/kmz 0.6.3 → 0.7.0
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 +12 -1
- package/dist/index.mjs +42 -35
- package/package.json +1 -1
- package/src/plan/plan-mapping2d.ts +54 -42
- package/src/plan/plan.test.ts +19 -5
- package/src/types/action.ts +12 -0
package/dist/index.d.mts
CHANGED
|
@@ -572,8 +572,19 @@ interface MegaphoneParam {
|
|
|
572
572
|
megaphoneFileMd5: string;
|
|
573
573
|
/** 1=8000, 2=16000, 3=24000, 4=32000, 5=48000, 6=64000 (only 4 supported today). */
|
|
574
574
|
megaphoneFileBitrate: 1 | 2 | 3 | 4 | 5 | 6;
|
|
575
|
+
/** Non-spec DJI Pilot TTS params observed in M4D/M4TD megaphone actions. */
|
|
576
|
+
ttsparam?: MegaphoneTtsParam;
|
|
575
577
|
}
|
|
576
578
|
type MegaphoneAction = ActionBase<"megaphone", MegaphoneParam>;
|
|
579
|
+
interface MegaphoneTtsParam {
|
|
580
|
+
text: string;
|
|
581
|
+
role: "male" | "female";
|
|
582
|
+
language: "CN";
|
|
583
|
+
/** 0-100. */
|
|
584
|
+
volume: number;
|
|
585
|
+
/** 0-100. DJI Pilot exports commonly use 50. */
|
|
586
|
+
speed: number;
|
|
587
|
+
}
|
|
577
588
|
/** M4D/M4TD only — starts gimbal swing in smart-oblique mode. */
|
|
578
589
|
interface SmartObliquePoint {
|
|
579
590
|
/** seconds before this pose starts; DJI exports currently use 0. */
|
|
@@ -943,4 +954,4 @@ declare function validate(doc: Template | Waylines): Issue[];
|
|
|
943
954
|
/** Great-circle distance between two WGS-84 coordinates, in meters. */
|
|
944
955
|
declare function haversineMeters(a: LngLat, b: LngLat): number;
|
|
945
956
|
//#endregion
|
|
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 };
|
|
957
|
+
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, MegaphoneTtsParam, 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
|
@@ -738,6 +738,7 @@ function emitSmartOblique(folder, origin, enuWps, shootInterval, options) {
|
|
|
738
738
|
const lastIndex = enuWps.length - 1;
|
|
739
739
|
const pitch = folder.Placemark.smartObliqueGimbalPitch ?? degrees(-45);
|
|
740
740
|
const smartObliquePoints = buildSmartObliquePoints(Number(pitch), shootInterval);
|
|
741
|
+
let nextGroupId = 0;
|
|
741
742
|
const placemarks = enuWps.map((enu, index) => {
|
|
742
743
|
const coord = enuToLngLat(enu, origin);
|
|
743
744
|
const isLast = index === lastIndex;
|
|
@@ -754,41 +755,8 @@ function emitSmartOblique(folder, origin, enuWps, shootInterval, options) {
|
|
|
754
755
|
},
|
|
755
756
|
...COMMON_WP_EXTRAS
|
|
756
757
|
};
|
|
757
|
-
if (index === 0) placemark.actionGroup = [
|
|
758
|
-
|
|
759
|
-
actionGroupStartIndex: 0,
|
|
760
|
-
actionGroupEndIndex: lastIndex,
|
|
761
|
-
actionGroupMode: "sequence",
|
|
762
|
-
actionTrigger: { actionTriggerType: "reachPoint" },
|
|
763
|
-
action: [{
|
|
764
|
-
actionId: 0,
|
|
765
|
-
actionActuatorFunc: "gimbalAngleLock",
|
|
766
|
-
actionActuatorFuncParam: { payloadPositionIndex: 0 }
|
|
767
|
-
}, {
|
|
768
|
-
actionId: 1,
|
|
769
|
-
actionActuatorFunc: "startSmartOblique",
|
|
770
|
-
actionActuatorFuncParam: {
|
|
771
|
-
smartObliqueCycleMode: "unlimited",
|
|
772
|
-
payloadPositionIndex: 0,
|
|
773
|
-
smartObliquePoint: smartObliquePoints
|
|
774
|
-
}
|
|
775
|
-
}]
|
|
776
|
-
}];
|
|
777
|
-
else if (isLast) placemark.actionGroup = [{
|
|
778
|
-
actionGroupId: 1,
|
|
779
|
-
actionGroupStartIndex: lastIndex,
|
|
780
|
-
actionGroupEndIndex: lastIndex,
|
|
781
|
-
actionGroupMode: "sequence",
|
|
782
|
-
actionTrigger: { actionTriggerType: "reachPoint" },
|
|
783
|
-
action: [{
|
|
784
|
-
actionId: 0,
|
|
785
|
-
actionActuatorFunc: "stopSmartOblique",
|
|
786
|
-
actionActuatorFuncParam: { payloadPositionIndex: 0 }
|
|
787
|
-
}, {
|
|
788
|
-
actionId: 1,
|
|
789
|
-
actionActuatorFunc: "gimbalAngleUnlock"
|
|
790
|
-
}]
|
|
791
|
-
}];
|
|
758
|
+
if (index % 2 === 0 && index + 1 <= lastIndex) placemark.actionGroup = [smartObliqueStartGroup(index, index + 1, nextGroupId++, smartObliquePoints)];
|
|
759
|
+
else if (index % 2 === 1) placemark.actionGroup = [smartObliqueStopGroup(index, nextGroupId++)];
|
|
792
760
|
return placemark;
|
|
793
761
|
});
|
|
794
762
|
return {
|
|
@@ -800,6 +768,45 @@ function emitSmartOblique(folder, origin, enuWps, shootInterval, options) {
|
|
|
800
768
|
Placemark: placemarks
|
|
801
769
|
};
|
|
802
770
|
}
|
|
771
|
+
function smartObliqueStartGroup(startIndex, endIndex, groupId, smartObliquePoints) {
|
|
772
|
+
return {
|
|
773
|
+
actionGroupId: groupId,
|
|
774
|
+
actionGroupStartIndex: startIndex,
|
|
775
|
+
actionGroupEndIndex: endIndex,
|
|
776
|
+
actionGroupMode: "sequence",
|
|
777
|
+
actionTrigger: { actionTriggerType: "betweenAdjacentPoints" },
|
|
778
|
+
action: [{
|
|
779
|
+
actionId: 0,
|
|
780
|
+
actionActuatorFunc: "gimbalAngleLock",
|
|
781
|
+
actionActuatorFuncParam: { payloadPositionIndex: 0 }
|
|
782
|
+
}, {
|
|
783
|
+
actionId: 1,
|
|
784
|
+
actionActuatorFunc: "startSmartOblique",
|
|
785
|
+
actionActuatorFuncParam: {
|
|
786
|
+
smartObliqueCycleMode: "unlimited",
|
|
787
|
+
payloadPositionIndex: 0,
|
|
788
|
+
smartObliquePoint: smartObliquePoints
|
|
789
|
+
}
|
|
790
|
+
}]
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
function smartObliqueStopGroup(index, groupId) {
|
|
794
|
+
return {
|
|
795
|
+
actionGroupId: groupId,
|
|
796
|
+
actionGroupStartIndex: index,
|
|
797
|
+
actionGroupEndIndex: index,
|
|
798
|
+
actionGroupMode: "sequence",
|
|
799
|
+
actionTrigger: { actionTriggerType: "reachPoint" },
|
|
800
|
+
action: [{
|
|
801
|
+
actionId: 0,
|
|
802
|
+
actionActuatorFunc: "stopSmartOblique",
|
|
803
|
+
actionActuatorFuncParam: { payloadPositionIndex: 0 }
|
|
804
|
+
}, {
|
|
805
|
+
actionId: 1,
|
|
806
|
+
actionActuatorFunc: "gimbalAngleUnlock"
|
|
807
|
+
}]
|
|
808
|
+
};
|
|
809
|
+
}
|
|
803
810
|
function buildSmartObliquePoints(pitchDeg, shootInterval) {
|
|
804
811
|
const stayTime = Math.max(.1, shootInterval);
|
|
805
812
|
const obliquePitch = -Math.abs(pitchDeg || 45);
|
package/package.json
CHANGED
|
@@ -472,6 +472,7 @@ function emitSmartOblique(
|
|
|
472
472
|
const lastIndex = enuWps.length - 1;
|
|
473
473
|
const pitch = folder.Placemark.smartObliqueGimbalPitch ?? degrees(-45);
|
|
474
474
|
const smartObliquePoints = buildSmartObliquePoints(Number(pitch), shootInterval);
|
|
475
|
+
let nextGroupId = 0;
|
|
475
476
|
|
|
476
477
|
const placemarks: WaylinesPlacemark[] = enuWps.map((enu, index) => {
|
|
477
478
|
const coord = enuToLngLat(enu, origin);
|
|
@@ -492,50 +493,12 @@ function emitSmartOblique(
|
|
|
492
493
|
},
|
|
493
494
|
...COMMON_WP_EXTRAS,
|
|
494
495
|
};
|
|
495
|
-
if (index === 0) {
|
|
496
|
-
placemark.actionGroup = [
|
|
497
|
-
{
|
|
498
|
-
actionGroupId: 0,
|
|
499
|
-
actionGroupStartIndex: 0,
|
|
500
|
-
actionGroupEndIndex: lastIndex,
|
|
501
|
-
actionGroupMode: "sequence",
|
|
502
|
-
actionTrigger: { actionTriggerType: "reachPoint" },
|
|
503
|
-
action: [
|
|
504
|
-
{
|
|
505
|
-
actionId: 0,
|
|
506
|
-
actionActuatorFunc: "gimbalAngleLock",
|
|
507
|
-
actionActuatorFuncParam: { payloadPositionIndex: 0 },
|
|
508
|
-
},
|
|
509
|
-
{
|
|
510
|
-
actionId: 1,
|
|
511
|
-
actionActuatorFunc: "startSmartOblique",
|
|
512
|
-
actionActuatorFuncParam: {
|
|
513
|
-
smartObliqueCycleMode: "unlimited",
|
|
514
|
-
payloadPositionIndex: 0,
|
|
515
|
-
smartObliquePoint: smartObliquePoints,
|
|
516
|
-
},
|
|
517
|
-
},
|
|
518
|
-
],
|
|
519
|
-
},
|
|
520
|
-
];
|
|
521
|
-
} else if (isLast) {
|
|
496
|
+
if (index % 2 === 0 && index + 1 <= lastIndex) {
|
|
522
497
|
placemark.actionGroup = [
|
|
523
|
-
|
|
524
|
-
actionGroupId: 1,
|
|
525
|
-
actionGroupStartIndex: lastIndex,
|
|
526
|
-
actionGroupEndIndex: lastIndex,
|
|
527
|
-
actionGroupMode: "sequence",
|
|
528
|
-
actionTrigger: { actionTriggerType: "reachPoint" },
|
|
529
|
-
action: [
|
|
530
|
-
{
|
|
531
|
-
actionId: 0,
|
|
532
|
-
actionActuatorFunc: "stopSmartOblique",
|
|
533
|
-
actionActuatorFuncParam: { payloadPositionIndex: 0 },
|
|
534
|
-
},
|
|
535
|
-
{ actionId: 1, actionActuatorFunc: "gimbalAngleUnlock" },
|
|
536
|
-
],
|
|
537
|
-
},
|
|
498
|
+
smartObliqueStartGroup(index, index + 1, nextGroupId++, smartObliquePoints),
|
|
538
499
|
];
|
|
500
|
+
} else if (index % 2 === 1) {
|
|
501
|
+
placemark.actionGroup = [smartObliqueStopGroup(index, nextGroupId++)];
|
|
539
502
|
}
|
|
540
503
|
return placemark;
|
|
541
504
|
});
|
|
@@ -550,6 +513,55 @@ function emitSmartOblique(
|
|
|
550
513
|
};
|
|
551
514
|
}
|
|
552
515
|
|
|
516
|
+
function smartObliqueStartGroup(
|
|
517
|
+
startIndex: number,
|
|
518
|
+
endIndex: number,
|
|
519
|
+
groupId: number,
|
|
520
|
+
smartObliquePoints: SmartObliquePoint[],
|
|
521
|
+
) {
|
|
522
|
+
return {
|
|
523
|
+
actionGroupId: groupId,
|
|
524
|
+
actionGroupStartIndex: startIndex,
|
|
525
|
+
actionGroupEndIndex: endIndex,
|
|
526
|
+
actionGroupMode: "sequence" as const,
|
|
527
|
+
actionTrigger: { actionTriggerType: "betweenAdjacentPoints" as const },
|
|
528
|
+
action: [
|
|
529
|
+
{
|
|
530
|
+
actionId: 0,
|
|
531
|
+
actionActuatorFunc: "gimbalAngleLock" as const,
|
|
532
|
+
actionActuatorFuncParam: { payloadPositionIndex: 0 },
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
actionId: 1,
|
|
536
|
+
actionActuatorFunc: "startSmartOblique" as const,
|
|
537
|
+
actionActuatorFuncParam: {
|
|
538
|
+
smartObliqueCycleMode: "unlimited" as const,
|
|
539
|
+
payloadPositionIndex: 0,
|
|
540
|
+
smartObliquePoint: smartObliquePoints,
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
],
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
function smartObliqueStopGroup(index: number, groupId: number) {
|
|
548
|
+
return {
|
|
549
|
+
actionGroupId: groupId,
|
|
550
|
+
actionGroupStartIndex: index,
|
|
551
|
+
actionGroupEndIndex: index,
|
|
552
|
+
actionGroupMode: "sequence" as const,
|
|
553
|
+
actionTrigger: { actionTriggerType: "reachPoint" as const },
|
|
554
|
+
action: [
|
|
555
|
+
{
|
|
556
|
+
actionId: 0,
|
|
557
|
+
actionActuatorFunc: "stopSmartOblique" as const,
|
|
558
|
+
actionActuatorFuncParam: { payloadPositionIndex: 0 },
|
|
559
|
+
},
|
|
560
|
+
{ actionId: 1, actionActuatorFunc: "gimbalAngleUnlock" as const },
|
|
561
|
+
],
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
553
565
|
function buildSmartObliquePoints(pitchDeg: number, shootInterval: number): SmartObliquePoint[] {
|
|
554
566
|
const stayTime = Math.max(0.1, shootInterval);
|
|
555
567
|
const obliquePitch = -Math.abs(pitchDeg || 45);
|
package/src/plan/plan.test.ts
CHANGED
|
@@ -370,16 +370,30 @@ 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
|
-
|
|
374
|
-
expect(funcs.filter((fn) => fn === "
|
|
373
|
+
const scanlineCount = Math.floor(wl.Folder[0]!.Placemark.length / 2);
|
|
374
|
+
expect(funcs.filter((fn) => fn === "startSmartOblique")).toHaveLength(scanlineCount);
|
|
375
|
+
expect(funcs.filter((fn) => fn === "stopSmartOblique")).toHaveLength(scanlineCount);
|
|
375
376
|
expect(funcs).toContain("gimbalAngleLock");
|
|
376
377
|
expect(funcs).toContain("startSmartOblique");
|
|
377
378
|
expect(funcs).toContain("stopSmartOblique");
|
|
378
379
|
expect(funcs).toContain("gimbalAngleUnlock");
|
|
379
380
|
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
.
|
|
381
|
+
const groups = wl.Folder[0]!.Placemark.flatMap((p) => p.actionGroup ?? []);
|
|
382
|
+
const firstStartGroup = groups.find((g) =>
|
|
383
|
+
g.action.some((a) => a.actionActuatorFunc === "startSmartOblique"),
|
|
384
|
+
)!;
|
|
385
|
+
expect(firstStartGroup.actionGroupStartIndex).toBe(0);
|
|
386
|
+
expect(firstStartGroup.actionGroupEndIndex).toBe(1);
|
|
387
|
+
expect(firstStartGroup.actionTrigger.actionTriggerType).toBe("betweenAdjacentPoints");
|
|
388
|
+
|
|
389
|
+
const firstStopGroup = groups.find((g) =>
|
|
390
|
+
g.action.some((a) => a.actionActuatorFunc === "stopSmartOblique"),
|
|
391
|
+
)!;
|
|
392
|
+
expect(firstStopGroup.actionGroupStartIndex).toBe(1);
|
|
393
|
+
expect(firstStopGroup.actionGroupEndIndex).toBe(1);
|
|
394
|
+
expect(firstStopGroup.actionTrigger.actionTriggerType).toBe("reachPoint");
|
|
395
|
+
|
|
396
|
+
const start = firstStartGroup.action.find((a) => a.actionActuatorFunc === "startSmartOblique");
|
|
383
397
|
expect(start?.actionActuatorFunc).toBe("startSmartOblique");
|
|
384
398
|
if (start?.actionActuatorFunc === "startSmartOblique") {
|
|
385
399
|
expect(start.actionActuatorFuncParam.smartObliqueCycleMode).toBe("unlimited");
|
package/src/types/action.ts
CHANGED
|
@@ -249,9 +249,21 @@ export interface MegaphoneParam {
|
|
|
249
249
|
megaphoneFileMd5: string;
|
|
250
250
|
/** 1=8000, 2=16000, 3=24000, 4=32000, 5=48000, 6=64000 (only 4 supported today). */
|
|
251
251
|
megaphoneFileBitrate: 1 | 2 | 3 | 4 | 5 | 6;
|
|
252
|
+
/** Non-spec DJI Pilot TTS params observed in M4D/M4TD megaphone actions. */
|
|
253
|
+
ttsparam?: MegaphoneTtsParam;
|
|
252
254
|
}
|
|
253
255
|
export type MegaphoneAction = ActionBase<"megaphone", MegaphoneParam>;
|
|
254
256
|
|
|
257
|
+
export interface MegaphoneTtsParam {
|
|
258
|
+
text: string;
|
|
259
|
+
role: "male" | "female";
|
|
260
|
+
language: "CN";
|
|
261
|
+
/** 0-100. */
|
|
262
|
+
volume: number;
|
|
263
|
+
/** 0-100. DJI Pilot exports commonly use 50. */
|
|
264
|
+
speed: number;
|
|
265
|
+
}
|
|
266
|
+
|
|
255
267
|
/** M4D/M4TD only — starts gimbal swing in smart-oblique mode. */
|
|
256
268
|
export interface SmartObliquePoint {
|
|
257
269
|
/** seconds before this pose starts; DJI exports currently use 0. */
|