GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/multibody/friction-cone.hxx
Date: 2025-05-13 10:30:51
Exec Total Coverage
Lines: 0 162 0.0%
Branches: 0 214 0.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2025, University of Edinburgh, University of Oxford,
5 // Heriot-Watt University
6 // Copyright note valid unless otherwise stated in individual files.
7 // All rights reserved.
8 ///////////////////////////////////////////////////////////////////////////////
9
10 namespace crocoddyl {
11
12 template <typename Scalar>
13 FrictionConeTpl<Scalar>::FrictionConeTpl(const Matrix3s& R, const Scalar mu,
14 std::size_t nf, const bool inner_appr,
15 const Scalar min_nforce,
16 const Scalar max_nforce)
17 : nf_(nf),
18 R_(R),
19 mu_(mu),
20 inner_appr_(inner_appr),
21 min_nforce_(min_nforce),
22 max_nforce_(max_nforce) {
23 if (nf_ % 2 != 0) {
24 nf_ = 4;
25 std::cerr << "Warning: nf has to be an even number, set to 4" << std::endl;
26 }
27 if (mu < Scalar(0.)) {
28 mu_ = Scalar(1.);
29 std::cerr << "Warning: mu has to be a positive value, set to 1."
30 << std::endl;
31 }
32 if (min_nforce < Scalar(0.)) {
33 min_nforce_ = Scalar(0.);
34 std::cerr << "Warning: min_nforce has to be a positive value, set to 0"
35 << std::endl;
36 }
37 if (max_nforce < Scalar(0.)) {
38 max_nforce_ = std::numeric_limits<Scalar>::infinity();
39 std::cerr << "Warning: max_nforce has to be a positive value, set to "
40 "infinity value"
41 << std::endl;
42 }
43 A_ = MatrixX3s::Zero(nf_ + 1, 3);
44 ub_ = VectorXs::Zero(nf_ + 1);
45 lb_ = VectorXs::Zero(nf_ + 1);
46
47 // Update the inequality matrix and bounds
48 update();
49 }
50
51 template <typename Scalar>
52 FrictionConeTpl<Scalar>::FrictionConeTpl()
53 : nf_(4),
54 A_(nf_ + 1, 3),
55 ub_(nf_ + 1),
56 lb_(nf_ + 1),
57 R_(Matrix3s::Identity()),
58 mu_(Scalar(0.7)),
59 inner_appr_(true),
60 min_nforce_(Scalar(0.)),
61 max_nforce_(std::numeric_limits<Scalar>::infinity()) {
62 A_.setZero();
63 ub_.setZero();
64 lb_.setZero();
65
66 // Update the inequality matrix and bounds
67 update();
68 }
69
70 template <typename Scalar>
71 FrictionConeTpl<Scalar>::FrictionConeTpl(const FrictionConeTpl<Scalar>& cone)
72 : nf_(cone.get_nf()),
73 A_(cone.get_A()),
74 ub_(cone.get_ub()),
75 lb_(cone.get_lb()),
76 R_(cone.get_R()),
77 mu_(cone.get_mu()),
78 inner_appr_(cone.get_inner_appr()),
79 min_nforce_(cone.get_min_nforce()),
80 max_nforce_(cone.get_max_nforce()) {}
81
82 template <typename Scalar>
83 FrictionConeTpl<Scalar>::~FrictionConeTpl() {}
84
85 template <typename Scalar>
86 void FrictionConeTpl<Scalar>::update() {
87 // Initialize the matrix and bounds
88 A_.setZero();
89 ub_.setZero();
90 lb_.setOnes();
91 lb_ *= -std::numeric_limits<Scalar>::infinity();
92
93 // Compute the mu given the type of friction cone approximation
94 Scalar mu = mu_;
95 const Scalar theta =
96 static_cast<Scalar>(2.0) * pi<Scalar>() / static_cast<Scalar>(nf_);
97 if (inner_appr_) {
98 mu *= cos(theta * Scalar(0.5));
99 }
100
101 // Create a temporary object for computation
102 Matrix3s R_transpose = R_.transpose();
103
104 // Update the inequality matrix and the bounds
105 // This matrix is defined as
106 // [ 1 0 -mu;
107 // -1 0 -mu;
108 // 0 1 -mu;
109 // 0 -1 -mu;
110 // 0 0 1]
111 Scalar theta_i;
112 Vector3s tsurf_i;
113 Vector3s mu_nsurf =
114 -mu * Vector3s::UnitZ(); // We can pull this out because it's reused.
115 std::size_t row = 0;
116 for (std::size_t i = 0; i < nf_ / 2; ++i) {
117 theta_i = theta * static_cast<Scalar>(i);
118 tsurf_i << cos(theta_i), sin(theta_i), Scalar(0.);
119 A_.row(row++) = (mu_nsurf + tsurf_i).transpose() * R_transpose;
120 A_.row(row++) = (mu_nsurf - tsurf_i).transpose() * R_transpose;
121 }
122 A_.row(nf_) = R_transpose.row(2);
123 lb_(nf_) = min_nforce_;
124 ub_(nf_) = max_nforce_;
125 }
126
127 template <typename Scalar>
128 void FrictionConeTpl<Scalar>::update(const Vector3s& normal, const Scalar mu,
129 const bool inner_appr,
130 const Scalar min_nforce,
131 const Scalar max_nforce) {
132 Vector3s nsurf = normal;
133 // Sanity checks
134 if (!nsurf.isUnitary()) {
135 nsurf /= normal.norm();
136 std::cerr
137 << "Warning: normal is not an unitary vector, then we normalized it"
138 << std::endl;
139 }
140 R_ = Quaternions::FromTwoVectors(nsurf, Vector3s::UnitZ()).toRotationMatrix();
141 set_mu(mu);
142 set_inner_appr(inner_appr);
143 set_min_nforce(min_nforce);
144 set_max_nforce(max_nforce);
145
146 // Update the inequality matrix and bounds
147 update();
148 }
149
150 template <typename Scalar>
151 template <typename NewScalar>
152 FrictionConeTpl<NewScalar> FrictionConeTpl<Scalar>::cast() const {
153 typedef FrictionConeTpl<NewScalar> ReturnType;
154 ReturnType ret(R_.template cast<NewScalar>(), scalar_cast<NewScalar>(mu_),
155 nf_, inner_appr_, scalar_cast<NewScalar>(min_nforce_),
156 scalar_cast<NewScalar>(max_nforce_));
157 return ret;
158 }
159
160 template <typename Scalar>
161 const typename MathBaseTpl<Scalar>::MatrixX3s& FrictionConeTpl<Scalar>::get_A()
162 const {
163 return A_;
164 }
165
166 template <typename Scalar>
167 const typename MathBaseTpl<Scalar>::VectorXs& FrictionConeTpl<Scalar>::get_ub()
168 const {
169 return ub_;
170 }
171
172 template <typename Scalar>
173 const typename MathBaseTpl<Scalar>::VectorXs& FrictionConeTpl<Scalar>::get_lb()
174 const {
175 return lb_;
176 }
177
178 template <typename Scalar>
179 const typename MathBaseTpl<Scalar>::Matrix3s& FrictionConeTpl<Scalar>::get_R()
180 const {
181 return R_;
182 }
183
184 template <typename Scalar>
185 typename MathBaseTpl<Scalar>::Vector3s FrictionConeTpl<Scalar>::get_nsurf() {
186 return R_.row(2).transpose();
187 }
188
189 template <typename Scalar>
190 const Scalar FrictionConeTpl<Scalar>::get_mu() const {
191 return mu_;
192 }
193
194 template <typename Scalar>
195 std::size_t FrictionConeTpl<Scalar>::get_nf() const {
196 return nf_;
197 }
198
199 template <typename Scalar>
200 bool FrictionConeTpl<Scalar>::get_inner_appr() const {
201 return inner_appr_;
202 }
203
204 template <typename Scalar>
205 const Scalar FrictionConeTpl<Scalar>::get_min_nforce() const {
206 return min_nforce_;
207 }
208
209 template <typename Scalar>
210 const Scalar FrictionConeTpl<Scalar>::get_max_nforce() const {
211 return max_nforce_;
212 }
213
214 template <typename Scalar>
215 void FrictionConeTpl<Scalar>::set_R(const Matrix3s& R) {
216 R_ = R;
217 }
218
219 template <typename Scalar>
220 void FrictionConeTpl<Scalar>::set_nsurf(const Vector3s& nsurf) {
221 Vector3s normal = nsurf;
222 // Sanity checks
223 if (!nsurf.isUnitary()) {
224 normal /= nsurf.norm();
225 std::cerr
226 << "Warning: normal is not an unitary vector, then we normalized it"
227 << std::endl;
228 }
229 R_ =
230 Quaternions::FromTwoVectors(normal, Vector3s::UnitZ()).toRotationMatrix();
231 }
232
233 template <typename Scalar>
234 void FrictionConeTpl<Scalar>::set_mu(const Scalar mu) {
235 if (mu < Scalar(0.)) {
236 mu_ = Scalar(1.);
237 std::cerr << "Warning: mu has to be a positive value, set to 1."
238 << std::endl;
239 }
240 mu_ = mu;
241 }
242
243 template <typename Scalar>
244 void FrictionConeTpl<Scalar>::set_inner_appr(const bool inner_appr) {
245 inner_appr_ = inner_appr;
246 }
247
248 template <typename Scalar>
249 void FrictionConeTpl<Scalar>::set_min_nforce(const Scalar min_nforce) {
250 if (min_nforce < Scalar(0.)) {
251 min_nforce_ = Scalar(0.);
252 std::cerr << "Warning: min_nforce has to be a positive value, set to 0"
253 << std::endl;
254 }
255 min_nforce_ = min_nforce;
256 }
257
258 template <typename Scalar>
259 void FrictionConeTpl<Scalar>::set_max_nforce(const Scalar max_nforce) {
260 if (max_nforce < Scalar(0.)) {
261 max_nforce_ = std::numeric_limits<Scalar>::infinity();
262 std::cerr << "Warning: max_nforce has to be a positive value, set to "
263 "infinity value"
264 << std::endl;
265 }
266 max_nforce_ = max_nforce;
267 }
268
269 template <typename Scalar>
270 FrictionConeTpl<Scalar>& FrictionConeTpl<Scalar>::operator=(
271 const FrictionConeTpl<Scalar>& other) {
272 if (this != &other) {
273 nf_ = other.get_nf();
274 A_ = other.get_A();
275 ub_ = other.get_ub();
276 lb_ = other.get_lb();
277 R_ = other.get_R();
278 mu_ = other.get_mu();
279 inner_appr_ = other.get_inner_appr();
280 min_nforce_ = other.get_min_nforce();
281 max_nforce_ = other.get_max_nforce();
282 }
283 return *this;
284 }
285
286 template <typename Scalar>
287 std::ostream& operator<<(std::ostream& os, const FrictionConeTpl<Scalar>& X) {
288 os << " R: " << X.get_R() << std::endl;
289 os << " mu: " << X.get_mu() << std::endl;
290 os << " nf: " << X.get_nf() << std::endl;
291 os << "inner_appr: ";
292 if (X.get_inner_appr()) {
293 os << "true" << std::endl;
294 } else {
295 os << "false" << std::endl;
296 }
297 os << " min_force: " << X.get_min_nforce() << std::endl;
298 os << " max_force: " << X.get_max_nforce() << std::endl;
299 return os;
300 }
301
302 } // namespace crocoddyl
303