| 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 |