TrajectoryFollowingController.cpp
Go to the documentation of this file.
2 
3 #include <cmath>
4 
5 #include <SimoxUtility/math/convert/mat4f_to_pos.h>
6 #include <SimoxUtility/math/convert/mat4f_to_rpy.h>
7 #include <SimoxUtility/math/convert/mat4f_to_xyyaw.h>
8 #include <VirtualRobot/Robot.h>
9 
12 #include <ArmarXCore/interface/serialization/Eigen/Eigen_fdi.h>
13 
15 
20 #include <armarx/navigation/trajectory_control/global/aron/TrajectoryFollowingControllerParams.aron.generated.h>
23 
25 {
26  // TrajectoryFollowingControllerParams
27 
30  {
32  }
33 
36  {
37  arondto::TrajectoryFollowingControllerParams dto;
38 
41 
42  return dto.toAron();
43  }
44 
47  {
48  arondto::TrajectoryFollowingControllerParams dto;
49  dto.fromAron(dict);
50 
53 
54  return bo;
55  }
56 
57  // TrajectoryFollowingController
58 
60  params(params),
61  pidPos(params.pidPos.Kp,
62  params.pidPos.Ki,
63  params.pidPos.Kd,
64  std::numeric_limits<double>::max(),
65  std::numeric_limits<double>::max(),
66  false,
67  std::vector<bool>{false, false, false}),
68  pidPosTarget(params.pidPos.Kp,
69  params.pidPos.Ki,
70  params.pidPos.Kd,
73  false,
74  std::vector<bool>{false, false, false}),
75  pidOri(params.pidOri.Kp,
76  params.pidOri.Ki,
77  params.pidOri.Kd,
80  false,
81  std::vector<bool>{true, true, true}),
82  pidOriTarget(params.pidOri.Kp,
83  params.pidOri.Ki,
84  params.pidOri.Kd,
87  false,
88  std::vector<bool>{true, true, true})
89  {
90  ARMARX_IMPORTANT << "Trajectory following controller params: "
91  << VAROUT(params.limits.linear) << ", " << VAROUT(params.limits.angular);
92  }
93 
94  core::Twist
96  {
97  const core::Twist limits{.linear = Eigen::Vector3f::Ones() * params.limits.linear,
98  .angular = Eigen::Vector3f::Ones() * params.limits.angular};
99 
100  ARMARX_CHECK((limits.linear.array() > 0).all());
101  ARMARX_CHECK((limits.angular.array() > 0).all());
102 
103  ARMARX_CHECK(limits.linear.allFinite());
104  ARMARX_CHECK(limits.angular.allFinite());
105 
106  // for all entries, scale should be less than 1
107  const float scalePos = twist.linear.norm() / limits.linear.norm();
108  const auto scaleOri = twist.angular.cwiseAbs().cwiseQuotient(limits.angular.cwiseAbs());
109 
110  // ARMARX_CHECK(scalePos.allFinite());
111  ARMARX_CHECK(scaleOri.allFinite());
112 
113  const float scaleMax = std::max(scalePos, scaleOri.maxCoeff());
114 
115  if (scaleMax < 1.0F) // both linear and angular velocity in bounds?
116  {
117  return twist;
118  }
119 
120  ARMARX_CHECK(not std::isnan(scaleMax));
121 
122  // scale such that no limit is violated
123  twist.linear /= scaleMax;
124  twist.angular /= scaleMax;
125 
126  // constexpr float eps = 0.001;
127 
128  // pedantic checks
129  // ARMARX_CHECK_LESS_EQUAL(std::abs(twist.linear.x()), params.limits.linear + eps);
130  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.linear.y()), params.limits.linear + eps);
131  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.linear.z()), params.limits.linear + eps);
132  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.angular.x()), params.limits.angular + eps);
133  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.angular.y()), params.limits.angular + eps);
134  //ARMARX_CHECK_LESS_EQUAL(std::abs(twist.angular.z()), params.limits.angular + eps);
135 
136  return twist;
137  }
138 
141  const core::Pose& global_T_robot)
142  {
143  using simox::math::mat4f_to_pos;
144  using simox::math::mat4f_to_rpy;
145 
146  const core::Pose currentPose(global_T_robot);
147  const float currentOrientation = mat4f_to_rpy(currentPose.matrix()).z();
148 
149  if (trajectory.points().empty())
150  {
151  ARMARX_INFO << "Trajectory is empty.";
154  .dropPoint = {.waypoint = {.pose = core::Pose::Identity()}, .velocity = 0},
155  .isFinalSegment = true,
156  .currentOrientation = currentOrientation,
157  .desiredOrientation = currentOrientation,
158  .orientationError = 0,
159  .positionError = 0};
160  }
161 
162 
163  const auto projectedPose = trajectory.getProjection(
164  currentPose.translation(), core::VelocityInterpolation::LinearInterpolation);
165 
166 
167  pidPos.update(mat4f_to_pos(currentPose.matrix()),
168  mat4f_to_pos(projectedPose.projection.waypoint.pose.matrix()));
169  pidOri.update(mat4f_to_rpy(currentPose.matrix()),
170  mat4f_to_rpy(projectedPose.projection.waypoint.pose.matrix()));
171 
172  const float desiredOrientation =
173  mat4f_to_rpy(projectedPose.projection.waypoint.pose.matrix()).z();
174 
175  const core::Twist twist = [&]() -> core::Twist
176  {
177  // on the final segment, bahavior differs
178  if (projectedPose.segment == core::Projection::Segment::FINAL)
179  {
180 
181  ARMARX_VERBOSE << deactivateSpam(1) << "final segment";
182  // TODO fairly inefficient to do this every time
183  pidPos.reset();
184  pidOri.reset();
185 
186  pidPosTarget.update(currentPose.translation(),
187  trajectory.points().back().waypoint.pose.translation());
188 
189  pidOriTarget.update(
190  mat4f_to_rpy(currentPose.matrix()),
191  mat4f_to_rpy(trajectory.points().back().waypoint.pose.matrix()));
192 
193  return core::Twist{.linear = pidPosTarget.getControlValue(),
194  .angular = pidOriTarget.getControlValue()};
195  }
196 
197  // pidPosTarget not used yet
198  // TODO fairly inefficient to do this every time
199  pidPosTarget.reset();
200 
201  // the "standard" case following the trajectory
202  const Eigen::Vector3f desiredMovementDirection =
203  (projectedPose.wayPointAfter.waypoint.pose.translation() -
204  projectedPose.wayPointBefore.waypoint.pose.translation())
205  .normalized();
206 
207  const float ffVel = projectedPose.projection.velocity;
208  ARMARX_CHECK_FINITE(ffVel);
209  ARMARX_CHECK_LESS(ffVel, 3000); // 3 m/s should be sufficient, right?
210 
211  const auto feedforwardVelocity = desiredMovementDirection * ffVel;
212 
213  ARMARX_VERBOSE << deactivateSpam(1) << "Feed forward direction "
214  << feedforwardVelocity.normalized();
215  ARMARX_VERBOSE << deactivateSpam(1) << "Feed forward velocity " << feedforwardVelocity;
216  ARMARX_VERBOSE << deactivateSpam(1) << "Control value " << pidPos.getControlValue();
217 
218  return core::Twist{.linear = pidPos.getControlValue() + feedforwardVelocity,
219  .angular = pidOri.getControlValue()};
220  }();
221 
222  const auto twistLimited = applyTwistLimits(twist);
223  ARMARX_VERBOSE << deactivateSpam(1) << "Twist limited " << twistLimited.linear.transpose();
224  ARMARX_VERBOSE << deactivateSpam(1) << "Twist angular " << twistLimited.angular.transpose();
225 
226  // convert to the robot's base frame
227  const auto& twistGlobal = twistLimited;
228 
229  core::Twist twistLocal;
230  twistLocal.linear = global_T_robot.linear().inverse() * twistGlobal.linear;
231  // TODO if not in 2D, then this must be changed!
232  twistLocal.angular = twistGlobal.angular;
233 
234 
235  const bool isFinalSegment = projectedPose.segment == core::Projection::Segment::FINAL;
236 
238  .twist = twistLocal,
239  .dropPoint = projectedPose.projection,
240  .isFinalSegment = isFinalSegment,
241  .currentOrientation = currentOrientation,
242  .desiredOrientation = desiredOrientation,
243  .orientationError = std::abs(currentOrientation - desiredOrientation),
244  .positionError = (global_T_robot.translation() -
245  trajectory.points().back().waypoint.pose.translation())
246  .head<2>()
247  .norm()};
248  }
249 
250 } // namespace armarx::navigation::traj_ctrl::global
armarx::navigation::core::GlobalTrajectory
Definition: Trajectory.h:68
aron_conversions.h
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::navigation::traj_ctrl::global::TrajectoryControllerResult
Definition: TrajectoryController.h:44
armarx::navigation::traj_ctrl::global::TrajectoryFollowingController::control
TrajectoryControllerResult control(const core::GlobalTrajectory &trajectory, const core::Pose &global_T_robot) override
Definition: TrajectoryFollowingController.cpp:140
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::navigation::core::VelocityInterpolation::LinearInterpolation
@ LinearInterpolation
armarx::MultiDimPIDControllerTemplate::reset
void reset()
Definition: MultiDimPIDController.h:196
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:95
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:26
armarx::MultiDimPIDControllerTemplate::update
void update(const double deltaSec, const PIDVectorX &measuredValue, const PIDVectorX &targetValue)
Definition: MultiDimPIDController.h:75
armarx::max
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
Definition: VectorHelpers.h:267
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:93
TrajectoryFollowingController.h
armarx::navigation::traj_ctrl::global::TrajectoryFollowingController::TrajectoryFollowingController
TrajectoryFollowingController(const Params &params)
Definition: TrajectoryFollowingController.cpp:59
armarx::navigation::core::Projection::Segment::FINAL
@ FINAL
armarx::navigation::core::TwistLimits::angular
float angular
Definition: types.h:94
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:35
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:72
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
core.h
MultiDimPIDController.h
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:253
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
max
T max(T t1, T t2)
Definition: gdiam.h:48
armarx::navigation::traj_ctrl::global::toAron
void toAron(arondto::TrajectoryControllerParams &dto, const TrajectoryControllerParams &bo)
Definition: aron_conversions.cpp:20
ExpressionException.h
armarx::navigation::traj_ctrl::global::TrajectoryFollowingControllerParams::FromAron
static TrajectoryFollowingControllerParams FromAron(const aron::data::DictPtr &dict)
Definition: TrajectoryFollowingController.cpp:46
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:34
armarx::navigation::traj_ctrl::global::TrajectoryFollowingControllerParams::algorithm
Algorithms algorithm() const override
Definition: TrajectoryFollowingController.cpp:29
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
std
Definition: Application.h:66
armarx::MultiDimPIDControllerTemplate::getControlValue
const PIDVectorX & getControlValue() const
Definition: MultiDimPIDController.h:186
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
F
Definition: ExportDialogControllerTest.cpp:16
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:46
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:243
Logging.h
armarx::navigation::traj_ctrl::global::TrajectoryControllerParams::limits
core::TwistLimits limits
Definition: TrajectoryController.h:57
Trajectory.h
armarx::navigation::traj_ctrl::global
This file is part of ArmarX.
Definition: aron_conversions.cpp:16
armarx::navigation::core::GlobalTrajectory::points
const std::vector< GlobalTrajectoryPoint > & points() const
Definition: Trajectory.cpp:732
types.h
armarx::aron::bo
const std::optional< BoT > & bo
Definition: aron_conversions.h:168