Directory: | ./ |
---|---|
File: | src/explicit/convex-shape-contact.cc |
Date: | 2025-05-05 12:19:30 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 64 | 104 | 61.5% |
Branches: | 72 | 262 | 27.5% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2020, Airbus SAS and CNRS | ||
2 | // Authors: Florent Lamiraux | ||
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 <hpp/constraints/affine-function.hh> | ||
30 | #include <hpp/constraints/convex-shape-contact.hh> | ||
31 | #include <hpp/constraints/explicit/convex-shape-contact.hh> | ||
32 | #include <hpp/constraints/explicit/relative-pose.hh> | ||
33 | #include <hpp/pinocchio/liegroup-space.hh> | ||
34 | |||
35 | #include "../src/explicit/input-configurations.hh" | ||
36 | |||
37 | namespace hpp { | ||
38 | namespace constraints { | ||
39 | namespace explicit_ { | ||
40 | // Check that object contact surface | ||
41 | // - belong to the same object (joint), | ||
42 | // - are on a freeflyer joint. | ||
43 | // Throw in case these assertions are not true | ||
44 | 1 | static void checkContactSurfaces(const JointAndShapes_t& objectSurfaces) { | |
45 | 1 | JointPtr_t joint(0x0); | |
46 |
3/4✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
|
3 | for (auto js : objectSurfaces) { |
47 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
|
2 | if (!joint) { |
48 | 1 | joint = js.first; | |
49 | // Check that joint is a freeflyer | ||
50 |
6/16✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
|
2 | if ((*joint->configurationSpace() != *pinocchio::LiegroupSpace::SE3()) && |
51 |
1/10✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
1 | (*joint->configurationSpace() != |
52 |
2/8✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
1 | *pinocchio::LiegroupSpace::R3xSO3())) { |
53 | ✗ | std::ostringstream os; | |
54 | os << "You are trying to build an explicit contact constraint but" | ||
55 | " the joint that holds at least on object contact surface is " | ||
56 | " not a freeflyer joint: " | ||
57 | ✗ | << joint->name(); | |
58 | ✗ | throw std::logic_error(os.str().c_str()); | |
59 | if (joint->parentJoint()) { | ||
60 | os << "You are trying to build an explicit contact constraint " | ||
61 | "but the joint that holds at least on object contact " | ||
62 | "surface: " | ||
63 | << joint->name() | ||
64 | << " is attached to another joint. This is not supported"; | ||
65 | throw std::logic_error(os.str().c_str()); | ||
66 | } | ||
67 | } | ||
68 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
1 | } else if (*(js.first) != *joint) { |
69 | ✗ | std::ostringstream os; | |
70 | os << "You are trying to build an explicit contact constraint " | ||
71 | "but several joints hold object contact surface: " | ||
72 | ✗ | << joint->name() << " and " << js.first->name(); | |
73 | ✗ | throw std::logic_error(os.str().c_str()); | |
74 | } | ||
75 | 2 | } | |
76 | 1 | } | |
77 | |||
78 | 1 | ConvexShapeContactPtr_t ConvexShapeContact::create( | |
79 | const std::string& name, DevicePtr_t robot, | ||
80 | const JointAndShapes_t& floorSurfaces, | ||
81 | const JointAndShapes_t& objectSurfaces, const value_type& margin) { | ||
82 | 1 | checkContactSurfaces(objectSurfaces); | |
83 | ConvexShapeContact* ptr(new ConvexShapeContact(name, robot, floorSurfaces, | ||
84 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | objectSurfaces, margin)); |
85 | 1 | ConvexShapeContactPtr_t shPtr(ptr); | |
86 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ptr->init(shPtr); |
87 | 1 | return shPtr; | |
88 | } | ||
89 | |||
90 | ConvexShapeContact::Constraints_t | ||
91 | ✗ | ConvexShapeContact::createConstraintAndComplement( | |
92 | const std::string& name, DevicePtr_t robot, | ||
93 | const JointAndShapes_t& floorSurfaces, | ||
94 | const JointAndShapes_t& objectSurfaces, const value_type& margin) { | ||
95 | ✗ | Constraints_t result; | |
96 | std::pair<hpp::constraints::ConvexShapeContactPtr_t, | ||
97 | hpp::constraints::ConvexShapeContactComplementPtr_t> | ||
98 | functions(ConvexShapeContactComplement::createPair( | ||
99 | ✗ | name, robot, floorSurfaces, objectSurfaces)); | |
100 | ✗ | functions.first->setNormalMargin(margin); | |
101 | // Contact constraint (= 0) | ||
102 | ✗ | std::get<0>(result) = Implicit::create(functions.first, 5 * EqualToZero); | |
103 | // Contact constraint complement (= rhs) | ||
104 | ✗ | std::get<1>(result) = Implicit::create( | |
105 | functions.second, | ||
106 | ✗ | ComparisonTypes_t(functions.second->outputSize(), constraints::Equality)); | |
107 | ✗ | std::get<2>(result) = | |
108 | ✗ | create(name + "/hold", robot, floorSurfaces, objectSurfaces, margin); | |
109 | ✗ | return result; | |
110 | } | ||
111 | |||
112 | ✗ | ConvexShapeContactPtr_t ConvexShapeContact::createCopy( | |
113 | const ConvexShapeContactPtr_t& other) { | ||
114 | ✗ | ConvexShapeContact* ptr(new ConvexShapeContact(*other)); | |
115 | ✗ | ConvexShapeContactPtr_t shPtr(ptr); | |
116 | ✗ | ConvexShapeContactWkPtr_t wkPtr(shPtr); | |
117 | ✗ | ptr->init(wkPtr); | |
118 | ✗ | return shPtr; | |
119 | } | ||
120 | |||
121 | ✗ | ImplicitPtr_t ConvexShapeContact::copy() const { | |
122 | ✗ | return createCopy(weak_.lock()); | |
123 | } | ||
124 | |||
125 | 400 | void ConvexShapeContact::outputValue(LiegroupElementRef result, vectorIn_t qin, | |
126 | LiegroupElementConstRef rhs) const { | ||
127 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 400 times.
|
400 | assert(HPP_DYNAMIC_PTR_CAST(ConvexShapeContactHold, functionPtr())); |
128 | ConvexShapeContactHoldPtr_t f( | ||
129 | 400 | HPP_STATIC_PTR_CAST(ConvexShapeContactHold, functionPtr())); | |
130 | std::size_t ifloor, iobject; | ||
131 |
2/4✓ Branch 1 taken 400 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 400 times.
✗ Branch 5 not taken.
|
400 | LiegroupElement relativePoseRhs(LiegroupSpace::R3xSO3()); |
132 |
3/6✓ Branch 4 taken 400 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 400 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 400 times.
✗ Branch 11 not taken.
|
400 | f->complement()->computeRelativePoseRightHandSide(rhs, ifloor, iobject, |
133 | relativePoseRhs); | ||
134 | // Extract input configuration of relative pose from qin | ||
135 |
1/2✓ Branch 2 taken 400 times.
✗ Branch 3 not taken.
|
400 | Eigen::RowBlockIndices inputIndices(inputConf()); |
136 |
1/2✓ Branch 3 taken 400 times.
✗ Branch 4 not taken.
|
400 | vector_t q(f->inputSize()); |
137 |
1/2✓ Branch 2 taken 400 times.
✗ Branch 3 not taken.
|
400 | q.fill(sqrt(-1)); |
138 |
2/4✓ Branch 1 taken 400 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 400 times.
✗ Branch 5 not taken.
|
400 | inputIndices.lview(q) = qin; |
139 | 400 | RelativePosePtr_t relativePose(pose_[ifloor * nObjSurf_ + iobject]); | |
140 |
1/2✓ Branch 3 taken 400 times.
✗ Branch 4 not taken.
|
400 | Eigen::RowBlockIndices relPosInputIndices(relativePose->inputConf()); |
141 |
2/4✓ Branch 1 taken 400 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 400 times.
✗ Branch 5 not taken.
|
400 | vector_t qinRelPose = relPosInputIndices.rview(q); |
142 |
2/4✓ Branch 1 taken 400 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 400 times.
|
400 | assert(!qinRelPose.hasNaN()); |
143 |
4/8✓ Branch 2 taken 400 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 400 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 400 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 400 times.
✗ Branch 12 not taken.
|
400 | relativePose->outputValue(result, qinRelPose, relativePoseRhs); |
144 | 400 | } | |
145 | |||
146 | ✗ | void ConvexShapeContact::jacobianOutputValue(vectorIn_t qin, | |
147 | LiegroupElementConstRef, | ||
148 | LiegroupElementConstRef rhs, | ||
149 | matrixOut_t jacobian) const { | ||
150 | ✗ | assert(HPP_DYNAMIC_PTR_CAST(ConvexShapeContactHold, functionPtr())); | |
151 | ConvexShapeContactHoldPtr_t f( | ||
152 | ✗ | HPP_STATIC_PTR_CAST(ConvexShapeContactHold, functionPtr())); | |
153 | std::size_t ifloor, iobject; | ||
154 | ✗ | LiegroupElement relativePoseRhs(LiegroupSpace::R3xSO3()); | |
155 | ✗ | f->complement()->computeRelativePoseRightHandSide(rhs, ifloor, iobject, | |
156 | relativePoseRhs); | ||
157 | // Extract input configuration of relative pose from qin | ||
158 | ✗ | Eigen::RowBlockIndices inputIndices(inputConf()); | |
159 | ✗ | vector_t q(f->inputSize()); | |
160 | ✗ | q.fill(sqrt(-1)); | |
161 | ✗ | inputIndices.lview(q) = qin; | |
162 | ✗ | RelativePosePtr_t relativePose(pose_[ifloor * nObjSurf_ + iobject]); | |
163 | ✗ | Eigen::RowBlockIndices relPosInputIndices(relativePose->inputConf()); | |
164 | ✗ | vector_t qinRelPose = relPosInputIndices.rview(q); | |
165 | ✗ | assert(!qinRelPose.hasNaN()); | |
166 | ✗ | LiegroupElement outputRelPose(LiegroupSpace::R3xSO3()); | |
167 | ✗ | relativePose->outputValue(outputRelPose, qinRelPose, relativePoseRhs); | |
168 | ✗ | relativePose->jacobianOutputValue(qinRelPose, outputRelPose, relativePoseRhs, | |
169 | jacobian); | ||
170 | } | ||
171 | |||
172 | 1 | ConvexShapeContact::ConvexShapeContact(const std::string& name, | |
173 | DevicePtr_t robot, | ||
174 | const JointAndShapes_t& floorSurfaces, | ||
175 | const JointAndShapes_t& objectSurfaces, | ||
176 | 1 | const value_type& margin) | |
177 | : Explicit( | ||
178 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | ConvexShapeContactHold::create(name, robot, floorSurfaces, |
179 | objectSurfaces), | ||
180 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | ConstantFunction::create( |
181 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | pinocchio::LiegroupSpace::SE3()->neutral(), |
182 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | contact::inputSize(robot, floorSurfaces, objectSurfaces), |
183 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | contact::inputDerivSize(robot, floorSurfaces, objectSurfaces), |
184 | name), | ||
185 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | contact::inputConfVariables(robot, floorSurfaces, objectSurfaces), |
186 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | relativePose::jointConfInterval(objectSurfaces.front().first), |
187 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | contact::inputVelocityVariables(robot, floorSurfaces, objectSurfaces), |
188 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | relativePose::jointVelInterval(objectSurfaces.front().first), |
189 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
|
5 | (5 * EqualToZero << 3 * Equality), std::vector<bool>(8, true)) { |
190 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
1 | assert(HPP_DYNAMIC_PTR_CAST(ConvexShapeContactHold, functionPtr())); |
191 | ConvexShapeContactHoldPtr_t f( | ||
192 | 1 | HPP_STATIC_PTR_CAST(ConvexShapeContactHold, functionPtr())); | |
193 |
1/2✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | f->contactConstraint()->setNormalMargin(margin); |
194 | 1 | const ConvexShapes_t& fs(f->contactConstraint()->floorContactSurfaces()); | |
195 | 1 | const ConvexShapes_t& os(f->contactConstraint()->objectContactSurfaces()); | |
196 | 1 | nObjSurf_ = os.size(); | |
197 | // Compute explicit relative poses | ||
198 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | for (std::size_t ifloor = 0; ifloor < fs.size(); ++ifloor) { |
199 | // move floor surface along x to take into account margin. | ||
200 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | Transform3s posInJoint(fs[ifloor].positionInJoint()); |
201 | hppDout(info, "posInJoint" << posInJoint); | ||
202 |
5/10✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
|
2 | posInJoint.translation() -= margin * posInJoint.rotation().col(0); |
203 | hppDout(info, "posInJoint" << posInJoint); | ||
204 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
|
6 | for (std::size_t iobject = 0; iobject < os.size(); ++iobject) { |
205 | // Create explicit relative pose for each combination | ||
206 | // (floor surface, object surface) | ||
207 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | pose_.push_back( |
208 |
2/4✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
|
8 | RelativePose::create("", robot, fs[ifloor].joint_, os[iobject].joint_, |
209 | 4 | posInJoint, os[iobject].positionInJoint(), | |
210 |
2/4✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
8 | EqualToZero << 3 * Equality << 2 * EqualToZero, |
211 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
8 | std::vector<bool>(6, true))); |
212 | } | ||
213 | } | ||
214 | 1 | } | |
215 | 1 | void ConvexShapeContact::init(ConvexShapeContactWkPtr_t weak) { | |
216 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | Explicit::init(weak); |
217 | 1 | weak_ = weak; | |
218 | 1 | } | |
219 | } // namespace explicit_ | ||
220 | } // namespace constraints | ||
221 | } // namespace hpp | ||
222 |