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