77 pidPos(params.pidPos.Kp,
80 std::numeric_limits<double>::
max(),
81 std::numeric_limits<double>::
max(),
83 std::vector<bool>{
false,
false,
false}),
84 pidPosTarget(params.pidPos.Kp / 2,
87 std::numeric_limits<double>::max(),
88 std::numeric_limits<double>::max(),
90 std::vector<bool>{false, false, false}),
91 pidOri(params.pidOri.Kp,
94 std::numeric_limits<double>::max(),
95 std::numeric_limits<double>::max(),
97 std::vector<bool>{true, true, true}),
98 pidOriTarget(params.pidOri.Kp,
101 std::numeric_limits<double>::max(),
102 std::numeric_limits<double>::max(),
104 std::vector<bool>{true, true, true})
107 <<
VAROUT(params.limits.linear) <<
", " <<
VAROUT(params.limits.angular);
112 pidPos(params.pidPos.Kp,
115 std::numeric_limits<double>::
max(),
116 std::numeric_limits<double>::
max(),
118 std::vector<bool>{
false,
false,
false}),
119 pidPosTarget(params.pidPos.Kp / 2,
122 std::numeric_limits<double>::max(),
123 std::numeric_limits<double>::max(),
125 std::vector<bool>{false, false, false}),
126 pidOri(params.pidOri.Kp,
129 std::numeric_limits<double>::max(),
130 std::numeric_limits<double>::max(),
132 std::vector<bool>{true, true, true}),
133 pidOriTarget(params.pidOri.Kp,
136 std::numeric_limits<double>::max(),
137 std::numeric_limits<double>::max(),
139 std::vector<bool>{true, true, true})
142 <<
VAROUT(params.limits.linear) <<
", " <<
VAROUT(params.limits.angular);
148 const core::Twist limits{.linear = Eigen::Vector3f::Ones() * params.limits.linear,
149 .angular = Eigen::Vector3f::Ones() * params.limits.angular};
157 const auto scalePos = twist.
linear.cwiseAbs().cwiseQuotient(limits.linear.cwiseAbs());
158 const auto scaleOri = twist.
angular.cwiseAbs().cwiseQuotient(limits.angular.cwiseAbs());
163 const float scaleMax = std::max(scalePos.maxCoeff(), scaleOri.maxCoeff());
170 if (params.coupleLinearAndAngularLimits)
177 if (scalePos.maxCoeff() >= 1.0F)
179 twist.
linear /= scalePos.maxCoeff();
181 if (scaleOri.maxCoeff() >= 1.0F)
183 twist.
angular /= scaleOri.maxCoeff();
187 constexpr float eps = 0.001;
244 const Eigen::Isometry3f& global_T_robot)
258 using simox::math::mat4f_to_pos;
259 using simox::math::mat4f_to_rpy;
264 <<
VAROUT(target.pose.translation().head<2>() -
265 global_T_robot.translation().head<2>());
267 pidPos.update(global_T_robot.translation(), target.pose.translation());
268 pidOri.update(mat4f_to_rpy(global_T_robot.matrix()), mat4f_to_rpy(target.pose.matrix()));
271 core::Twist twistFeedForward = target.feedforwardTwist;
272 float ffAngular = twistFeedForward.
angular.z();
273 float cappedFfVel = twistFeedForward.
linear.norm();
276 if (params.enableAngularFeedforward)
278 if (std::abs(ffAngular) < 0.001f && target.idx + 1 <
trajectory.points().size())
280 const auto& ptBefore =
trajectory.points().at(target.idx);
281 const auto& ptAfter =
trajectory.points().at(target.idx + 1);
283 const float yawBefore = mat4f_to_rpy(ptBefore.pose.matrix()).z();
284 const float yawAfter = mat4f_to_rpy(ptAfter.pose.matrix()).z();
285 const float angularDelta = signedShortestAngularDiff(yawAfter, yawBefore);
288 (ptAfter.pose.translation() - ptBefore.pose.translation()).norm();
289 const float dt = (ptAfter.timestamp - ptBefore.timestamp).toSecondsDouble();
293 const float requiredRate = angularDelta /
dt;
294 ffAngular = requiredRate;
297 if (std::abs(requiredRate) > params.limits.angular)
299 const float scale = params.limits.angular / std::abs(requiredRate);
300 twistFeedForward.
linear *= scale;
301 twistFeedForward.
angular.z() = requiredRate * scale;
302 cappedFfVel = twistFeedForward.
linear.norm();
306 else if (std::abs(ffAngular) > params.limits.angular)
309 const float scale = params.limits.angular / std::abs(ffAngular);
310 twistFeedForward.
linear *= scale;
311 twistFeedForward.
angular *= scale;
313 cappedFfVel = twistFeedForward.
linear.norm();
317 const core::Twist twistError{.linear = pidPos.getControlValue(),
318 .angular = pidOri.getControlValue()};
323 .angular = twistFeedForward.
angular + twistError.angular};
339 << twistLimited.linear.transpose();
341 << twistLimited.angular.transpose();
345 << twistScaled.linear.transpose();
347 << twistScaled.angular.transpose();
350 const auto& twistGlobal = twistScaled;
353 global_T_robot.linear().inverse() * twistGlobal.linear,
354 .angular = twistGlobal.angular};
358 .ffAngular = ffAngular,
359 .cappedFfVel = cappedFfVel};