Directory: | ./ |
---|---|
File: | src/explicit/relative-transformation.cc |
Date: | 2025-05-05 12:19:30 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 63 | 133 | 47.4% |
Branches: | 82 | 436 | 18.8% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2017 - 2018, Joseph Mirabel | ||
2 | // Authors: Joseph Mirabel (joseph.mirabel@laas.fr) | ||
3 | // | ||
4 | |||
5 | // Redistribution and use in source and binary forms, with or without | ||
6 | // modification, are permitted provided that the following conditions are | ||
7 | // met: | ||
8 | // | ||
9 | // 1. Redistributions of source code must retain the above copyright | ||
10 | // notice, this list of conditions and the following disclaimer. | ||
11 | // | ||
12 | // 2. Redistributions in binary form must reproduce the above copyright | ||
13 | // notice, this list of conditions and the following disclaimer in the | ||
14 | // documentation and/or other materials provided with the distribution. | ||
15 | // | ||
16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
20 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | ||
27 | // DAMAGE. | ||
28 | |||
29 | #include <boost/serialization/utility.hpp> | ||
30 | #include <boost/serialization/vector.hpp> | ||
31 | #include <boost/serialization/weak_ptr.hpp> | ||
32 | #include <hpp/constraints/explicit/relative-transformation.hh> | ||
33 | #include <hpp/constraints/serialization.hh> | ||
34 | #include <hpp/pinocchio/device.hh> | ||
35 | #include <hpp/util/serialization.hh> | ||
36 | #include <pinocchio/serialization/se3.hpp> | ||
37 | #include <pinocchio/spatial/explog.hpp> | ||
38 | #include <pinocchio/spatial/skew.hpp> | ||
39 | |||
40 | #include "../serialization.hh" | ||
41 | |||
42 | namespace hpp { | ||
43 | namespace constraints { | ||
44 | namespace explicit_ { | ||
45 | namespace { | ||
46 | typedef JointJacobian_t::ConstNRowsBlockXpr<3>::Type ConstHalfJacobian_t; | ||
47 | ✗ | inline ConstHalfJacobian_t omega(const JointJacobian_t& j) { | |
48 | ✗ | return j.bottomRows<3>(); | |
49 | } | ||
50 | ✗ | inline ConstHalfJacobian_t trans(const JointJacobian_t& j) { | |
51 | ✗ | return j.topRows<3>(); | |
52 | } | ||
53 | |||
54 | 16 | void inputVariable(JointConstPtr_t joint, std::vector<bool>& conf, | |
55 | std::vector<bool>& vel) { | ||
56 |
5/6✓ Branch 1 taken 6 times.
✓ Branch 2 taken 16 times.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 16 times.
|
22 | while (joint && joint->index() != 0) { |
57 |
2/2✓ Branch 2 taken 42 times.
✓ Branch 3 taken 6 times.
|
48 | for (size_type i = 0; i < joint->configSize(); ++i) |
58 |
2/4✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
|
42 | conf[joint->rankInConfiguration() + i] = |
59 | 84 | !conf[joint->rankInConfiguration() + i]; | |
60 |
2/2✓ Branch 2 taken 36 times.
✓ Branch 3 taken 6 times.
|
42 | for (size_type i = 0; i < joint->numberDof(); ++i) |
61 |
2/4✓ Branch 6 taken 36 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 36 times.
✗ Branch 10 not taken.
|
36 | vel[joint->rankInVelocity() + i] = !vel[joint->rankInVelocity() + i]; |
62 | hppDout(info, "Adding joint " << joint->name() << " as input variable."); | ||
63 | 6 | joint = joint->parentJoint(); | |
64 | } | ||
65 | 16 | } | |
66 | |||
67 | 16 | BlockIndex::segments_t vectorOfBoolToIntervals(std::vector<bool>& v) { | |
68 | 16 | BlockIndex::segments_t ret; | |
69 |
2/2✓ Branch 1 taken 286 times.
✓ Branch 2 taken 16 times.
|
302 | for (std::size_t i = 0; i < v.size(); ++i) |
70 |
4/6✓ Branch 1 taken 286 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 78 times.
✓ Branch 5 taken 208 times.
✓ Branch 8 taken 78 times.
✗ Branch 9 not taken.
|
286 | if (v[i]) ret.push_back(BlockIndex::segment_t(i, 1)); |
71 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | BlockIndex::shrink(ret); |
72 | 16 | return ret; | |
73 | } | ||
74 | |||
75 | 8 | BlockIndex::segments_t jointConfInterval(JointConstPtr_t j) { | |
76 | return BlockIndex::segments_t( | ||
77 |
3/6✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
|
16 | 1, BlockIndex::segment_t(j->rankInConfiguration(), j->configSize())); |
78 | } | ||
79 | 8 | BlockIndex::segments_t jointVelInterval(JointConstPtr_t j) { | |
80 | return BlockIndex::segments_t( | ||
81 |
3/6✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
|
16 | 1, BlockIndex::segment_t(j->rankInVelocity(), j->numberDof())); |
82 | } | ||
83 | } // namespace | ||
84 | |||
85 | 8 | RelativeTransformationPtr_t RelativeTransformation::create( | |
86 | const std::string& name, const DevicePtr_t& robot, | ||
87 | const JointConstPtr_t& joint1, const JointConstPtr_t& joint2, | ||
88 | const Transform3s& frame1, const Transform3s& frame2) { | ||
89 |
2/4✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
|
8 | std::vector<bool> conf(robot->configSize(), false); |
90 |
2/4✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
|
8 | std::vector<bool> vel(robot->numberDof(), false); |
91 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | inputVariable(joint1, conf, vel); |
92 |
2/4✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
|
8 | inputVariable(joint2->parentJoint(), conf, vel); |
93 | |||
94 | RelativeTransformation* ptr = new RelativeTransformation( | ||
95 | name, robot, joint1, joint2, frame1, frame2, | ||
96 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
24 | vectorOfBoolToIntervals(conf), jointConfInterval(joint2), |
97 |
5/10✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 17 not taken.
|
16 | vectorOfBoolToIntervals(vel), jointVelInterval(joint2)); |
98 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | RelativeTransformationPtr_t shPtr(ptr); |
99 | 8 | ptr->init(shPtr); | |
100 | 16 | return shPtr; | |
101 | 8 | } | |
102 | |||
103 | 8 | RelativeTransformation::RelativeTransformation( | |
104 | const std::string& name, const DevicePtr_t& robot, | ||
105 | const JointConstPtr_t& joint1, const JointConstPtr_t& joint2, | ||
106 | const Transform3s& frame1, const Transform3s& frame2, | ||
107 | const segments_t inConf, const segments_t outConf, const segments_t inVel, | ||
108 | 8 | const segments_t outVel, std::vector<bool> /*mask*/) | |
109 | : DifferentiableFunction(BlockIndex::cardinal(inConf), | ||
110 | BlockIndex::cardinal(inVel), | ||
111 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | pinocchio::LiegroupSpace::SE3(), name), |
112 | 8 | robot_(robot), | |
113 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | parentJoint_(joint2->parentJoint()), |
114 | 8 | joint1_(joint1), | |
115 | 8 | joint2_(joint2), | |
116 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | frame1_(frame1), |
117 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | frame2_(frame2), |
118 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | inConf_(inConf), |
119 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | inVel_(inVel), |
120 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | outConf_(outConf), |
121 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | outVel_(outVel), |
122 |
9/18✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 17 not taken.
✓ Branch 20 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 8 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 8 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 8 times.
✗ Branch 30 not taken.
|
32 | F1inJ1_invF2inJ2_(frame1 * frame2.inverse()) {} |
123 | |||
124 | 6800 | void RelativeTransformation::forwardKinematics(vectorIn_t arg) const { | |
125 |
1/2✓ Branch 4 taken 6800 times.
✗ Branch 5 not taken.
|
6800 | qsmall_ = inConf_.rview(robot_->currentConfiguration()); |
126 |
2/2✓ Branch 1 taken 199 times.
✓ Branch 2 taken 6601 times.
|
6800 | if (qsmall_ != arg) { |
127 | 199 | q_ = robot_->currentConfiguration(); | |
128 |
1/2✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
|
199 | inConf_.lview(q_) = arg; |
129 |
1/2✓ Branch 3 taken 199 times.
✗ Branch 4 not taken.
|
199 | robot_->currentConfiguration(q_); |
130 | } | ||
131 | 6800 | robot_->computeForwardKinematics(pinocchio::JOINT_POSITION); | |
132 | 6800 | } | |
133 | |||
134 | 6800 | void RelativeTransformation::impl_compute(LiegroupElementRef result, | |
135 | vectorIn_t argument) const { | ||
136 |
2/4✓ Branch 1 taken 6800 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6800 times.
✗ Branch 5 not taken.
|
6800 | forwardKinematics(argument); |
137 | |||
138 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 6800 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
6800 | bool hasParent = (parentJoint_ && parentJoint_->index() > 0); |
139 | |||
140 | // J1 * M1/J1 = J2 * M2/J2 | ||
141 | // J2 = J1 * M1/J1 * M2/J2^{-1} | ||
142 | // J2 = J2_{parent} * T | ||
143 | // T = J2_{parent}^{-1} * J2 | ||
144 | // T = J2_{parent}^{-1} * J1 * F1/J1 * F2/J2^{-1} | ||
145 |
1/2✓ Branch 1 taken 6800 times.
✗ Branch 2 not taken.
|
6800 | Transform3s freeflyerPose; |
146 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6800 times.
|
6800 | if (!joint1_) |
147 | ✗ | freeflyerPose = F1inJ1_invF2inJ2_; | |
148 | else | ||
149 |
3/6✓ Branch 2 taken 6800 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6800 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6800 times.
✗ Branch 9 not taken.
|
6800 | freeflyerPose = joint1_->currentTransformation() * F1inJ1_invF2inJ2_; |
150 | |||
151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6800 times.
|
6800 | if (hasParent) |
152 | ✗ | freeflyerPose = parentJoint_->currentTransformation().actInv(freeflyerPose); | |
153 | |||
154 |
3/6✓ Branch 2 taken 6800 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6800 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6800 times.
✗ Branch 9 not taken.
|
6800 | freeflyerPose = joint2_->positionInParentFrame().actInv(freeflyerPose); |
155 | |||
156 | typedef Transform3s::Quaternion Q_t; | ||
157 |
3/6✓ Branch 1 taken 6800 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 6800 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6800 times.
✗ Branch 9 not taken.
|
6800 | result.vector().head<3>() = freeflyerPose.translation(); |
158 |
4/8✓ Branch 1 taken 6800 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6800 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 6800 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 6800 times.
✗ Branch 13 not taken.
|
6800 | result.vector().tail<4>() = Q_t(freeflyerPose.rotation()).coeffs(); |
159 | 6800 | } | |
160 | |||
161 | ✗ | void RelativeTransformation::impl_jacobian(matrixOut_t jacobian, | |
162 | vectorIn_t arg) const { | ||
163 | ✗ | LiegroupElement result(outputSpace()); | |
164 | ✗ | impl_compute(result, arg); | |
165 | ✗ | Configuration_t q(robot_->currentConfiguration()); | |
166 | ✗ | outConf_.lview(q) = result.vector(); | |
167 | ✗ | robot_->currentConfiguration(q); | |
168 | ✗ | robot_->computeForwardKinematics(pinocchio::JOINT_POSITION | | |
169 | pinocchio::JACOBIAN); | ||
170 | |||
171 | ✗ | bool absolute = !joint1_; | |
172 | ✗ | bool hasParent = (parentJoint_ && parentJoint_->index() > 0); | |
173 | |||
174 | ✗ | static const JointJacobian_t Jabs; | |
175 | ✗ | const JointJacobian_t& J1(absolute ? Jabs : joint1_->jacobian()); | |
176 | // const JointJacobian_t& J2_parent (parentJoint_->jacobian()); | ||
177 | |||
178 | ✗ | const matrix3_t& R1(absolute ? matrix3_t::Identity().eval() | |
179 | ✗ | : joint1_->currentTransformation().rotation()); | |
180 | ✗ | const matrix3_t& R2(joint2_->currentTransformation().rotation()); | |
181 | const matrix3_t& R2_inParentFrame( | ||
182 | ✗ | joint2_->positionInParentFrame().rotation()); | |
183 | |||
184 | const vector3_t& t1(absolute | ||
185 | ✗ | ? vector3_t::Zero().eval() | |
186 | ✗ | : joint1_->currentTransformation().translation()); | |
187 | |||
188 | matrix3_t cross1 = ::pinocchio::skew( | ||
189 | ✗ | (R1 * F1inJ1_invF2inJ2_.translation()).eval()), | |
190 | ✗ | cross2; | |
191 | ✗ | if (hasParent) { | |
192 | const vector3_t& t2_parent( | ||
193 | ✗ | parentJoint_->currentTransformation().translation()); | |
194 | ✗ | cross2 = ::pinocchio::skew((t2_parent - t1).eval()); | |
195 | |||
196 | ✗ | if (absolute) | |
197 | ✗ | J2_parent_minus_J1_.noalias() = parentJoint_->jacobian(); | |
198 | else | ||
199 | ✗ | J2_parent_minus_J1_.noalias() = parentJoint_->jacobian() - J1; | |
200 | } else { | ||
201 | ✗ | cross2 = -::pinocchio::skew(t1); | |
202 | // J2_parent_minus_J1_ = - J1; | ||
203 | } | ||
204 | |||
205 | // Express velocity of J1 * M1/J1 * M2/J2^{-1} in J2_{parent}. | ||
206 | ✗ | if (hasParent) { | |
207 | const matrix3_t& R2_parent( | ||
208 | ✗ | parentJoint_->currentTransformation().rotation()); | |
209 | ✗ | const JointJacobian_t& J2_parent(parentJoint_->jacobian()); | |
210 | |||
211 | ✗ | tmpJac_.noalias() = | |
212 | ✗ | (R2_inParentFrame.transpose() * R2_parent.transpose()) * | |
213 | ✗ | (cross1 * (omega(J2_parent_minus_J1_))-cross2 * omega(J2_parent) - | |
214 | ✗ | trans(J2_parent_minus_J1_)); | |
215 | ✗ | jacobian.topRows<3>() = inVel_.rview(tmpJac_); | |
216 | } else { | ||
217 | ✗ | if (absolute) | |
218 | ✗ | jacobian.topRows<3>().setZero(); | |
219 | else { | ||
220 | ✗ | tmpJac_.noalias() = | |
221 | ✗ | R2.transpose() * ((-cross1 * R1) * omega(J1) + R1 * trans(J1)); | |
222 | ✗ | jacobian.topRows<3>() = inVel_.rview(tmpJac_); | |
223 | } | ||
224 | } | ||
225 | |||
226 | ✗ | if (hasParent) { | |
227 | const matrix3_t& R2_parent( | ||
228 | ✗ | parentJoint_->currentTransformation().rotation()); | |
229 | ✗ | const JointJacobian_t& J2_parent(parentJoint_->jacobian()); | |
230 | |||
231 | // J = p2RT2 * 0RTp2 * [ p2 | ||
232 | ✗ | tmpJac_.noalias() = (R2.transpose() * R2_parent) * omega(J2_parent); | |
233 | ✗ | if (!absolute) tmpJac_.noalias() -= (R2.transpose() * R1) * omega(J1); | |
234 | ✗ | jacobian.bottomRows<3>() = inVel_.rview(tmpJac_); | |
235 | } else { | ||
236 | ✗ | if (absolute) | |
237 | ✗ | jacobian.bottomRows<3>().setZero(); | |
238 | else { | ||
239 | ✗ | tmpJac_.noalias() = (R2.transpose() * R1) * omega(J1); | |
240 | ✗ | jacobian.bottomRows<3>() = inVel_.rview(tmpJac_); | |
241 | } | ||
242 | } | ||
243 | } | ||
244 | |||
245 | template <class Archive> | ||
246 | ✗ | void RelativeTransformation::serialize(Archive& ar, | |
247 | const unsigned int version) { | ||
248 | (void)version; | ||
249 | ✗ | ar& boost::serialization::make_nvp( | |
250 | ✗ | "base", boost::serialization::base_object<DifferentiableFunction>(*this)); | |
251 | ✗ | ar& BOOST_SERIALIZATION_NVP(robot_); | |
252 | ✗ | internal::serialize_joint(ar, "parentJoint_", parentJoint_); | |
253 | ✗ | internal::serialize_joint(ar, "joint1_", joint1_); | |
254 | ✗ | internal::serialize_joint(ar, "joint2_", joint2_); | |
255 | ✗ | ar& BOOST_SERIALIZATION_NVP(frame1_); | |
256 | ✗ | ar& BOOST_SERIALIZATION_NVP(frame2_); | |
257 | |||
258 | ✗ | ar& BOOST_SERIALIZATION_NVP(inConf_); | |
259 | ✗ | ar& BOOST_SERIALIZATION_NVP(inVel_); | |
260 | ✗ | ar& BOOST_SERIALIZATION_NVP(outConf_); | |
261 | ✗ | ar& BOOST_SERIALIZATION_NVP(outVel_); | |
262 | ✗ | ar& BOOST_SERIALIZATION_NVP(F1inJ1_invF2inJ2_); | |
263 | ✗ | ar& BOOST_SERIALIZATION_NVP(weak_); | |
264 | } | ||
265 | |||
266 | HPP_SERIALIZATION_IMPLEMENT(RelativeTransformation); | ||
267 | } // namespace explicit_ | ||
268 | } // namespace constraints | ||
269 | } // namespace hpp | ||
270 | |||
271 | BOOST_CLASS_EXPORT_IMPLEMENT( | ||
272 | hpp::constraints::explicit_::RelativeTransformation) | ||
273 |