@@ -44,8 +44,11 @@ void SwingTrajectoryPlanner::updateSwingMotions(scalar_t initTime, scalar_t fina
44
44
throw std::runtime_error (" [SwingTrajectoryPlanner] terrain cannot be null. Update the terrain before planning swing motions" );
45
45
}
46
46
47
- // Need a copy to provide joint references later (possibly adapted with inverse kinematics)
48
- targetTrajectories_ = targetTrajectories;
47
+ // Need a copy to
48
+ // 1. possibly overwrite joint references later (adapted with inverse kinematics)
49
+ // 2. ensure a maximum interval between references points.
50
+ // 3. unsure we have samples at start and end of the MPC horizon.
51
+ subsampleReferenceTrajectory (targetTrajectories, initTime, finalTime);
49
52
50
53
const feet_array_t <std::vector<ContactTiming>> contactTimingsPerLeg = extractContactTimingsPerLeg (modeSchedule);
51
54
@@ -429,6 +432,56 @@ std::vector<ConvexTerrain> SwingTrajectoryPlanner::selectNominalFootholdTerrain(
429
432
return nominalFootholdTerrain;
430
433
}
431
434
435
+ void SwingTrajectoryPlanner::subsampleReferenceTrajectory (const ocs2::TargetTrajectories& targetTrajectories, scalar_t initTime,
436
+ scalar_t finalTime) {
437
+ if (targetTrajectories.empty ()) {
438
+ throw std::runtime_error (" [SwingTrajectoryPlanner] provided target trajectory cannot be empty." );
439
+ }
440
+
441
+ targetTrajectories_.clear ();
442
+
443
+ // Add first reference
444
+ {
445
+ const auto initInterpIndex = ocs2::LinearInterpolation::timeSegment (initTime, targetTrajectories.timeTrajectory );
446
+ targetTrajectories_.timeTrajectory .push_back (initTime);
447
+ targetTrajectories_.stateTrajectory .push_back (
448
+ ocs2::LinearInterpolation::interpolate (initInterpIndex, targetTrajectories.stateTrajectory ));
449
+ targetTrajectories_.inputTrajectory .push_back (
450
+ ocs2::LinearInterpolation::interpolate (initInterpIndex, targetTrajectories.inputTrajectory ));
451
+ }
452
+
453
+ for (int k = 0 ; k < targetTrajectories.timeTrajectory .size (); ++k) {
454
+ if (targetTrajectories.timeTrajectory [k] < initTime) {
455
+ continue ; // Drop all samples before init time
456
+ } else if (targetTrajectories.timeTrajectory [k] > finalTime) {
457
+ // Add final time sample. Samples after final time are also kept for touchdowns after the horizon.
458
+ const auto finalInterpIndex = ocs2::LinearInterpolation::timeSegment (finalTime, targetTrajectories.timeTrajectory );
459
+ targetTrajectories_.timeTrajectory .push_back (finalTime);
460
+ targetTrajectories_.stateTrajectory .push_back (
461
+ ocs2::LinearInterpolation::interpolate (finalInterpIndex, targetTrajectories.stateTrajectory ));
462
+ targetTrajectories_.inputTrajectory .push_back (
463
+ ocs2::LinearInterpolation::interpolate (finalInterpIndex, targetTrajectories.inputTrajectory ));
464
+ }
465
+
466
+ // Check if we need to add extra intermediate samples
467
+ while (targetTrajectories_.timeTrajectory .back () + settings_.maximumReferenceSampleTime < targetTrajectories.timeTrajectory [k]) {
468
+ const scalar_t t = targetTrajectories_.timeTrajectory .back () + settings_.maximumReferenceSampleTime ;
469
+ const auto interpIndex = ocs2::LinearInterpolation::timeSegment (t, targetTrajectories.timeTrajectory );
470
+
471
+ targetTrajectories_.timeTrajectory .push_back (t);
472
+ targetTrajectories_.stateTrajectory .push_back (
473
+ ocs2::LinearInterpolation::interpolate (interpIndex, targetTrajectories.stateTrajectory ));
474
+ targetTrajectories_.inputTrajectory .push_back (
475
+ ocs2::LinearInterpolation::interpolate (interpIndex, targetTrajectories.inputTrajectory ));
476
+ }
477
+
478
+ // Add the original reference sample
479
+ targetTrajectories_.timeTrajectory .push_back (targetTrajectories.timeTrajectory [k]);
480
+ targetTrajectories_.stateTrajectory .push_back (targetTrajectories.stateTrajectory [k]);
481
+ targetTrajectories_.inputTrajectory .push_back (targetTrajectories.inputTrajectory [k]);
482
+ }
483
+ }
484
+
432
485
void SwingTrajectoryPlanner::adaptJointReferencesWithInverseKinematics (scalar_t finalTime) {
433
486
const scalar_t damping = 0.01 ; // Quite some damping on the IK to get well conditions references.
434
487
@@ -548,6 +601,7 @@ SwingTrajectoryPlannerSettings loadSwingTrajectorySettings(const std::string& fi
548
601
ocs2::loadData::loadPtreeValue (pt, settings.nominalLegExtension , prefix + " nominalLegExtension" , verbose);
549
602
ocs2::loadData::loadPtreeValue (pt, settings.legOverExtensionPenalty , prefix + " legOverExtensionPenalty" , verbose);
550
603
ocs2::loadData::loadPtreeValue (pt, settings.referenceExtensionAfterHorizon , prefix + " referenceExtensionAfterHorizon" , verbose);
604
+ ocs2::loadData::loadPtreeValue (pt, settings.maximumReferenceSampleTime , prefix + " maximumReferenceSampleTime" , verbose);
551
605
ocs2::loadData::loadPtreeValue (pt, settings.swingTrajectoryFromReference , prefix + " swingTrajectoryFromReference" , verbose);
552
606
553
607
if (verbose) {
0 commit comments