@lumikmz/kmz 0.6.3 → 0.6.4

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.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
- actionGroupId: 0,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumikmz/kmz",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "description": "DJI KMZ/WPML domain model + plan() algorithm + validate(), spec-aligned types mirroring docs/kmz/",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -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);
@@ -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
- expect(funcs.filter((fn) => fn === "startSmartOblique")).toHaveLength(1);
374
- expect(funcs.filter((fn) => fn === "stopSmartOblique")).toHaveLength(1);
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 start = wl.Folder[0]!.Placemark.flatMap((p) => p.actionGroup ?? [])
381
- .flatMap((g) => g.action)
382
- .find((a) => a.actionActuatorFunc === "startSmartOblique");
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");