1 |
|
|
// Copyright (c) 2014, LAAS-CNRS |
2 |
|
|
// Authors: Steve Tonneau (steve.tonneau@laas.fr) |
3 |
|
|
// |
4 |
|
|
// This file is part of hpp-rbprm. |
5 |
|
|
// hpp-rbprm is free software: you can redistribute it |
6 |
|
|
// and/or modify it under the terms of the GNU Lesser General Public |
7 |
|
|
// License as published by the Free Software Foundation, either version |
8 |
|
|
// 3 of the License, or (at your option) any later version. |
9 |
|
|
// |
10 |
|
|
// hpp-rbprm is distributed in the hope that it will be |
11 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty |
12 |
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 |
|
|
// General Lesser Public License for more details. You should have |
14 |
|
|
// received a copy of the GNU Lesser General Public License along with |
15 |
|
|
// hpp-rbprm. If not, see <http://www.gnu.org/licenses/>. |
16 |
|
|
|
17 |
|
|
#include <hpp/rbprm/rbprm-state.hh> |
18 |
|
|
|
19 |
|
|
namespace hpp { |
20 |
|
|
namespace rbprm { |
21 |
|
|
|
22 |
|
16 |
State::State(const State& other) |
23 |
|
16 |
: configuration_(other.configuration_), |
24 |
|
16 |
contactOrder_(other.contactOrder_), |
25 |
|
16 |
nbContacts(other.nbContacts), |
26 |
|
16 |
stable(other.stable), |
27 |
✓✗ |
16 |
robustness(other.robustness) { |
28 |
✓✗ |
16 |
contacts_ = (other.contacts_); |
29 |
✓✗ |
16 |
contactNormals_ = (other.contactNormals_); |
30 |
✓✗ |
16 |
contactPositions_ = (other.contactPositions_); |
31 |
✓✗ |
16 |
contactRotation_ = (other.contactRotation_); |
32 |
|
16 |
} |
33 |
|
|
|
34 |
|
235 |
State& State::operator=(const State& other) { |
35 |
✓✗ |
235 |
if (this != &other) // protect against invalid self-assignment |
36 |
|
|
{ |
37 |
|
235 |
contacts_ = other.contacts_; |
38 |
|
235 |
contactNormals_ = other.contactNormals_; |
39 |
|
235 |
contactPositions_ = other.contactPositions_; |
40 |
|
235 |
contactRotation_ = other.contactRotation_; |
41 |
|
235 |
contactOrder_ = other.contactOrder_; |
42 |
|
235 |
nbContacts = other.nbContacts; |
43 |
|
235 |
stable = other.stable; |
44 |
|
235 |
configuration_ = other.configuration_; |
45 |
|
|
} |
46 |
|
|
// by convention, always return *this |
47 |
|
235 |
return *this; |
48 |
|
|
} |
49 |
|
|
|
50 |
|
16 |
bool State::RemoveContact(const std::string& contactId) { |
51 |
✓✗ |
16 |
if (contacts_.erase(contactId)) { |
52 |
✓✗ |
16 |
contactNormals_.erase(contactId); |
53 |
✓✗ |
16 |
contactPositions_.erase(contactId); |
54 |
✓✗ |
16 |
contactRotation_.erase(contactId); |
55 |
✓✗ |
16 |
contactNormals_.erase(contactId); |
56 |
|
16 |
--nbContacts; |
57 |
|
16 |
stable = false; |
58 |
✓✗ |
32 |
std::queue<std::string> newQueue; |
59 |
|
16 |
std::string currentContact; |
60 |
✓✓ |
48 |
while (!contactOrder_.empty()) { |
61 |
✓✗ |
32 |
currentContact = contactOrder_.front(); |
62 |
|
32 |
contactOrder_.pop(); |
63 |
✓✓ |
32 |
if (contactId != currentContact) { |
64 |
✓✗ |
16 |
newQueue.push(currentContact); |
65 |
|
|
} |
66 |
|
|
} |
67 |
✓✗ |
16 |
contactOrder_ = newQueue; |
68 |
|
16 |
return true; |
69 |
|
|
} |
70 |
|
|
return false; |
71 |
|
|
} |
72 |
|
|
|
73 |
|
|
std::string State::RemoveFirstContact() { |
74 |
|
|
if (contactOrder_.empty()) return ""; |
75 |
|
|
std::string contactId = contactOrder_.front(); |
76 |
|
|
contactOrder_.pop(); |
77 |
|
|
contacts_.erase(contactId); |
78 |
|
|
contactNormals_.erase(contactId); |
79 |
|
|
contactPositions_.erase(contactId); |
80 |
|
|
contactRotation_.erase(contactId); |
81 |
|
|
contactNormals_.erase(contactId); |
82 |
|
|
stable = false; |
83 |
|
|
--nbContacts; |
84 |
|
|
return contactId; |
85 |
|
|
} |
86 |
|
|
|
87 |
|
268 |
void State::contactCreations(const State& previous, |
88 |
|
|
std::vector<std::string>& outList) const { |
89 |
|
944 |
for (std::map<std::string, fcl::Vec3f>::const_iterator cit = |
90 |
|
268 |
contactPositions_.begin(); |
91 |
✓✓ |
2156 |
cit != contactPositions_.end(); ++cit) { |
92 |
|
944 |
const std::string& name = cit->first; |
93 |
|
944 |
bool newContact(true); |
94 |
✓✗ |
944 |
if (previous.contactPositions_.find(name) != |
95 |
✓✗ |
1888 |
previous.contactPositions_.end()) { |
96 |
|
944 |
newContact = |
97 |
✓✗✓✗ ✓✗ |
944 |
(previous.contactPositions_.at(name) - cit->second).norm() > 0.01; |
98 |
|
|
} |
99 |
✓✓✓✓
|
1008 |
if (newContact && |
100 |
✓✗✓✓
|
1008 |
std::find(outList.begin(), outList.end(), name) == outList.end()) { |
101 |
✓✗ |
48 |
outList.push_back(name); |
102 |
|
|
} |
103 |
|
|
} |
104 |
|
268 |
} |
105 |
|
|
|
106 |
|
134 |
void State::contactBreaks(const State& previous, |
107 |
|
|
std::vector<std::string>& outList) const { |
108 |
|
134 |
previous.contactCreations(*this, outList); |
109 |
|
134 |
} |
110 |
|
|
|
111 |
|
|
std::vector<std::string> State::contactBreaks(const State& previous) const { |
112 |
|
|
std::vector<std::string> res; |
113 |
|
|
contactBreaks(previous, res); |
114 |
|
|
return res; |
115 |
|
|
} |
116 |
|
|
|
117 |
|
|
std::vector<std::string> State::contactCreations(const State& previous) const { |
118 |
|
|
std::vector<std::string> res; |
119 |
|
|
contactCreations(previous, res); |
120 |
|
|
return res; |
121 |
|
|
} |
122 |
|
|
|
123 |
|
|
namespace { |
124 |
|
|
// Given known contact variations, computes all effector that were not in |
125 |
|
|
// contacts |
126 |
|
|
std::vector<std::string> freeLimbMotions( |
127 |
|
|
const std::vector<std::string>& allEffectors, |
128 |
|
|
const std::vector<std::string>& contactVariations, const State& current) { |
129 |
|
|
std::vector<std::string> res; |
130 |
|
|
for (std::vector<std::string>::const_iterator cit = allEffectors.begin(); |
131 |
|
|
cit != allEffectors.end(); ++cit) { |
132 |
|
|
if (std::find(contactVariations.begin(), contactVariations.end(), *cit) == |
133 |
|
|
contactVariations.end() && |
134 |
|
|
!current.contacts_.at(*cit)) { |
135 |
|
|
res.push_back(*cit); |
136 |
|
|
} |
137 |
|
|
} |
138 |
|
|
return res; |
139 |
|
|
} |
140 |
|
|
} // namespace |
141 |
|
|
|
142 |
|
|
std::vector<std::string> State::freeVariations( |
143 |
|
|
const State& previous, const std::vector<std::string>& allEffectors) const { |
144 |
|
|
return freeLimbMotions(allEffectors, contactVariations(previous), *this); |
145 |
|
|
} |
146 |
|
|
|
147 |
|
118 |
std::vector<std::string> State::contactVariations(const State& previous) const { |
148 |
|
118 |
std::vector<std::string> res; |
149 |
✓✗ |
118 |
contactCreations(previous, res); |
150 |
✓✗ |
118 |
contactBreaks(previous, res); |
151 |
|
118 |
return res; |
152 |
|
|
} |
153 |
|
|
|
154 |
|
102 |
std::vector<std::string> State::fixedContacts(const State& previous) const { |
155 |
|
102 |
std::vector<std::string> res; |
156 |
✓✗ |
204 |
std::vector<std::string> variations = contactVariations(previous); |
157 |
|
408 |
for (std::map<std::string, fcl::Vec3f>::const_iterator cit = |
158 |
|
102 |
contactPositions_.begin(); |
159 |
✓✓ |
918 |
cit != contactPositions_.end(); ++cit) { |
160 |
|
408 |
const std::string& name = cit->first; |
161 |
✓✗ |
408 |
if (std::find(variations.begin(), variations.end(), name) == |
162 |
✓✗ |
816 |
variations.end()) { |
163 |
✓✗ |
408 |
res.push_back(name); |
164 |
|
|
} |
165 |
|
|
} |
166 |
|
204 |
return res; |
167 |
|
|
} |
168 |
|
|
|
169 |
|
|
std::vector<std::string> State::allVariations( |
170 |
|
|
const State& previous, const std::vector<std::string>& allEffectors) const { |
171 |
|
|
std::vector<std::string> res; |
172 |
|
|
std::vector<std::string> fixedContacts = this->fixedContacts(previous); |
173 |
|
|
for (std::vector<std::string>::const_iterator cit = allEffectors.begin(); |
174 |
|
|
cit != allEffectors.end(); ++cit) { |
175 |
|
|
if (std::find(fixedContacts.begin(), fixedContacts.end(), *cit) == |
176 |
|
|
fixedContacts.end()) { |
177 |
|
|
res.push_back(*cit); |
178 |
|
|
} |
179 |
|
|
} |
180 |
|
|
return res; |
181 |
|
|
} |
182 |
|
|
|
183 |
|
|
void State::print() const { |
184 |
|
|
std::cout << " State " << std::endl; |
185 |
|
|
/*std::cout << " \t Configuration " << std::endl; |
186 |
|
|
for(int i = 0; i< configuration_.rows(); ++i) |
187 |
|
|
{ |
188 |
|
|
std::cout << configuration_[i] << " "; |
189 |
|
|
} |
190 |
|
|
std::cout << std::endl;*/ |
191 |
|
|
|
192 |
|
|
std::cout << " \t contacts " << std::endl; |
193 |
|
|
for (std::map<std::string, bool>::const_iterator cit = contacts_.begin(); |
194 |
|
|
cit != contacts_.end(); ++cit) { |
195 |
|
|
std::cout << cit->first << ": " << cit->second << std::endl; |
196 |
|
|
} |
197 |
|
|
|
198 |
|
|
std::cout << "\t stable " << this->stable << std::endl; |
199 |
|
|
std::cout << "\t robustness " << this->robustness << std::endl; |
200 |
|
|
|
201 |
|
|
/*std::cout << " \t positions " << std::endl; |
202 |
|
|
for(std::map<std::string, fcl::Vec3f>::const_iterator cit = |
203 |
|
|
contactPositions_.begin(); cit != contactPositions_.end(); ++cit) |
204 |
|
|
{ |
205 |
|
|
std::cout << cit->first << ": " << cit->second << std::endl; |
206 |
|
|
}*/ |
207 |
|
|
/*std::cout << " \t contactNormals_ " << std::endl; |
208 |
|
|
for(std::map<std::string, fcl::Vec3f>::const_iterator cit = |
209 |
|
|
contactNormals_.begin(); cit != contactNormals_.end(); ++cit) |
210 |
|
|
{ |
211 |
|
|
std::cout << cit->first << ": " << cit->second << std::endl; |
212 |
|
|
} |
213 |
|
|
std::cout << std::endl;*/ |
214 |
|
|
} |
215 |
|
|
|
216 |
|
|
void State::printInternal(std::stringstream& ss) const { |
217 |
|
|
std::map<std::string, fcl::Vec3f>::const_iterator cit = |
218 |
|
|
contactNormals_.begin(); |
219 |
|
|
for (unsigned int c = 0; c < nbContacts; ++c, ++cit) { |
220 |
|
|
const std::string& name = cit->first; |
221 |
|
|
const fcl::Vec3f& position = contactPositions_.at(name); |
222 |
|
|
const fcl::Matrix3f& rotation = contactRotation_.at(name); |
223 |
|
|
ss << name.substr(1); |
224 |
|
|
for (std::size_t i = 0; i < 3; ++i) { |
225 |
|
|
ss << " " << position[i]; |
226 |
|
|
} |
227 |
|
|
for (std::size_t i = 0; i < 3; ++i) { |
228 |
|
|
for (std::size_t j = 0; j < 3; ++j) { |
229 |
|
|
ss << " " << rotation(i, j); |
230 |
|
|
} |
231 |
|
|
} |
232 |
|
|
ss << "\n"; |
233 |
|
|
} |
234 |
|
|
ss << "configuration "; |
235 |
|
|
for (int i = 0; i < configuration_.rows(); ++i) { |
236 |
|
|
ss << " " << configuration_[i]; |
237 |
|
|
} |
238 |
|
|
ss << "\n \n"; |
239 |
|
|
} |
240 |
|
|
|
241 |
|
|
void State::print(std::stringstream& ss) const { |
242 |
|
|
ss << nbContacts << "\n"; |
243 |
|
|
ss << ""; |
244 |
|
|
std::map<std::string, fcl::Vec3f>::const_iterator cit = |
245 |
|
|
contactNormals_.begin(); |
246 |
|
|
for (unsigned int c = 0; c < nbContacts; ++c, ++cit) { |
247 |
|
|
ss << " " << cit->first << " "; |
248 |
|
|
} |
249 |
|
|
ss << "\n"; |
250 |
|
|
printInternal(ss); |
251 |
|
|
} |
252 |
|
|
|
253 |
|
|
void State::print(std::stringstream& ss, const State& previous) const { |
254 |
|
|
ss << nbContacts << "\n"; |
255 |
|
|
std::vector<std::string> ncontacts; |
256 |
|
|
ss << ""; |
257 |
|
|
for (std::map<std::string, fcl::Vec3f>::const_iterator cit = |
258 |
|
|
contactPositions_.begin(); |
259 |
|
|
cit != contactPositions_.end(); ++cit) { |
260 |
|
|
const std::string& name = cit->first; |
261 |
|
|
bool newContact(true); |
262 |
|
|
if (previous.contactPositions_.find(name) != |
263 |
|
|
previous.contactPositions_.end()) { |
264 |
|
|
newContact = |
265 |
|
|
(previous.contactPositions_.at(name) - cit->second).norm() > 0.01; |
266 |
|
|
} |
267 |
|
|
if (newContact) { |
268 |
|
|
ncontacts.push_back(name); |
269 |
|
|
ss << name.substr(1) << " "; |
270 |
|
|
} |
271 |
|
|
} |
272 |
|
|
ss << "\n"; |
273 |
|
|
/*ss << "broken Contacts: "; |
274 |
|
|
for(std::map<std::string, fcl::Vec3f>::const_iterator cit = |
275 |
|
|
previous.contactPositions_.begin(); cit != previous.contactPositions_.end(); |
276 |
|
|
++cit) |
277 |
|
|
{ |
278 |
|
|
const std::string& name = cit->first; |
279 |
|
|
if(contactPositions_.find(name) == contactPositions_.end()) |
280 |
|
|
{ |
281 |
|
|
ss << name << " "; |
282 |
|
|
} |
283 |
|
|
} |
284 |
|
|
ss << "\n";*/ |
285 |
|
|
printInternal(ss); |
286 |
|
|
/*for(std::vector<std::string>::const_iterator cit = ncontacts.begin(); |
287 |
|
|
cit != ncontacts.end(); ++cit) |
288 |
|
|
{ |
289 |
|
|
const std::string& name = *cit; |
290 |
|
|
const fcl::Vec3f& normal = contactNormals_.at(name); |
291 |
|
|
const fcl::Vec3f& position = contactPositions_.at(name); |
292 |
|
|
ss << " " << name <<": "; |
293 |
|
|
for(std::size_t i=0; i<3; ++i) |
294 |
|
|
{ |
295 |
|
|
ss << " " << position[i]; |
296 |
|
|
} |
297 |
|
|
for(std::size_t i=0; i<3; ++i) |
298 |
|
|
{ |
299 |
|
|
ss << " " << normal[i]; |
300 |
|
|
} |
301 |
|
|
ss << "\n"; |
302 |
|
|
} |
303 |
|
|
for(int i=0; i<configuration_.rows(); ++i) |
304 |
|
|
{ |
305 |
|
|
ss << " " << configuration_[i]; |
306 |
|
|
} |
307 |
|
|
ss << "\n \n";*/ |
308 |
|
|
} |
309 |
|
|
|
310 |
|
|
pinocchio::value_type effectorDistance(const State& from, const State& to) { |
311 |
|
|
std::vector<std::string> variations = to.contactCreations(from); |
312 |
|
|
pinocchio::value_type norm = 0.; |
313 |
|
|
for (std::vector<std::string>::const_iterator cit = variations.begin(); |
314 |
|
|
cit != variations.end(); ++cit) { |
315 |
|
|
std::string name = *cit; |
316 |
|
|
if (from.contactPositions_.find(name) != from.contactPositions_.end()) { |
317 |
|
|
norm = std::max(norm, (from.contactPositions_.at(name) - |
318 |
|
|
to.contactPositions_.at(name)) |
319 |
|
|
.norm()); |
320 |
|
|
} |
321 |
|
|
} |
322 |
|
|
return norm; |
323 |
|
|
} |
324 |
|
|
|
325 |
|
|
} // namespace rbprm |
326 |
|
|
} // namespace hpp |