TrajectoryFollowingController.cpp
Go to the documentation of this file.
2 
3 #include <algorithm>
4 #include <cmath>
5 #include <limits>
6 #include <vector>
7 
8 #include <SimoxUtility/math/convert/mat4f_to_pos.h>
9 #include <SimoxUtility/math/convert/mat4f_to_rpy.h>
10 
14 #include <ArmarXCore/interface/serialization/Eigen/Eigen_fdi.h>
15 
18 
23 #include <armarx/navigation/trajectory_control/global/aron/TrajectoryFollowingControllerParams.aron.generated.h>
26 
28 {
29  // TrajectoryFollowingControllerParams
30 
33  {
35  }
36 
39  {
40  arondto::TrajectoryFollowingControllerParams dto;
41 
44 
45  return dto.toAron();
46  }
47 
50  {
51  arondto::TrajectoryFollowingControllerParams dto;
52  dto.fromAron(dict);
53 
56 
57  return bo;
58  }
59 
60  // TrajectoryFollowingController
61 
63  params(params),
64  pidPos(params.pidPos.Kp,
65  params.pidPos.Ki,
66  params.pidPos.Kd,
67  std::numeric_limits<double>::max(),
68  std::numeric_limits<double>::max(),
69  false,
70  std::vector<bool>{false, false, false}),
71  pidPosTarget(params.pidPos.Kp,
72  params.pidPos.Ki,
73  params.pidPos.Kd,
76  false,
77  std::vector<bool>{false, false, false}),
78  pidOri(params.pidOri.Kp,
79  params.pidOri.Ki,
80  params.pidOri.Kd,
83  false,
84  std::vector<bool>{true, true, true}),
85  pidOriTarget(params.pidOri.Kp,
86  params.pidOri.Ki,
87  params.pidOri.Kd,
90  false,
91  std::vector<bool>{true, true, true})
92  {
93  ARMARX_IMPORTANT << "Trajectory following controller params: "
94  << VAROUT(params.limits.linear) << ", " << VAROUT(params.limits.angular);
95  }
96 
97  core::Twist
99  {
100  if (params.limits.linear == 0 or params.limits.angular == 0)
101  {
102  return core::Twist{.linear = Eigen::Vector3f::Zero(),
103  .angular = Eigen::Vector3f::Zero()};
104  }
105 
108 
109  const core::Twist limits{.linear = Eigen::Vector3f::Ones() * params.limits.linear,
110  .angular = Eigen::Vector3f::Ones() * params.limits.angular};
111 
112  ARMARX_CHECK(limits.linear.allFinite());
113  ARMARX_CHECK(limits.angular.allFinite());
114 
115  // for all entries, scale should be less than 1
116  const float scalePos = twist.linear.norm() / limits.linear.norm();
117  const auto scaleOri = twist.angular.cwiseAbs().cwiseQuotient(limits.angular.cwiseAbs());
118 
119  // ARMARX_CHECK(scalePos.allFinite());
120  ARMARX_CHECK(scaleOri.allFinite());
121 
122  const float scaleMax = std::max(scalePos, scaleOri.maxCoeff());
123 
124  if (scaleMax < 1.0F) // both linear and angular velocity in bounds?
125  {
126  return twist;
127  }
128 
129  ARMARX_CHECK(not std::isnan(scaleMax));
130 
131  // scale such that no limit is violated
132  twist.linear /= scaleMax;
133  twist.angular /= scaleMax;
134 
135  // constexpr float eps = 0.001;
136 
137  // pedantic checks
138  // ARMARX_CHECK_LESS_EQUAL(std::abs(twist.linear.x()), params.limits.linear + eps);
139  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.linear.y()), params.limits.linear + eps);
140  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.linear.z()), params.limits.linear + eps);
141  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.angular.x()), params.limits.angular + eps);
142  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.angular.y()), params.limits.angular + eps);
143  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.angular.z()), params.limits.angular + eps);
144 
145  return twist;
146  }
147 
148  void
150  {
151  params.limits = limits;
152  }
153 
155  {
156  twist.linear *= params.velocityFactor;
157  twist.angular *= params.velocityFactor;
158 
159  return twist;
160  }
161 
163  {
164  ARMARX_CHECK(velocityFactor >= 0)
165  << "Scaling factor for velocity may not be negative, but is " << velocityFactor;
166  ARMARX_CHECK(velocityFactor <= 1)
167  << "Scaling factor for velocity may not be > 1, but is " << velocityFactor;
168 
169  params.velocityFactor = velocityFactor;
170  }
171 
174  const core::Pose& global_T_robot)
175  {
176  using simox::math::mat4f_to_pos;
177  using simox::math::mat4f_to_rpy;
178 
179  const core::Pose currentPose(global_T_robot);
180  const float currentOrientation = mat4f_to_rpy(currentPose.matrix()).z();
181 
182  if (trajectory.points().empty())
183  {
184  ARMARX_INFO << "Trajectory is empty.";
187  .dropPoint = {.waypoint = {.pose = core::Pose::Identity()}, .velocity = 0},
188  .isFinalSegment = true,
189  .currentOrientation = currentOrientation,
190  .desiredOrientation = currentOrientation,
191  .orientationError = 0,
192  .positionError = 0};
193  }
194 
195 
196  const auto projectedPose = trajectory.getProjection(
197  currentPose.translation(), core::VelocityInterpolation::LinearInterpolation);
198 
199 
200  pidPos.update(mat4f_to_pos(currentPose.matrix()),
201  mat4f_to_pos(projectedPose.projection.waypoint.pose.matrix()));
202  pidOri.update(mat4f_to_rpy(currentPose.matrix()),
203  mat4f_to_rpy(projectedPose.projection.waypoint.pose.matrix()));
204 
205  const float desiredOrientation =
206  mat4f_to_rpy(projectedPose.projection.waypoint.pose.matrix()).z();
207 
208  const core::Twist twist = [&]() -> core::Twist
209  {
210  // on the final segment, bahavior differs
211  if (projectedPose.segment == core::Projection::Segment::FINAL)
212  {
213 
214  ARMARX_VERBOSE << deactivateSpam(1) << "final segment";
215  // TODO fairly inefficient to do this every time
216  pidPos.reset();
217  pidOri.reset();
218 
219  pidPosTarget.update(currentPose.translation(),
220  trajectory.points().back().waypoint.pose.translation());
221 
222  pidOriTarget.update(
223  mat4f_to_rpy(currentPose.matrix()),
224  mat4f_to_rpy(trajectory.points().back().waypoint.pose.matrix()));
225 
226  return core::Twist{.linear = pidPosTarget.getControlValue(),
227  .angular = pidOriTarget.getControlValue()};
228  }
229 
230  // pidPosTarget not used yet
231  // TODO fairly inefficient to do this every time
232  pidPosTarget.reset();
233 
234  // the "standard" case following the trajectory
235  const Eigen::Vector3f desiredMovementDirection =
236  (projectedPose.wayPointAfter.waypoint.pose.translation() -
237  projectedPose.wayPointBefore.waypoint.pose.translation())
238  .normalized();
239 
240  const float ffVel = projectedPose.projection.velocity;
241  ARMARX_CHECK_FINITE(ffVel);
242  ARMARX_CHECK_LESS(ffVel, 3000); // 3 m/s should be sufficient, right?
243 
244  const auto feedforwardVelocity = desiredMovementDirection * ffVel;
245 
246  ARMARX_VERBOSE << deactivateSpam(1) << "Feed forward direction "
247  << feedforwardVelocity.normalized();
248  ARMARX_VERBOSE << deactivateSpam(1) << "Feed forward velocity " << feedforwardVelocity;
249  ARMARX_VERBOSE << deactivateSpam(1) << "Control value " << pidPos.getControlValue();
250 
251  return core::Twist{.linear = pidPos.getControlValue() + feedforwardVelocity,
252  .angular = pidOri.getControlValue()};
253  }();
254 
255  const auto twistLimited = applyTwistLimits(twist);
256  ARMARX_VERBOSE << deactivateSpam(1) << "Twist limited linear " << twistLimited.linear.transpose();
257  ARMARX_VERBOSE << deactivateSpam(1) << "Twist limited angular " << twistLimited.angular.transpose();
258 
259  const auto twistScaled = applyVelocityFactor(twistLimited);
260  ARMARX_VERBOSE << deactivateSpam(1) << "Twist scaled linear " << twistScaled.linear.transpose();
261  ARMARX_VERBOSE << deactivateSpam(1) << "Twist scaled angular " << twistScaled.angular.transpose();
262 
263  // convert to the robot's base frame
264  const auto& twistGlobal = twistScaled;
265 
266  core::Twist twistLocal;
267  twistLocal.linear = global_T_robot.linear().inverse() * twistGlobal.linear;
268  // TODO if not in 2D, then this must be changed!
269  twistLocal.angular = twistGlobal.angular;
270 
271 
272  const bool isFinalSegment = projectedPose.segment == core::Projection::Segment::FINAL;
273 
275  .twist = twistLocal,
276  .dropPoint = projectedPose.projection,
277  .isFinalSegment = isFinalSegment,
278  .currentOrientation = currentOrientation,
279  .desiredOrientation = desiredOrientation,
280  .orientationError = std::abs(currentOrientation - desiredOrientation),
281  .positionError = (global_T_robot.translation() -
282  trajectory.points().back().waypoint.pose.translation())
283  .head<2>()
284  .norm()};
285  }
286 
287 } // namespace armarx::navigation::traj_ctrl::global
armarx::navigation::core::GlobalTrajectory
Definition: Trajectory.h:70
armarx::navigation::traj_ctrl::global::TrajectoryFollowingController::updateTwistLimits
void updateTwistLimits(const core::TwistLimits &limits)
Definition: TrajectoryFollowingController.cpp:149
aron_conversions.h
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::navigation::traj_ctrl::global::TrajectoryControllerResult
Definition: TrajectoryController.h:40
armarx::navigation::traj_ctrl::global::TrajectoryFollowingController::control
TrajectoryControllerResult control(const core::GlobalTrajectory &trajectory, const core::Pose &global_T_robot) override
Definition: TrajectoryFollowingController.cpp:173
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::navigation::core::VelocityInterpolation::LinearInterpolation
@ LinearInterpolation
armarx::MultiDimPIDControllerTemplate::reset
void reset()
Definition: MultiDimPIDController.h:214
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
basic_types.h
armarx::navigation::traj_ctrl::global::TrajectoryFollowingController::applyTwistLimits
core::Twist applyTwistLimits(core::Twist twist)
Definition: TrajectoryFollowingController.cpp:98
armarx::navigation::core::Twist::Zero
static Twist Zero()
Definition: basic_types.cpp:13
armarx::navigation::traj_ctrl::global::fromAron
void fromAron(const arondto::TrajectoryControllerParams &dto, TrajectoryControllerParams &bo)
Definition: aron_conversions.cpp:21
armarx::MultiDimPIDControllerTemplate::update
void update(const double deltaSec, const PIDVectorX &measuredValue, const PIDVectorX &targetValue)
Definition: MultiDimPIDController.h:79
armarx::max
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
Definition: VectorHelpers.h:297
armarx::navigation::traj_ctrl::global::Algorithms
Algorithms
Definition: core.h:30
ARMARX_CHECK_LESS
#define ARMARX_CHECK_LESS(lhs, rhs)
This macro evaluates whether lhs is less (<) than rhs and if it turns out to be false it will throw a...
Definition: ExpressionException.h:102
armarx::navigation::core::TwistLimits::linear
float linear
Definition: types.h:82
TrajectoryFollowingController.h
armarx::navigation::traj_ctrl::global::TrajectoryFollowingController::TrajectoryFollowingController
TrajectoryFollowingController(const Params &params)
Definition: TrajectoryFollowingController.cpp:62
Dict.h
armarx::navigation::core::Projection::Segment::FINAL
@ FINAL
armarx::navigation::core::TwistLimits::angular
float angular
Definition: types.h:83
StringHelpers.h
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
armarx::navigation::core::Twist
Definition: basic_types.h:53
TrajectoryController.h
armarx::navigation::traj_ctrl::global::TrajectoryFollowingControllerParams::toAron
aron::data::DictPtr toAron() const override
Definition: TrajectoryFollowingController.cpp:38
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
core.h
MultiDimPIDController.h
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:281
ARMARX_CHECK_FINITE
#define ARMARX_CHECK_FINITE(number)
This macro evaluates whether number is finite (not nan or inf) and if it turns out to be false it wil...
Definition: ExpressionException.h:182
armarx::navigation::core::TwistLimits
Definition: types.h:80
max
T max(T t1, T t2)
Definition: gdiam.h:51
armarx::navigation::traj_ctrl::global::toAron
void toAron(arondto::TrajectoryControllerParams &dto, const TrajectoryControllerParams &bo)
Definition: aron_conversions.cpp:15
ARMARX_CHECK_POSITIVE
#define ARMARX_CHECK_POSITIVE(number)
This macro evaluates whether number is positive (> 0) and if it turns out to be false it will throw a...
Definition: ExpressionException.h:145
ExpressionException.h
armarx::navigation::traj_ctrl::global::TrajectoryFollowingController::applyVelocityFactor
core::Twist applyVelocityFactor(core::Twist twist)
Definition: TrajectoryFollowingController.cpp:154
armarx::navigation::traj_ctrl::global::TrajectoryFollowingController::updateVelocityFactor
void updateVelocityFactor(float velocityFactor)
Definition: TrajectoryFollowingController.cpp:162
armarx::navigation::traj_ctrl::global::TrajectoryFollowingControllerParams::FromAron
static TrajectoryFollowingControllerParams FromAron(const aron::data::DictPtr &dict)
Definition: TrajectoryFollowingController.cpp:49
armarx::navigation::core::Twist::linear
LinearVelocity linear
Definition: basic_types.h:55
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::navigation::traj_ctrl::global::TrajectoryFollowingControllerParams
Definition: TrajectoryFollowingController.h:40
armarx::navigation::traj_ctrl::global::TrajectoryFollowingControllerParams::algorithm
Algorithms algorithm() const override
Definition: TrajectoryFollowingController.cpp:32
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
std
Definition: Application.h:66
armarx::MultiDimPIDControllerTemplate::getControlValue
const PIDVectorX & getControlValue() const
Definition: MultiDimPIDController.h:201
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
armarx::navigation::traj_ctrl::global::TrajectoryFollowingControllerParams::velocityFactor
float velocityFactor
Definition: TrajectoryFollowingController.h:46
armarx::navigation::core::Twist::angular
AngularVelocity angular
Definition: basic_types.h:56
armarx::navigation::traj_ctrl::global::TrajectoryControllerResult::twist
core::Twist twist
Definition: TrajectoryController.h:42
armarx::navigation::traj_ctrl::global::Algorithms::TrajectoryFollowingController
@ TrajectoryFollowingController
armarx::navigation::core::GlobalTrajectory::getProjection
Projection getProjection(const Position &point, const VelocityInterpolation &velocityInterpolation) const
Definition: Trajectory.cpp:245
Logging.h
armarx::navigation::traj_ctrl::global::TrajectoryControllerParams::limits
core::TwistLimits limits
Definition: TrajectoryController.h:54
Trajectory.h
armarx::navigation::traj_ctrl::global
This file is part of ArmarX.
Definition: aron_conversions.cpp:11
armarx::navigation::core::GlobalTrajectory::points
const std::vector< GlobalTrajectoryPoint > & points() const
Definition: Trajectory.cpp:790
types.h
armarx::aron::bo
const std::optional< BoT > & bo
Definition: aron_conversions.h:174