Crocoddyl
 
Loading...
Searching...
No Matches
floating-base-thrusters.hpp
1
2// BSD 3-Clause License
3//
4// Copyright (C) 2014-2024, Heriot-Watt University
5// Copyright note valid unless otherwise stated in individual files.
6// All rights reserved.
8
9#ifndef CROCODDYL_MULTIBODY_ACTUATIONS_PROPELLERS_HPP_
10#define CROCODDYL_MULTIBODY_ACTUATIONS_PROPELLERS_HPP_
11
12#include <pinocchio/multibody/fwd.hpp>
13#include <pinocchio/spatial/se3.hpp>
14#include <vector>
15
16#include "crocoddyl/core/actuation-base.hpp"
17#include "crocoddyl/core/utils/exception.hpp"
18#include "crocoddyl/multibody/states/multibody.hpp"
19
20namespace crocoddyl {
21
22enum ThrusterType { CW = 0, CCW };
23
24template <typename _Scalar>
26 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
27
28 typedef _Scalar Scalar;
29 typedef pinocchio::SE3Tpl<Scalar> SE3;
31
42 ThrusterTpl(const SE3& pose, const Scalar ctorque,
43 const ThrusterType type = CW,
44 const Scalar min_thrust = Scalar(0.),
45 const Scalar max_thrust = std::numeric_limits<Scalar>::infinity())
46 : pose(pose),
48 type(type),
51
62 ThrusterTpl(const Scalar ctorque, const ThrusterType type = CW,
63 const Scalar min_thrust = Scalar(0.),
64 const Scalar max_thrust = std::numeric_limits<Scalar>::infinity())
65 : pose(SE3::Identity()),
67 type(type),
71 : pose(clone.pose),
72 ctorque(clone.ctorque),
73 type(clone.type),
75 max_thrust(clone.max_thrust) {}
76
77 ThrusterTpl& operator=(const ThrusterTpl<Scalar>& other) {
78 if (this != &other) {
79 pose = other.pose;
80 ctorque = other.ctorque;
81 type = other.type;
82 min_thrust = other.min_thrust;
83 max_thrust = other.max_thrust;
84 }
85 return *this;
86 }
87
88 template <typename OtherScalar>
89 bool operator==(const ThrusterTpl<OtherScalar>& other) const {
90 return (pose == other.pose && ctorque == other.ctorque &&
91 type == other.type && min_thrust == other.min_thrust &&
92 max_thrust == other.max_thrust);
93 }
94
95 friend std::ostream& operator<<(std::ostream& os,
96 const ThrusterTpl<Scalar>& X) {
97 os << " pose:" << std::endl
98 << X.pose << " ctorque: " << X.ctorque << std::endl
99 << " type: " << X.type << std::endl
100 << "min_thrust: " << X.min_thrust << std::endl
101 << "max_thrust: " << X.max_thrust << std::endl;
102 return os;
103 }
104
105 SE3 pose;
106 Scalar ctorque;
107 ThrusterType type;
109 Scalar min_thrust;
110 Scalar max_thrust;
111};
112
131template <typename _Scalar>
133 : public ActuationModelAbstractTpl<_Scalar> {
134 public:
135 typedef _Scalar Scalar;
141 typedef typename MathBase::Vector3s Vector3s;
142 typedef typename MathBase::VectorXs VectorXs;
143 typedef typename MathBase::MatrixXs MatrixXs;
144
152 ActuationModelFloatingBaseThrustersTpl(std::shared_ptr<StateMultibody> state,
153 const std::vector<Thruster>& thrusters)
154 : Base(state,
155 state->get_nv() -
156 state->get_pinocchio()
157 ->joints[(
158 state->get_pinocchio()->existJointName("root_joint")
159 ? state->get_pinocchio()->getJointId("root_joint")
160 : 0)]
161 .nv() +
162 thrusters.size()),
163 thrusters_(thrusters),
164 n_thrusters_(thrusters.size()),
165 W_thrust_(state_->get_nv(), nu_),
166 update_data_(true) {
167 if (!state->get_pinocchio()->existJointName("root_joint")) {
168 throw_pretty(
169 "Invalid argument: "
170 << "the first joint has to be a root one (e.g., free-flyer joint)");
171 }
172 // Update the joint actuation part
173 W_thrust_.setZero();
174 if (nu_ > n_thrusters_) {
175 W_thrust_.bottomRightCorner(nu_ - n_thrusters_, nu_ - n_thrusters_)
176 .diagonal()
177 .setOnes();
178 }
179 // Update the floating base actuation part
181 }
183
192 virtual void calc(const std::shared_ptr<Data>& data,
193 const Eigen::Ref<const VectorXs>&,
194 const Eigen::Ref<const VectorXs>& u) {
195 if (static_cast<std::size_t>(u.size()) != nu_) {
196 throw_pretty(
197 "Invalid argument: " << "u has wrong dimension (it should be " +
198 std::to_string(nu_) + ")");
199 }
200 if (update_data_) {
201 updateData(data);
202 }
203 data->tau.noalias() = data->dtau_du * u;
204 }
205
214#ifndef NDEBUG
215 virtual void calcDiff(const std::shared_ptr<Data>& data,
216 const Eigen::Ref<const VectorXs>&,
217 const Eigen::Ref<const VectorXs>&) {
218#else
219 virtual void calcDiff(const std::shared_ptr<Data>&,
220 const Eigen::Ref<const VectorXs>&,
221 const Eigen::Ref<const VectorXs>&) {
222#endif
223 // The derivatives has constant values which were set in createData.
224 assert_pretty(MatrixXs(data->dtau_du).isApprox(W_thrust_),
225 "dtau_du has wrong value");
226 }
227
228 virtual void commands(const std::shared_ptr<Data>& data,
229 const Eigen::Ref<const VectorXs>&,
230 const Eigen::Ref<const VectorXs>& tau) {
231 data->u.noalias() = data->Mtau * tau;
232 }
233
234#ifndef NDEBUG
235 virtual void torqueTransform(const std::shared_ptr<Data>& data,
236 const Eigen::Ref<const VectorXs>&,
237 const Eigen::Ref<const VectorXs>&) {
238#else
239 virtual void torqueTransform(const std::shared_ptr<Data>&,
240 const Eigen::Ref<const VectorXs>&,
241 const Eigen::Ref<const VectorXs>&) {
242#endif
243 // The torque transform has constant values which were set in createData.
244 assert_pretty(MatrixXs(data->Mtau).isApprox(Mtau_), "Mtau has wrong value");
245 }
246
252 virtual std::shared_ptr<Data> createData() {
253 std::shared_ptr<Data> data =
254 std::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
255 updateData(data);
256 return data;
257 }
258
262 const std::vector<Thruster>& get_thrusters() const { return thrusters_; }
263
267 std::size_t get_nthrusters() const { return n_thrusters_; }
268
277 void set_thrusters(const std::vector<Thruster>& thrusters) {
278 if (static_cast<std::size_t>(thrusters.size()) != n_thrusters_) {
279 throw_pretty("Invalid argument: "
280 << "the number of thrusters is wrong (it should be " +
281 std::to_string(n_thrusters_) + ")");
282 }
283 thrusters_ = thrusters;
284 // Update the mapping matrix from thrusters thrust to body force/moments
285 for (std::size_t i = 0; i < n_thrusters_; ++i) {
286 const Thruster& p = thrusters_[i];
287 const Vector3s& f_z = p.pose.rotation() * Vector3s::UnitZ();
288 W_thrust_.template topRows<3>().col(i) += f_z;
289 W_thrust_.template middleRows<3>(3).col(i).noalias() +=
290 p.pose.translation().cross(f_z);
291 switch (p.type) {
292 case CW:
293 W_thrust_.template middleRows<3>(3).col(i) += p.ctorque * f_z;
294 break;
295 case CCW:
296 W_thrust_.template middleRows<3>(3).col(i) -= p.ctorque * f_z;
297 break;
298 }
299 }
300 // Compute the torque transform matrix from generalized torques to joint
301 // torque inputs
302 Mtau_ = pseudoInverse(MatrixXs(W_thrust_));
303 S_.noalias() = W_thrust_ * Mtau_;
304 update_data_ = true;
305 }
306
307 const MatrixXs& get_Wthrust() const { return W_thrust_; }
308
309 const MatrixXs& get_S() const { return S_; }
310
311 void print(std::ostream& os) const {
312 os << "ActuationModelFloatingBaseThrusters {nu=" << nu_
313 << ", nthrusters=" << n_thrusters_ << ", thrusters=" << std::endl;
314 for (std::size_t i = 0; i < n_thrusters_; ++i) {
315 os << std::to_string(i) << ": " << thrusters_[i];
316 }
317 os << "}";
318 }
319
320 protected:
321 std::vector<Thruster> thrusters_;
322 std::size_t n_thrusters_;
323 MatrixXs W_thrust_;
324 MatrixXs Mtau_;
326 MatrixXs S_;
327
328 bool update_data_;
329 using Base::nu_;
330 using Base::state_;
331
332 private:
333 void updateData(const std::shared_ptr<Data>& data) {
334 data->dtau_du = W_thrust_;
335 data->Mtau = Mtau_;
336 const std::size_t nv = state_->get_nv();
337 for (std::size_t k = 0; k < nv; ++k) {
338 if (fabs(S_(k, k)) < std::numeric_limits<Scalar>::epsilon()) {
339 data->tau_set[k] = false;
340 } else {
341 data->tau_set[k] = true;
342 }
343 }
344 update_data_ = false;
345 }
346};
347
348} // namespace crocoddyl
349
350#endif // CROCODDYL_MULTIBODY_ACTUATIONS_PROPELLERS_HPP_
Abstract class for the actuation-mapping model.
std::shared_ptr< StateAbstract > state_
Model of the state.
std::size_t nu_
Dimension of joint torque inputs.
Actuation models for floating base systems actuated with thrusters.
MatrixXs S_
Selection matrix for under-actuation part.
std::shared_ptr< StateAbstract > state_
Model of the state.
virtual void commands(const std::shared_ptr< Data > &data, const Eigen::Ref< const VectorXs > &, const Eigen::Ref< const VectorXs > &tau)
Compute the joint torque input from the generalized torques.
virtual void calcDiff(const std::shared_ptr< Data > &data, const Eigen::Ref< const VectorXs > &, const Eigen::Ref< const VectorXs > &)
Compute the Jacobians of the floating base thruster actuation function.
virtual void calc(const std::shared_ptr< Data > &data, const Eigen::Ref< const VectorXs > &, const Eigen::Ref< const VectorXs > &u)
Compute the actuation signal and actuation set from its thrust and joint torque inputs .
ActuationModelFloatingBaseThrustersTpl(std::shared_ptr< StateMultibody > state, const std::vector< Thruster > &thrusters)
Initialize the floating base actuation model equipped with thrusters.
std::vector< Thruster > thrusters_
Vector of thrusters.
std::size_t nu_
Dimension of joint torque inputs.
std::size_t get_nthrusters() const
Return the number of thrusters.
MatrixXs W_thrust_
Matrix from thrusters thrusts to body wrench.
virtual std::shared_ptr< Data > createData()
Create the floating base thruster actuation data.
void print(std::ostream &os) const
Print relevant information of the residual model.
virtual void torqueTransform(const std::shared_ptr< Data > &data, const Eigen::Ref< const VectorXs > &, const Eigen::Ref< const VectorXs > &)
Compute the torque transform from generalized torques to joint torque inputs.
void set_thrusters(const std::vector< Thruster > &thrusters)
Modify the vector of thrusters.
const std::vector< Thruster > & get_thrusters() const
Return the vector of thrusters.
State multibody representation.
Definition multibody.hpp:35
ThrusterTpl(const SE3 &pose, const Scalar ctorque, const ThrusterType type=CW, const Scalar min_thrust=Scalar(0.), const Scalar max_thrust=std::numeric_limits< Scalar >::infinity())
Initialize the thruster in a give pose from the root joint.
ThrusterTpl(const Scalar ctorque, const ThrusterType type=CW, const Scalar min_thrust=Scalar(0.), const Scalar max_thrust=std::numeric_limits< Scalar >::infinity())
Initialize the thruster in a pose in the origin of the root joint.
Scalar ctorque
Coefficient of generated torque per thrust.