64 pidPos(params.pidPos.Kp,
67 std::numeric_limits<double>::
max(),
68 std::numeric_limits<double>::
max(),
70 std::vector<bool>{
false,
false,
false}),
71 pidPosTarget(params.pidPos.Kp,
74 std::numeric_limits<double>::max(),
75 std::numeric_limits<double>::max(),
77 std::vector<bool>{false, false, false}),
78 pidOri(params.pidOri.Kp,
81 std::numeric_limits<double>::max(),
82 std::numeric_limits<double>::max(),
84 std::vector<bool>{true, true, true}),
85 pidOriTarget(params.pidOri.Kp,
88 std::numeric_limits<double>::max(),
89 std::numeric_limits<double>::max(),
91 std::vector<bool>{true, true, true})
94 <<
VAROUT(params.limits.linear) <<
", " <<
VAROUT(params.limits.angular);
217 using simox::math::mat4f_to_pos;
218 using simox::math::mat4f_to_rpy;
221 const float currentOrientation = mat4f_to_rpy(currentPose.matrix()).z();
228 .dropPoint = {.waypoint = {.pose = core::Pose::Identity()}, .velocity = 0},
229 .isFinalSegment =
true,
230 .currentOrientation = currentOrientation,
231 .desiredOrientation = currentOrientation,
232 .orientationError = 0,
237 const TrajectoryId currentTrajectoryId{
239 .firstTranslation =
trajectory.points().front().waypoint.pose.translation(),
240 .lastTranslation =
trajectory.points().back().waypoint.pose.translation()};
242 if (not lastTrajectoryId_.has_value() or lastTrajectoryId_.value() != currentTrajectoryId)
244 lastTrajectoryId_ = currentTrajectoryId;
245 lastProjectionIndex_ = 0;
249 const std::size_t startSegment =
250 (lastProjectionIndex_ > 0) ? lastProjectionIndex_ - 1 : 0;
252 const auto projectedPose =
trajectory.getProjection(
256 static_cast<std::size_t
>(params.maxSegmentsAhead),
257 params.orientationWeight);
259 lastProjectionIndex_ = projectedPose.indexBefore;
262 pidPos.update(mat4f_to_pos(currentPose.matrix()),
263 mat4f_to_pos(projectedPose.projection.waypoint.pose.matrix()));
264 pidOri.update(mat4f_to_rpy(currentPose.matrix()),
265 mat4f_to_rpy(projectedPose.projection.waypoint.pose.matrix()));
267 const float desiredOrientation =
268 mat4f_to_rpy(projectedPose.projection.waypoint.pose.matrix()).z();
270 float ffAngular = 0.0f;
271 float cappedFfVel = 0.0f;
284 pidPosTarget.update(currentPose.translation(),
285 trajectory.points().back().waypoint.pose.translation());
288 mat4f_to_rpy(currentPose.matrix()),
289 mat4f_to_rpy(
trajectory.points().back().waypoint.pose.matrix()));
291 return core::Twist{.linear = pidPosTarget.getControlValue(),
292 .angular = pidOriTarget.getControlValue()};
297 pidPosTarget.reset();
300 const Eigen::Vector3f desiredMovementDirection =
301 (projectedPose.wayPointAfter.waypoint.pose.translation() -
302 projectedPose.wayPointBefore.waypoint.pose.translation())
305 const float ffVel = projectedPose.projection.velocity;
311 if (params.enableAngularFeedforward)
313 const float yawBefore =
314 mat4f_to_rpy(projectedPose.wayPointBefore.waypoint.pose.matrix()).z();
315 const float yawAfter =
316 mat4f_to_rpy(projectedPose.wayPointAfter.waypoint.pose.matrix()).z();
317 const float angularDelta = signedShortestAngularDiff(yawAfter, yawBefore);
319 const float segmentLength =
320 (projectedPose.wayPointAfter.waypoint.pose.translation() -
321 projectedPose.wayPointBefore.waypoint.pose.translation())
325 const float requiredAngularRate =
326 (segmentLength > 1.0f) ? (angularDelta / segmentLength * ffVel) : 0.0f;
329 if (std::abs(requiredAngularRate) > params.limits.angular)
331 cappedFfVel = ffVel * (params.limits.angular / std::abs(requiredAngularRate));
336 (segmentLength > 1.0f) ? (angularDelta / segmentLength * cappedFfVel) : 0.0f;
341 const auto feedforwardVelocity = desiredMovementDirection * cappedFfVel;
344 << feedforwardVelocity.normalized();
349 angularFF.z() = ffAngular;
350 return core::Twist{.linear = pidPos.getControlValue() + feedforwardVelocity,
351 .angular = pidOri.getControlValue() + angularFF};
356 << twistLimited.linear.transpose();
358 << twistLimited.angular.transpose();
362 << twistScaled.linear.transpose();
364 << twistScaled.angular.transpose();
367 const auto& twistGlobal = twistScaled;
370 twistLocal.
linear = global_T_robot.linear().inverse() * twistGlobal.linear;
372 twistLocal.
angular = twistGlobal.angular;
379 .dropPoint = projectedPose.projection,
380 .isFinalSegment = isFinalSegment,
381 .currentOrientation = currentOrientation,
382 .desiredOrientation = desiredOrientation,
383 .orientationError = std::abs(currentOrientation - desiredOrientation),
384 .positionError = (global_T_robot.translation() -
385 trajectory.points().back().waypoint.pose.translation())
388 .ffAngular = ffAngular,
389 .cappedFfVel = cappedFfVel};