@@ -44,8 +44,11 @@ void SwingTrajectoryPlanner::updateSwingMotions(scalar_t initTime, scalar_t fina
4444 throw std::runtime_error (" [SwingTrajectoryPlanner] terrain cannot be null. Update the terrain before planning swing motions" );
4545 }
4646
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);
4952
5053 const feet_array_t <std::vector<ContactTiming>> contactTimingsPerLeg = extractContactTimingsPerLeg (modeSchedule);
5154
@@ -429,6 +432,56 @@ std::vector<ConvexTerrain> SwingTrajectoryPlanner::selectNominalFootholdTerrain(
429432 return nominalFootholdTerrain;
430433}
431434
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+
432485void SwingTrajectoryPlanner::adaptJointReferencesWithInverseKinematics (scalar_t finalTime) {
433486 const scalar_t damping = 0.01 ; // Quite some damping on the IK to get well conditions references.
434487
@@ -548,6 +601,7 @@ SwingTrajectoryPlannerSettings loadSwingTrajectorySettings(const std::string& fi
548601 ocs2::loadData::loadPtreeValue (pt, settings.nominalLegExtension , prefix + " nominalLegExtension" , verbose);
549602 ocs2::loadData::loadPtreeValue (pt, settings.legOverExtensionPenalty , prefix + " legOverExtensionPenalty" , verbose);
550603 ocs2::loadData::loadPtreeValue (pt, settings.referenceExtensionAfterHorizon , prefix + " referenceExtensionAfterHorizon" , verbose);
604+ ocs2::loadData::loadPtreeValue (pt, settings.maximumReferenceSampleTime , prefix + " maximumReferenceSampleTime" , verbose);
551605 ocs2::loadData::loadPtreeValue (pt, settings.swingTrajectoryFromReference , prefix + " swingTrajectoryFromReference" , verbose);
552606
553607 if (verbose) {
0 commit comments