TrajectoryFollowingController.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4
5#include <Eigen/Geometry>
6
7#include <SimoxUtility/math/convert/mat4f_to_pos.h>
8#include <SimoxUtility/math/convert/mat4f_to_rpy.h>
9#include <SimoxUtility/math/convert/mat4f_to_xyyaw.h>
10
15#include <ArmarXCore/interface/serialization/Eigen/Eigen_fdi.h>
16
18
23#include <armarx/navigation/trajectory_control/local/aron/TrajectoryFollowingControllerParams.aron.generated.h>
26
28{
29 // TrajectoryFollowingControllerParams
30
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
64 const core::GeneralConfig& generalConfig)
65 {
67
68 p.limits = generalConfig.maxVel;
69
70 return p;
71 }
72
74 const Params& i_params,
75 const core::GeneralConfig& generalConfig) :
76 params(applyLimitFromGeneralConfig(i_params, generalConfig)),
77 pidPos(params.pidPos.Kp,
78 params.pidPos.Ki,
79 params.pidPos.Kd,
80 std::numeric_limits<double>::max(),
81 std::numeric_limits<double>::max(),
82 false,
83 std::vector<bool>{false, false, false}),
84 pidPosTarget(params.pidPos.Kp / 2,
85 params.pidPos.Ki,
86 params.pidPos.Kd,
87 std::numeric_limits<double>::max(),
88 std::numeric_limits<double>::max(),
89 false,
90 std::vector<bool>{false, false, false}),
91 pidOri(params.pidOri.Kp,
92 params.pidOri.Ki,
93 params.pidOri.Kd,
94 std::numeric_limits<double>::max(),
95 std::numeric_limits<double>::max(),
96 false,
97 std::vector<bool>{true, true, true}),
98 pidOriTarget(params.pidOri.Kp,
99 params.pidOri.Ki,
100 params.pidOri.Kd,
101 std::numeric_limits<double>::max(),
102 std::numeric_limits<double>::max(),
103 false,
104 std::vector<bool>{true, true, true})
105 {
106 ARMARX_IMPORTANT << "Trajectory following controller params: "
107 << VAROUT(params.limits.linear) << ", " << VAROUT(params.limits.angular);
108 }
109
111 params(params),
112 pidPos(params.pidPos.Kp,
113 params.pidPos.Ki,
114 params.pidPos.Kd,
115 std::numeric_limits<double>::max(),
116 std::numeric_limits<double>::max(),
117 false,
118 std::vector<bool>{false, false, false}),
119 pidPosTarget(params.pidPos.Kp / 2,
120 params.pidPos.Ki,
121 params.pidPos.Kd,
122 std::numeric_limits<double>::max(),
123 std::numeric_limits<double>::max(),
124 false,
125 std::vector<bool>{false, false, false}),
126 pidOri(params.pidOri.Kp,
127 params.pidOri.Ki,
128 params.pidOri.Kd,
129 std::numeric_limits<double>::max(),
130 std::numeric_limits<double>::max(),
131 false,
132 std::vector<bool>{true, true, true}),
133 pidOriTarget(params.pidOri.Kp,
134 params.pidOri.Ki,
135 params.pidOri.Kd,
136 std::numeric_limits<double>::max(),
137 std::numeric_limits<double>::max(),
138 false,
139 std::vector<bool>{true, true, true})
140 {
141 ARMARX_IMPORTANT << "Trajectory following controller params: "
142 << VAROUT(params.limits.linear) << ", " << VAROUT(params.limits.angular);
143 }
144
147 {
148 const core::Twist limits{.linear = Eigen::Vector3f::Ones() * params.limits.linear,
149 .angular = Eigen::Vector3f::Ones() * params.limits.angular};
150
151 ARMARX_CHECK((limits.linear.array() > 0).all());
152 ARMARX_CHECK((limits.angular.array() > 0).all());
153 ARMARX_CHECK(limits.linear.allFinite());
154 ARMARX_CHECK(limits.angular.allFinite());
155
156 // for all entries, scale should be less than 1
157 const auto scalePos = twist.linear.cwiseAbs().cwiseQuotient(limits.linear.cwiseAbs());
158 const auto scaleOri = twist.angular.cwiseAbs().cwiseQuotient(limits.angular.cwiseAbs());
159
160 ARMARX_CHECK(scalePos.allFinite());
161 ARMARX_CHECK(scaleOri.allFinite());
162
163 const float scaleMax = std::max(scalePos.maxCoeff(), scaleOri.maxCoeff());
164 if (scaleMax < 1.0F) // both linear and angular velocity in bounds?
165 {
166 return twist;
167 }
168
169 // scale such that no limit is violated
170 twist.linear /= scaleMax;
171 twist.angular /= scaleMax;
172
173 constexpr float eps = 0.001;
174
175 // pedantic checks
176 ARMARX_CHECK_LESS_EQUAL(std::abs(twist.linear.x()), params.limits.linear + eps);
177 ARMARX_CHECK_LESS_EQUAL(std::abs(twist.linear.y()), params.limits.linear + eps);
178 ARMARX_CHECK_LESS_EQUAL(std::abs(twist.linear.z()), params.limits.linear + eps);
179 ARMARX_CHECK_LESS_EQUAL(std::abs(twist.angular.x()), params.limits.angular + eps);
180 ARMARX_CHECK_LESS_EQUAL(std::abs(twist.angular.y()), params.limits.angular + eps);
181 ARMARX_CHECK_LESS_EQUAL(std::abs(twist.angular.z()), params.limits.angular + eps);
182
183 return twist;
184 }
185
188 {
189 twist.linear *= params.velocityFactor;
190 twist.angular *= params.velocityFactor;
191
192 return twist;
193 }
194
195 void
197 {
199 << "Scaling factor for velocity may not be negative, but is " << p.velocityFactor;
201 << "Scaling factor for velocity may not be > 1, but is " << p.velocityFactor;
202
203 // only changes to these to parameters are actually relevant for this class
204 params.velocityFactor = p.velocityFactor;
205 params.limits = p.limits;
206 }
207
210 const Eigen::Isometry3f& global_T_robot)
211 {
212 if (trajectory.points().empty())
213 {
214 ARMARX_INFO << "Trajectory is empty.";
216 .target = {}}; // target not applicable
217 }
218
219 // FIXME
221
222 const core::Evaluation target = trajectory.evaluate(timestamp);
223
224 using simox::math::mat4f_to_pos;
225 using simox::math::mat4f_to_rpy;
226
227 ARMARX_VERBOSE << deactivateSpam(1) << VAROUT(global_T_robot.translation().head<2>());
228 ARMARX_VERBOSE << deactivateSpam(1) << VAROUT(target.pose.translation().head<2>());
230 << VAROUT(target.pose.translation().head<2>() -
231 global_T_robot.translation().head<2>());
232
233 pidPos.update(global_T_robot.translation(), target.pose.translation());
234 pidOri.update(mat4f_to_rpy(global_T_robot.matrix()), mat4f_to_rpy(target.pose.matrix()));
235
236 // Feed forward is already in global frame
237 const core::Twist& twistFeedForward = target.feedforwardTwist;
238
239 const core::Twist twistError{.linear = pidPos.getControlValue(),
240 .angular = pidOri.getControlValue()};
241
242 // const core::Twist twistError = core::Twist::Zero();
243
244 const core::Twist twist{.linear = twistFeedForward.linear + twistError.linear,
245 .angular = twistFeedForward.angular + twistError.angular};
246
247 // const core::Twist twist = twistError;
248
249 ARMARX_VERBOSE << deactivateSpam(1) << VAROUT(twistFeedForward.linear.transpose());
250 ARMARX_VERBOSE << deactivateSpam(1) << VAROUT(twistFeedForward.angular.transpose());
251
252 ARMARX_VERBOSE << deactivateSpam(1) << VAROUT(twistError.linear.transpose());
253 ARMARX_VERBOSE << deactivateSpam(1) << VAROUT(twistError.angular.transpose());
254
255 ARMARX_VERBOSE << deactivateSpam(1) << VAROUT(twist.linear.transpose());
256 ARMARX_VERBOSE << deactivateSpam(1) << VAROUT(twist.angular.transpose());
257
258
259 const auto twistLimited = applyTwistLimits(twist);
260 ARMARX_VERBOSE << deactivateSpam(1) << "Twist limited linear "
261 << twistLimited.linear.transpose();
262 ARMARX_VERBOSE << deactivateSpam(1) << "Twist limited angular "
263 << twistLimited.angular.transpose();
264
265 const auto twistScaled = applyVelocityFactor(twistLimited);
266 ARMARX_VERBOSE << deactivateSpam(1) << "Twist scaled linear "
267 << twistScaled.linear.transpose();
268 ARMARX_VERBOSE << deactivateSpam(1) << "Twist scaled angular "
269 << twistScaled.angular.transpose();
270
271 // convert to the robot's base frame
272 const auto& twistGlobal = twistScaled;
273
274 const core::Twist twistLocal{.linear =
275 global_T_robot.linear().inverse() * twistGlobal.linear,
276 .angular = twistGlobal.angular};
277
278 return TrajectoryControllerResult{.twist = twistLocal, .target = target};
279 }
280
281} // namespace armarx::navigation::traj_ctrl::local
std::string timestamp()
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define VAROUT(x)
static DateTime Now()
Current time on the virtual clock.
Definition Clock.cpp:93
static Duration MilliSeconds(std::int64_t milliSeconds)
Constructs a duration in milliseconds.
Definition Duration.cpp:48
Represents a point in time.
Definition DateTime.h:25
TrajectoryControllerResult control(const core::LocalTrajectory &trajectory, const Eigen::Isometry3f &global_T_robot) override
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_LESS_EQUAL(lhs, rhs)
This macro evaluates whether lhs is less or equal (<=) rhs and if it turns out to be false it will th...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::shared_ptr< Dict > DictPtr
Definition Dict.h:42
This file is part of ArmarX.
Definition fwd.h:47
void toAron(arondto::TrajectoryFollowingControllerParams &dto, const TrajectoryFollowingControllerParams &bo)
TrajectoryFollowingController::Params applyLimitFromGeneralConfig(const TrajectoryFollowingController::Params &params, const core::GeneralConfig &generalConfig)
void fromAron(const arondto::TrajectoryFollowingControllerParams &dto, TrajectoryFollowingControllerParams &bo)
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
static TrajectoryFollowingControllerParams FromAron(const aron::data::DictPtr &dict)