GCC Code Coverage Report


Directory: ./
File: src/center-of-mass-computation.cc
Date: 2025-05-04 12:09:19
Exec Total Coverage
Lines: 0 67 0.0%
Branches: 0 126 0.0%

Line Branch Exec Source
1 // Copyright (c) 2016, LAAS-CNRS
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 "hpp/pinocchio/center-of-mass-computation.hh"
30
31 #include <algorithm>
32 #include <boost/foreach.hpp>
33 #include <boost/serialization/vector.hpp>
34 #include <hpp/pinocchio/joint-collection.hh>
35 #include <hpp/util/exception-factory.hh>
36 #include <hpp/util/serialization.hh>
37 #include <pinocchio/algorithm/center-of-mass.hpp>
38 #include <pinocchio/algorithm/copy.hpp>
39
40 #include "hpp/pinocchio/device.hh"
41 #include "hpp/pinocchio/joint.hh"
42 #include "hpp/pinocchio/serialization.hh"
43
44 namespace hpp {
45 namespace pinocchio {
46 CenterOfMassComputationPtr_t CenterOfMassComputation::create(
47 const DevicePtr_t& d) {
48 return CenterOfMassComputationPtr_t(new CenterOfMassComputation(d));
49 }
50
51 void CenterOfMassComputation::compute(DeviceData& d,
52 const Computation_t& flag) {
53 const Model& model = robot_->model();
54
55 bool computeCOM = (flag & COM);
56 bool computeJac = (flag & JACOBIAN);
57 assert(computeCOM && "This does nothing");
58 assert(!(computeJac && !computeCOM)); // JACOBIAN => COM
59
60 Data& data = *d.data_;
61
62 data.mass[0] = 0;
63 if (computeCOM) data.com[0].setZero();
64 if (computeJac) data.Jcom.setZero();
65
66 // Propagate COM initialization on all joints.
67 // Could be done only on subtree, with minor gain (possibly loss because of
68 // more difficult branch prediction). I dont recommend to implement it.
69 for (JointIndex jid = 1; jid < JointIndex(model.joints.size()); ++jid) {
70 const double& mass = model.inertias[jid].mass();
71 data.mass[jid] = mass;
72 data.com[jid] = mass * data.oMi[jid].act(model.inertias[jid].lever());
73 }
74
75 // Nullify non-subtree com and mass.
76 std::size_t root = 0;
77 std::size_t rootId = roots_[root];
78 for (std::size_t jid = 1; jid < model.joints.size(); ++jid) {
79 if (jid == rootId) {
80 jid = (std::size_t)data.lastChild[rootId];
81 root++;
82 if (root < roots_.size())
83 rootId = roots_[root];
84 else
85 // After last root, make sure that all joints set to 0.
86 rootId = model.joints.size();
87 } else {
88 data.mass[jid] = 0;
89 data.com[jid].setZero();
90 }
91 }
92
93 // TODO as of now, it is not possible to access the template parameter
94 // JointCollectionTpl of Model so we use the default one.
95 typedef ::pinocchio::JacobianCenterOfMassBackwardStep<
96 Model::Scalar, Model::Options, JointCollectionTpl
97 #if PINOCCHIO_VERSION_AT_LEAST(2, 1, 6)
98 ,
99 Data::Matrix3x
100 #endif
101 >
102 Pass;
103
104 // Assume root is sorted from smallest id.
105 // Nasty cast below, from (u-long) size_t to int.
106 for (int root = int(roots_.size() - 1); root >= 0; --root) {
107 std::size_t rootId = roots_[(std::size_t)root];
108
109 // Backward loop on descendents of joint rootId.
110 for (JointIndex jid = (JointIndex)data.lastChild[rootId]; jid >= rootId;
111 --jid) {
112 if (computeJac)
113 Pass::run(model.joints[jid], data.joints[jid],
114 Pass::ArgsType(model, data,
115 #if PINOCCHIO_VERSION_AT_LEAST(2, 1, 6)
116 data.Jcom,
117 #endif
118 false));
119 else {
120 assert(computeCOM);
121 const JointIndex& parent = model.parents[jid];
122 data.com[parent] += data.com[jid];
123 data.mass[parent] += data.mass[jid];
124 }
125
126 // std::cout << data.oMi [jid] << std::endl;
127 // std::cout << data.mass[jid] << std::endl;
128 // std::cout << data.com [jid].transpose() << std::endl;
129 } // end for jid
130
131 // Backward loop on ancestors of joint rootId
132 JointIndex jid = model.parents[rootId]; // loop variable
133 rootId = (root > 0) ? roots_[(std::size_t)(root - 1)]
134 : 0; // root of previous subtree in roots_
135 while (jid > rootId) // stop when meeting the next subtree
136 {
137 const JointIndex& parent = model.parents[jid];
138 if (computeJac)
139 Pass::run(model.joints[jid], data.joints[jid],
140 Pass::ArgsType(model, data,
141 #if PINOCCHIO_VERSION_AT_LEAST(2, 1, 6)
142 data.Jcom,
143 #endif
144 false));
145 else {
146 assert(computeCOM);
147 data.com[parent] += data.com[jid];
148 data.mass[parent] += data.mass[jid];
149 }
150 jid = parent;
151 } // end while
152
153 } // end for root in roots_
154
155 if (computeCOM) data.com[0] /= data.mass[0];
156 if (computeJac) data.Jcom /= data.mass[0];
157 }
158
159 CenterOfMassComputation::CenterOfMassComputation(const DevicePtr_t& d)
160 : robot_(d), roots_() {
161 assert(d->modelPtr());
162 }
163
164 void CenterOfMassComputation::add(const JointPtr_t& j) {
165 const Data& data = robot_->data();
166 JointIndex jid = j->index();
167 BOOST_FOREACH (const JointIndex rootId, roots_) {
168 assert(std::size_t(rootId) < robot_->model().joints.size());
169 // Assert that the new root is not in already-recorded subtrees.
170 if ((jid >= rootId) && (data.lastChild[rootId] >= int(jid)))
171 // We are doing something stupid. Should we throw an error
172 // or just return silently ?
173 HPP_THROW(std::invalid_argument,
174 "Joint " << j->name() << " (" << jid
175 << ") is already in a subtree [" << rootId << ", "
176 << data.lastChild[rootId] << "]");
177 }
178
179 roots_.push_back(jid);
180 }
181
182 CenterOfMassComputation::~CenterOfMassComputation() {}
183
184 template <class Archive>
185 void CenterOfMassComputation::serialize(Archive& ar,
186 const unsigned int version) {
187 (void)version;
188 ar& BOOST_SERIALIZATION_NVP(robot_);
189 ar& BOOST_SERIALIZATION_NVP(roots_);
190 }
191
192 HPP_SERIALIZATION_IMPLEMENT(CenterOfMassComputation);
193 } // namespace pinocchio
194 } // namespace hpp
195