GCC Code Coverage Report


Directory: src/
File: src/graph.impl.cc
Date: 2024-12-13 15:43:02
Exec Total Coverage
Lines: 0 602 0.0%
Branches: 0 1438 0.0%

Line Branch Exec Source
1 // Copyright (c) 2014, 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 "graph.impl.hh"
30
31 #include <fstream>
32 #include <hpp/constraints/differentiable-function.hh>
33 #include <hpp/corbaserver/conversions.hh>
34 #include <hpp/corbaserver/manipulation/server.hh>
35 #include <hpp/manipulation/connected-component.hh>
36 #include <hpp/manipulation/constraint-set.hh>
37 #include <hpp/manipulation/graph/edge.hh>
38 #include <hpp/manipulation/graph/graph.hh>
39 #include <hpp/manipulation/graph/guided-state-selector.hh>
40 #include <hpp/manipulation/graph/helper.hh>
41 #include <hpp/manipulation/graph/state-selector.hh>
42 #include <hpp/manipulation/graph/state.hh>
43 #include <hpp/manipulation/manipulation-planner.hh>
44 #include <hpp/manipulation/problem.hh>
45 #include <hpp/manipulation/roadmap.hh>
46 #include <hpp/manipulation/steering-method/graph.hh>
47 #include <hpp/util/debug.hh>
48 #include <hpp/util/exception-factory.hh>
49 #include <hpp/util/pointer.hh>
50 #include <pinocchio/multibody/model.hpp>
51 #include <sstream>
52
53 #include "tools.hh"
54
55 namespace hpp {
56 namespace manipulation {
57 using constraints::Implicit;
58 namespace impl {
59 using CORBA::ULong;
60 using corbaServer::floatSeqToConfig;
61 using graph::Edge;
62 using graph::EdgePtr_t;
63 using graph::LevelSetEdge;
64 using graph::LevelSetEdgePtr_t;
65 using graph::WaypointEdge;
66 using graph::WaypointEdgePtr_t;
67
68 namespace {
69 typedef core::ProblemSolver CPs_t;
70
71 template <typename T>
72 std::string toStr() {
73 return typeid(T).name();
74 }
75 template <>
76 std::string toStr<graph::State>() {
77 return "Node";
78 }
79 template <>
80 std::string toStr<graph::Edge>() {
81 return "Edge";
82 }
83 template <>
84 std::string toStr<graph::Graph>() {
85 return "Graph";
86 }
87 template <>
88 std::string toStr<graph::LevelSetEdge>() {
89 return "LevelSetEdge";
90 }
91 template <>
92 std::string toStr<graph::WaypointEdge>() {
93 return "WaypointEdge";
94 }
95
96 std::vector<graph::helper::ObjectDef_t> toObjectVector(const Names_t& names,
97 const Namess_t& hsPO,
98 const Namess_t& shPO) {
99 using graph::helper::ObjectDef_t;
100 std::vector<graph::helper::ObjectDef_t> ret;
101 // Check size of lists
102 if (hsPO.length() != names.length()) {
103 HPP_THROW(Error, "Number of handle lists ("
104 << hsPO.length()
105 << ") does not match number of objects ("
106 << names.length() << ").");
107 }
108 if (shPO.length() != names.length()) {
109 HPP_THROW(Error, "Number of contact lists ("
110 << shPO.length()
111 << ") does not match number of objects ("
112 << names.length() << ").");
113 }
114 for (ULong i = 0; i < names.length(); ++i) {
115 ret.push_back(ObjectDef_t());
116 ObjectDef_t& od = ret.back();
117 od.name = names[i];
118 od.handles = corbaServer::toStrings<std::vector<std::string> >(hsPO[i]);
119 od.shapes = corbaServer::toStrings<std::vector<std::string> >(shPO[i]);
120 }
121 return ret;
122 }
123
124 void setRule(const hpp::corbaserver::manipulation::Rule& in,
125 graph::helper::Rule& out) {
126 out.grippers_ = toStringVector(in.grippers);
127 out.handles_ = toStringVector(in.handles);
128 out.link_ = in.link;
129 }
130 } // namespace
131
132 Graph::Graph() : server_(0x0) {}
133
134 ProblemSolverPtr_t Graph::problemSolver() { return server_->problemSolver(); }
135
136 graph::GraphPtr_t Graph::graph(bool throwIfNull) {
137 graph::GraphPtr_t g = problemSolver()->constraintGraph();
138 if (throwIfNull && !g) throw Error("You should create the graph");
139 return g;
140 }
141
142 template <typename T>
143 shared_ptr<T> Graph::getComp(ID id, bool throwIfWrongType) {
144 shared_ptr<T> comp;
145 try {
146 comp = HPP_DYNAMIC_PTR_CAST(T, graph()->get(id).lock());
147 } catch (std::out_of_range& e) {
148 throw Error(e.what());
149 }
150 if (throwIfWrongType && !comp) {
151 std::stringstream ss;
152 ss << "ID " << id << " is not a " << toStr<T>();
153 throw Error(ss.str().c_str());
154 }
155 return comp;
156 }
157
158 Long Graph::createGraph(const char* graphName) {
159 try {
160 std::string name(graphName);
161 if (problemSolver()->graphs.has(name)) {
162 HPP_THROW(Error, "A graph named " << name << " already exists");
163 }
164
165 DevicePtr_t robot = problemSolver()->robot();
166 if (!robot) throw Error("Build the robot first.");
167 // Create default steering method to store in edges, until we define a
168 // factory for steering methods.
169 graph::GraphPtr_t g =
170 graph::Graph::create(name, robot, problemSolver()->problem());
171 g->maxIterations(problemSolver()->maxIterProjection());
172 g->errorThreshold(problemSolver()->errorThreshold());
173
174 problemSolver()->graphs.add(name, g);
175 problemSolver()->constraintGraph(name);
176 return (Long)g->id();
177 } catch (std::exception& e) {
178 throw Error(e.what());
179 }
180 }
181
182 void Graph::deleteGraph(const char* graphName) {
183 try {
184 std::string name(graphName);
185 if (!problemSolver()->graphs.has(name)) {
186 HPP_THROW(Error, "There is no graph named " << name << ".");
187 }
188 problemSolver()->graphs.erase(name);
189 } catch (std::exception& e) {
190 throw Error(e.what());
191 }
192 }
193
194 void Graph::selectGraph(const char* graphName) {
195 try {
196 problemSolver()->constraintGraph(graphName);
197 } catch (const std::exception& e) {
198 throw Error(e.what());
199 }
200 }
201
202 void Graph::createSubGraph(const char* subgraphName) {
203 try {
204 graph::GuidedStateSelectorPtr_t ns = graph::GuidedStateSelector::create(
205 subgraphName, problemSolver()->roadmap());
206 graph()->stateSelector(ns);
207 } catch (const std::exception& exc) {
208 throw(Error(exc.what()));
209 }
210 }
211
212 void Graph::setTargetNodeList(const ID graphId, const hpp::IDseq& nodes) {
213 graph::GraphPtr_t graph = getComp<graph::Graph>(graphId);
214 graph::GuidedStateSelectorPtr_t ns =
215 HPP_DYNAMIC_PTR_CAST(graph::GuidedStateSelector, graph->stateSelector());
216 if (!ns)
217 throw Error("The state selector is not of type GuidedStateSelector.");
218 try {
219 graph::States_t nl;
220 for (unsigned int i = 0; i < nodes.length(); ++i)
221 nl.push_back(getComp<graph::State>(nodes[i]));
222 ns->setStateList(nl);
223 } catch (std::out_of_range& e) {
224 throw Error(e.what());
225 }
226 }
227
228 Long Graph::createNode(const Long graphId, const char* nodeName,
229 const bool waypoint, const Long priority) {
230 graph::GraphPtr_t graph = getComp<graph::Graph>(graphId);
231 if (graph->stateSelector()) {
232 graph::StatePtr_t state =
233 graph->stateSelector()->createState(nodeName, waypoint, priority);
234 return (Long)state->id();
235 } else {
236 throw Error("Graph has no state selector.");
237 }
238 }
239
240 Long Graph::createEdge(const Long nodeFromId, const Long nodeToId,
241 const char* edgeName, const Long w,
242 const Long isInNodeId) {
243 graph::StatePtr_t from = getComp<graph::State>(nodeFromId),
244 to = getComp<graph::State>(nodeToId),
245 isInState = getComp<graph::State>(isInNodeId);
246
247 EdgePtr_t edge = from->linkTo(edgeName, to, (size_type)w,
248 (graph::State::EdgeFactory)Edge::create);
249 edge->state(isInState);
250
251 return (Long)edge->id();
252 }
253
254 Long Graph::createWaypointEdge(const Long nodeFromId, const Long nodeToId,
255 const char* edgeName, const Long nb,
256 const Long w, const Long isInNodeId) {
257 try {
258 graph::StatePtr_t from = getComp<graph::State>(nodeFromId),
259 to = getComp<graph::State>(nodeToId),
260 isInNode = getComp<graph::State>(isInNodeId);
261
262 EdgePtr_t edge_pc =
263 from->linkTo(edgeName, to, (size_type)w,
264 (graph::State::EdgeFactory)WaypointEdge::create);
265
266 edge_pc->state(isInNode);
267 WaypointEdgePtr_t edge = HPP_DYNAMIC_PTR_CAST(WaypointEdge, edge_pc);
268
269 edge->nbWaypoints(nb);
270 return (Long)edge->id();
271 } catch (const std::exception& exc) {
272 throw(Error(exc.what()));
273 }
274 }
275
276 void Graph::setWaypoint(const ID waypointEdgeId, const Long index,
277 const ID edgeId, const ID nodeId) {
278 try {
279 WaypointEdgePtr_t we = getComp<graph::WaypointEdge>(waypointEdgeId);
280 EdgePtr_t edge = getComp<Edge>(edgeId);
281 graph::StatePtr_t state = getComp<graph::State>(nodeId);
282
283 if (index < 0 || (std::size_t)index > we->nbWaypoints())
284 throw Error("Invalid index");
285 we->setWaypoint(index, edge, state);
286 } catch (const std::exception& exc) {
287 throw(Error(exc.what()));
288 }
289 }
290
291 void Graph::getGraph(GraphComp_out graph_out, GraphElements_out elmts) {
292 GraphComps_t comp_n, comp_e;
293 GraphComp comp_g, current;
294
295 graph::StatePtr_t n;
296 graph::EdgePtr_t e;
297
298 ULong len_edges = 0;
299 ULong len_nodes = 0;
300 try {
301 graph::GraphPtr_t g = graph();
302
303 // Set the graph values
304 graph_out = new GraphComp();
305 graph_out->name = g->name().c_str();
306 graph_out->id = (Long)g->id();
307
308 for (std::size_t i = 0; i < g->nbComponents(); ++i) {
309 if (i == g->id()) continue;
310 graph::GraphComponentPtr_t gcomponent = g->get(i).lock();
311 if (!gcomponent) continue;
312 current.name = gcomponent->name().c_str();
313 current.id = (Long)gcomponent->id();
314 n = HPP_DYNAMIC_PTR_CAST(graph::State, gcomponent);
315 e = HPP_DYNAMIC_PTR_CAST(graph::Edge, gcomponent);
316 if (n) {
317 comp_n.length(len_nodes + 1);
318 comp_n[len_nodes] = current;
319 len_nodes++;
320 } else if (e) {
321 comp_e.length(len_edges + 1);
322 graph::WaypointEdgePtr_t we =
323 HPP_DYNAMIC_PTR_CAST(graph::WaypointEdge, e);
324 if (we) {
325 current.waypoints.length((ULong)we->nbWaypoints());
326 for (std::size_t i = 0; i < we->nbWaypoints(); ++i)
327 current.waypoints[(ULong)i] = (ID)we->waypoint(i)->stateTo()->id();
328 } else {
329 current.waypoints.length(0);
330 }
331 current.start = (Long)e->stateFrom()->id();
332 current.end = (Long)e->stateTo()->id();
333 comp_e[len_edges] = current;
334 len_edges++;
335 }
336 }
337 elmts = new GraphElements;
338 elmts->nodes = comp_n;
339 elmts->edges = comp_e;
340 } catch (std::out_of_range& e) {
341 throw Error(e.what());
342 }
343 }
344
345 void Graph::getEdgeStat(ID edgeId, Names_t_out reasons, intSeq_out freqs) {
346 try {
347 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId, true);
348 core::PathPlannerPtr_t p = problemSolver()->pathPlanner();
349 if (!p) throw Error("There is no planner");
350 ManipulationPlannerPtr_t mp = HPP_DYNAMIC_PTR_CAST(ManipulationPlanner, p);
351 if (!mp) throw Error("The planner must be a ManipulationPlanner");
352
353 StringList_t errors = ManipulationPlanner::errorList();
354 ManipulationPlanner::ErrorFreqs_t fes = mp->getEdgeStat(edge);
355
356 Names_t* r_ptr = toNames_t(errors.begin(), errors.end());
357 intSeq* f_ptr = toIntSeq(fes.begin(), fes.end());
358
359 reasons = r_ptr;
360 freqs = f_ptr;
361 } catch (std::out_of_range& e) {
362 throw Error(e.what());
363 }
364 }
365
366 Long Graph::getFrequencyOfNodeInRoadmap(ID nodeId,
367 intSeq_out freqPerConnectedComponent) {
368 try {
369 graph::StatePtr_t state = getComp<graph::State>(nodeId, true);
370 // Long nb = graph_->nodeHistogram()->freq(graph::NodeBin(node));
371 std::size_t nb = 0;
372 const core::ConnectedComponents_t& ccs =
373 problemSolver()->roadmap()->connectedComponents();
374 core::ConnectedComponents_t::const_iterator _cc;
375 std::vector<std::size_t> freqs;
376 for (_cc = ccs.begin(); _cc != ccs.end(); ++_cc) {
377 manipulation::ConnectedComponentPtr_t cc =
378 HPP_DYNAMIC_PTR_CAST(manipulation::ConnectedComponent, *_cc);
379 if (!cc) throw Error("Connected component is not of the right type.");
380 freqs.push_back(cc->getRoadmapNodes(state).size());
381 nb += freqs.back();
382 }
383 freqPerConnectedComponent = toIntSeq(freqs.begin(), freqs.end());
384 return (Long)nb;
385 } catch (std::out_of_range& e) {
386 throw Error(e.what());
387 }
388 }
389
390 bool Graph::getConfigProjectorStats(ID elmt, ConfigProjStat_out config,
391 ConfigProjStat_out path) {
392 try {
393 graph::StatePtr_t state = getComp<graph::State>(elmt, false);
394 graph::EdgePtr_t edge = getComp<graph::Edge>(elmt, false);
395 if (state) {
396 ConfigProjectorPtr_t proj =
397 graph()->configConstraint(state)->configProjector();
398 if (proj) {
399 config.success = (Long)proj->statistics().nbSuccess();
400 config.error = (Long)proj->statistics().nbFailure();
401 config.nbObs = (Long)proj->statistics().numberOfObservations();
402 }
403 path.success = 0;
404 path.error = 0;
405 path.nbObs = 0;
406 return true;
407 } else if (edge) {
408 ConfigProjectorPtr_t proj =
409 graph()->targetConstraint(edge)->configProjector();
410 if (proj) {
411 config.success = (Long)proj->statistics().nbSuccess();
412 config.error = (Long)proj->statistics().nbFailure();
413 config.nbObs = (Long)proj->statistics().numberOfObservations();
414 }
415 proj = graph()->pathConstraint(edge)->configProjector();
416 if (proj) {
417 path.success = (Long)proj->statistics().nbSuccess();
418 path.error = (Long)proj->statistics().nbFailure();
419 path.nbObs = (Long)proj->statistics().numberOfObservations();
420 }
421 return true;
422 } else {
423 throw Error("The ID does not exist.");
424 }
425 return false;
426 } catch (std::out_of_range& e) {
427 throw Error(e.what());
428 }
429 }
430
431 Long Graph::getWaypoint(const Long edgeId, const Long index,
432 hpp::ID_out nodeId) {
433 try {
434 graph::WaypointEdgePtr_t edge = getComp<graph::WaypointEdge>(edgeId);
435
436 if (index < 0 || (std::size_t)index > edge->nbWaypoints())
437 throw Error("Invalid index");
438 graph::EdgePtr_t waypoint = edge->waypoint(index);
439 nodeId = (Long)waypoint->stateTo()->id();
440 return (Long)waypoint->id();
441 } catch (std::out_of_range& e) {
442 throw Error(e.what());
443 }
444 }
445
446 Long Graph::createLevelSetEdge(const Long nodeFromId, const Long nodeToId,
447 const char* edgeName, const Long w,
448 const ID isInNodeId) {
449 try {
450 graph::StatePtr_t from = getComp<graph::State>(nodeFromId),
451 to = getComp<graph::State>(nodeToId),
452 isInState = getComp<graph::State>(isInNodeId);
453
454 graph::EdgePtr_t edge =
455 from->linkTo(edgeName, to, (size_type)w,
456 (graph::State::EdgeFactory)graph::LevelSetEdge::create);
457
458 edge->state(isInState);
459
460 return (Long)edge->id();
461 } catch (std::out_of_range& e) {
462 throw Error(e.what());
463 }
464 }
465
466 void Graph::addLevelSetFoliation(const Long edgeId, const hpp::Names_t& condNC,
467 const hpp::Names_t& paramNC) {
468 try {
469 graph::LevelSetEdgePtr_t edge = getComp<graph::LevelSetEdge>(edgeId);
470 for (CORBA::ULong i = 0; i < condNC.length(); ++i) {
471 std::string name(condNC[i]);
472 edge->insertConditionConstraint(
473 problemSolver()->numericalConstraints.get(name)->copy());
474 }
475 for (CORBA::ULong i = 0; i < paramNC.length(); ++i) {
476 std::string name(paramNC[i]);
477 edge->insertParamConstraint(
478 problemSolver()->numericalConstraints.get(name)->copy());
479 }
480 } catch (std::exception& err) {
481 throw Error(err.what());
482 }
483 }
484
485 void Graph::setContainingNode(const ID edgeId, const ID nodeId) {
486 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
487 graph::StatePtr_t state = getComp<graph::State>(nodeId);
488 try {
489 edge->state(state);
490 } catch (std::exception& err) {
491 throw Error(err.what());
492 }
493 }
494
495 char* Graph::getContainingNode(const ID edgeId) {
496 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
497 try {
498 std::string name(edge->state()->name());
499 char* res = new char[name.size() + 1];
500 strcpy(res, name.c_str());
501 return res;
502 } catch (std::exception& err) {
503 throw Error(err.what());
504 }
505 }
506
507 void Graph::addNumericalConstraints(const Long graphComponentId,
508 const hpp::Names_t& constraintNames) {
509 graph::GraphComponentPtr_t component =
510 getComp<graph::GraphComponent>(graphComponentId, true);
511
512 if (constraintNames.length() > 0) {
513 try {
514 for (CORBA::ULong i = 0; i < constraintNames.length(); ++i) {
515 std::string name(constraintNames[i]);
516 if (!problemSolver()->numericalConstraint(name)) {
517 std::ostringstream os;
518 os << "Numerical constraint \"" << name << "\" does not exist.";
519 throw Error(os.str().c_str());
520 }
521 component->addNumericalConstraint(
522 problemSolver()->numericalConstraint(name));
523 }
524 } catch (std::exception& err) {
525 throw Error(err.what());
526 }
527 }
528 }
529
530 void Graph::getNumericalConstraints(const Long graphComponentId,
531 hpp::Names_t_out names) {
532 graph::GraphComponentPtr_t elmt =
533 getComp<graph::GraphComponent>(graphComponentId);
534 core::NumericalConstraints_t constraints = elmt->numericalConstraints();
535 names = new hpp::Names_t;
536 names->length((ULong)constraints.size());
537 int i = 0;
538 for (core::NumericalConstraints_t::iterator it = constraints.begin();
539 it != constraints.end(); ++it) {
540 (*names)[i] = (*it)->function().name().c_str();
541 i++;
542 }
543 }
544
545 void Graph::resetConstraints(const Long graphComponentId) {
546 graph::GraphComponentPtr_t component =
547 getComp<graph::GraphComponent>(graphComponentId, true);
548 component->resetNumericalConstraints();
549 }
550
551 void Graph::addNumericalConstraintsForPath(
552 const Long nodeId, const hpp::Names_t& constraintNames) {
553 graph::StatePtr_t n = getComp<graph::State>(nodeId);
554
555 if (constraintNames.length() > 0) {
556 try {
557 for (CORBA::ULong i = 0; i < constraintNames.length(); ++i) {
558 std::string name(constraintNames[i]);
559 n->addNumericalConstraintForPath(
560 problemSolver()->numericalConstraint(name)->copy());
561 }
562 } catch (std::exception& err) {
563 throw Error(err.what());
564 }
565 }
566 }
567
568 void Graph::removeCollisionPairFromEdge(ID edgeId, const char* joint1,
569 const char* joint2) {
570 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
571
572 try {
573 using hpp::core::RelativeMotion;
574 RelativeMotion::matrix_type m(edge->relativeMotion());
575 DevicePtr_t robot = getRobotOrThrow(problemSolver());
576 JointIndex i1 = robot->getJointByName(joint1)->index();
577 JointIndex i2 = robot->getJointByName(joint2)->index();
578 m(i1, i2) = m(i2, i1) = RelativeMotion::Constrained;
579 edge->relativeMotion(m);
580 } catch (std::exception& err) {
581 throw Error(err.what());
582 }
583 }
584
585 void Graph::getNode(const hpp::floatSeq& dofArray, ID_out output) {
586 DevicePtr_t robot = getRobotOrThrow(problemSolver());
587 try {
588 Configuration_t config(floatSeqToConfig(robot, dofArray, true));
589 graph::StatePtr_t state = graph()->getState(config);
590 output = (Long)state->id();
591 } catch (std::exception& e) {
592 throw Error(e.what());
593 }
594 }
595
596 bool Graph::applyNodeConstraints(hpp::ID id, const hpp::floatSeq& input,
597 hpp::floatSeq_out output,
598 double& residualError) {
599 /// First get the constraint.
600 ConstraintSetPtr_t constraint;
601 try {
602 graph::GraphComponentPtr_t comp = graph()->get((size_t)id).lock();
603 graph::EdgePtr_t edge = HPP_DYNAMIC_PTR_CAST(graph::Edge, comp);
604 graph::StatePtr_t state = HPP_DYNAMIC_PTR_CAST(graph::State, comp);
605 if (edge) {
606 constraint = graph(false)->targetConstraint(edge);
607 DevicePtr_t robot = getRobotOrThrow(problemSolver());
608 if (core::ConfigProjectorPtr_t cp = constraint->configProjector()) {
609 cp->rightHandSideFromConfig(robot->currentConfiguration());
610 }
611 } else if (state)
612 constraint = graph(false)->configConstraint(state);
613 else {
614 std::stringstream ss;
615 ss << "ID " << id << " is neither an edge nor a state";
616 std::string errmsg = ss.str();
617 throw Error(errmsg.c_str());
618 }
619 bool success = false;
620 DevicePtr_t robot = getRobotOrThrow(problemSolver());
621 Configuration_t config = floatSeqToConfig(robot, input, true);
622 success = constraint->apply(config);
623 if (hpp::core::ConfigProjectorPtr_t configProjector =
624 constraint->configProjector()) {
625 residualError = configProjector->residualError();
626 }
627 output = vectorToFloatSeq(config);
628 return success;
629 } catch (const std::exception& exc) {
630 throw hpp::Error(exc.what());
631 }
632 }
633
634 bool Graph::applyEdgeLeafConstraints(hpp::ID IDedge, const hpp::floatSeq& qleaf,
635 const hpp::floatSeq& input,
636 hpp::floatSeq_out output,
637 double& residualError) {
638 /// First get the constraint.
639 graph::EdgePtr_t edge;
640 try {
641 edge =
642 HPP_DYNAMIC_PTR_CAST(graph::Edge, graph()->get((size_t)IDedge).lock());
643 if (!edge) {
644 std::stringstream ss;
645 ss << "ID " << IDedge << " is not an edge";
646 std::string errmsg = ss.str();
647 throw Error(errmsg.c_str());
648 }
649 bool success = false;
650 DevicePtr_t robot = getRobotOrThrow(problemSolver());
651 Configuration_t config = floatSeqToConfig(robot, input, true);
652 Configuration_t qRhs = floatSeqToConfig(robot, qleaf, true);
653 ConstraintSetPtr_t cs(edge->pathConstraint());
654 assert(cs);
655
656 if (cs->configProjector()) {
657 cs->configProjector()->rightHandSideFromConfig(qRhs);
658 success = cs->apply(config);
659 residualError = cs->configProjector()->residualError();
660 } else {
661 residualError = 0;
662 }
663
664 output = vectorToFloatSeq(config);
665 return success;
666 } catch (const std::exception& exc) {
667 throw hpp::Error(exc.what());
668 }
669 }
670
671 bool Graph::generateTargetConfig(hpp::ID IDedge, const hpp::floatSeq& qleaf,
672 const hpp::floatSeq& input,
673 hpp::floatSeq_out output,
674 double& residualError) {
675 /// First get the constraint.
676 graph::EdgePtr_t edge;
677 try {
678 edge =
679 HPP_DYNAMIC_PTR_CAST(graph::Edge, graph()->get((size_t)IDedge).lock());
680 if (!edge) {
681 std::stringstream ss;
682 ss << "ID " << IDedge << " is not an edge";
683 std::string errmsg = ss.str();
684 throw Error(errmsg.c_str());
685 }
686 bool success = false;
687 DevicePtr_t robot = getRobotOrThrow(problemSolver());
688 Configuration_t config = floatSeqToConfig(robot, input, true);
689 Configuration_t qRhs = floatSeqToConfig(robot, qleaf, true);
690 value_type dist = 0;
691 core::NodePtr_t nNode = problemSolver()->roadmap()->nearestNode(qRhs, dist);
692 if (dist < 1e-8)
693 success = edge->generateTargetConfig(nNode, config);
694 else
695 success = edge->generateTargetConfig(qRhs, config);
696
697 hpp::core::ConfigProjectorPtr_t configProjector(
698 edge->targetConstraint()->configProjector());
699 if (configProjector) {
700 residualError = configProjector->residualError();
701 } else {
702 hppDout(info, "No config projector.");
703 }
704 ULong size = (ULong)config.size();
705 hpp::floatSeq* q_ptr = new hpp::floatSeq();
706 q_ptr->length(size);
707
708 for (std::size_t i = 0; i < size; ++i) {
709 (*q_ptr)[(ULong)i] = config[i];
710 }
711 output = q_ptr;
712 return success;
713 } catch (const std::exception& exc) {
714 throw hpp::Error(exc.what());
715 }
716 }
717
718 CORBA::Boolean Graph::getConfigErrorForNode(ID nodeId,
719 const hpp::floatSeq& dofArray,
720 hpp::floatSeq_out error) {
721 graph::StatePtr_t state = getComp<graph::State>(nodeId);
722 DevicePtr_t robot = getRobotOrThrow(problemSolver());
723 try {
724 vector_t err;
725 Configuration_t config(floatSeqToConfig(robot, dofArray, true));
726 bool res = graph()->getConfigErrorForState(config, state, err);
727 error = vectorToFloatSeq(err);
728 return res;
729 } catch (const std::exception& exc) {
730 throw Error(exc.what());
731 }
732 }
733
734 CORBA::Boolean Graph::getConfigErrorForEdge(ID edgeId,
735 const hpp::floatSeq& dofArray,
736 hpp::floatSeq_out error) {
737 DevicePtr_t robot = getRobotOrThrow(problemSolver());
738 try {
739 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
740 // If steering method is not completely set in the graph, create
741 // one.
742 if (!edge->parentGraph()->problem()->manipulationSteeringMethod() ||
743 !edge->parentGraph()
744 ->problem()
745 ->manipulationSteeringMethod()
746 ->innerSteeringMethod()) {
747 problemSolver()->initSteeringMethod();
748 if (!edge->parentGraph()->problem()->manipulationSteeringMethod() ||
749 !edge->parentGraph()
750 ->problem()
751 ->manipulationSteeringMethod()
752 ->innerSteeringMethod())
753 throw Error("Could not initialize the steering method.");
754 }
755 vector_t err;
756 Configuration_t config(floatSeqToConfig(robot, dofArray, true));
757 bool res = graph()->getConfigErrorForEdge(config, edge, err);
758 floatSeq* e = new floatSeq();
759 e->length((ULong)err.size());
760 for (std::size_t i = 0; i < (std::size_t)err.size(); ++i) {
761 (*e)[(ULong)i] = err[i];
762 }
763 error = e;
764 return res;
765 } catch (const std::exception& exc) {
766 throw Error(exc.what());
767 }
768 }
769
770 CORBA::Boolean Graph::getConfigErrorForEdgeLeaf(
771 ID edgeId, const hpp::floatSeq& leafDofArray, const hpp::floatSeq& dofArray,
772 hpp::floatSeq_out error) {
773 DevicePtr_t robot = getRobotOrThrow(problemSolver());
774 try {
775 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
776 // If steering method is not completely set in the graph, create
777 // one.
778 if (!edge->parentGraph()->problem()->manipulationSteeringMethod() ||
779 !edge->parentGraph()
780 ->problem()
781 ->manipulationSteeringMethod()
782 ->innerSteeringMethod()) {
783 problemSolver()->initSteeringMethod();
784 if (!edge->parentGraph()->problem()->manipulationSteeringMethod() ||
785 !edge->parentGraph()
786 ->problem()
787 ->manipulationSteeringMethod()
788 ->innerSteeringMethod())
789 throw Error("Could not initialize the steering method.");
790 }
791 vector_t err;
792 Configuration_t leafConfig(floatSeqToConfig(robot, leafDofArray, true));
793 Configuration_t config(floatSeqToConfig(robot, dofArray, true));
794 bool res =
795 graph()->getConfigErrorForEdgeLeaf(leafConfig, config, edge, err);
796 floatSeq* e = new floatSeq();
797 e->length((ULong)err.size());
798 for (std::size_t i = 0; i < (std::size_t)err.size(); ++i) {
799 (*e)[(ULong)i] = err[i];
800 }
801 error = e;
802 return res;
803 } catch (const std::exception& exc) {
804 throw Error(exc.what());
805 }
806 }
807
808 CORBA::Boolean Graph::getConfigErrorForEdgeTarget(
809 ID edgeId, const hpp::floatSeq& leafDofArray, const hpp::floatSeq& dofArray,
810 hpp::floatSeq_out error) {
811 DevicePtr_t robot = getRobotOrThrow(problemSolver());
812 try {
813 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
814 // If steering method is not completely set in the graph, create
815 // one.
816 if (!edge->parentGraph()->problem()->manipulationSteeringMethod() ||
817 !edge->parentGraph()
818 ->problem()
819 ->manipulationSteeringMethod()
820 ->innerSteeringMethod()) {
821 problemSolver()->initSteeringMethod();
822 if (!edge->parentGraph()->problem()->manipulationSteeringMethod() ||
823 !edge->parentGraph()
824 ->problem()
825 ->manipulationSteeringMethod()
826 ->innerSteeringMethod())
827 throw Error("Could not initialize the steering method.");
828 }
829 vector_t err;
830 Configuration_t leafConfig(floatSeqToConfig(robot, leafDofArray, true));
831 Configuration_t config(floatSeqToConfig(robot, dofArray, true));
832 bool res =
833 graph()->getConfigErrorForEdgeTarget(leafConfig, config, edge, err);
834 floatSeq* e = new floatSeq();
835 e->length((ULong)err.size());
836 for (std::size_t i = 0; i < (std::size_t)err.size(); ++i) {
837 (*e)[(ULong)i] = err[i];
838 }
839 error = e;
840 return res;
841 } catch (const std::exception& exc) {
842 throw Error(exc.what());
843 }
844 }
845
846 void Graph::displayNodeConstraints(hpp::ID nodeId,
847 CORBA::String_out constraints) {
848 try {
849 graph::StatePtr_t state = getComp<graph::State>(nodeId);
850 ConstraintSetPtr_t cs(graph()->configConstraint(state));
851 std::ostringstream oss;
852 oss << (*cs);
853 constraints = oss.str().c_str();
854 } catch (const std::exception& exc) {
855 throw Error(exc.what());
856 }
857 }
858
859 void Graph::displayEdgeTargetConstraints(hpp::ID edgeId,
860 CORBA::String_out constraints) {
861 try {
862 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
863 ConstraintSetPtr_t cs(graph()->targetConstraint(edge));
864 std::ostringstream oss;
865 oss << (*cs);
866 constraints = oss.str().c_str();
867 } catch (const std::exception& exc) {
868 throw Error(exc.what());
869 }
870 }
871
872 void Graph::displayEdgeConstraints(hpp::ID edgeId,
873 CORBA::String_out constraints) {
874 try {
875 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
876 ConstraintSetPtr_t cs(graph()->pathConstraint(edge));
877 std::ostringstream oss;
878 oss << (*cs);
879 constraints = oss.str().c_str();
880 } catch (const std::exception& exc) {
881 throw Error(exc.what());
882 }
883 }
884
885 void Graph::getNodesConnectedByEdge(hpp::ID edgeId, CORBA::String_out from,
886 CORBA::String_out to) {
887 try {
888 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
889 from = edge->stateFrom()->name().c_str();
890 to = edge->stateTo()->name().c_str();
891 } catch (const std::exception& exc) {
892 throw Error(exc.what());
893 }
894 }
895
896 void Graph::display(const char* filename) {
897 try {
898 std::cout << *graph();
899 std::ofstream dotfile;
900 dotfile.open(filename);
901 graph()->dotPrint(dotfile);
902 dotfile.close();
903 } catch (const std::exception& exc) {
904 throw Error(exc.what());
905 }
906 }
907
908 void Graph::getHistogramValue(ID edgeId, hpp::floatSeq_out freq,
909 hpp::floatSeqSeq_out values) {
910 graph::LevelSetEdgePtr_t edge = getComp<graph::LevelSetEdge>(edgeId);
911 try {
912 graph::LeafHistogramPtr_t hist = edge->histogram();
913 floatSeq* _freq = new floatSeq();
914 floatSeqSeq* _values = new floatSeqSeq();
915 _freq->length(hist->numberOfBins());
916 _values->length(hist->numberOfBins());
917 ULong i = 0;
918 for (graph::LeafHistogram::const_iterator it = hist->begin();
919 it != hist->end(); ++it) {
920 (*_freq)[i] = (CORBA::Double)it->freq();
921 floatSeq v;
922 const vector_t& offset = it->value();
923 v.length((ULong)offset.size());
924 for (ULong j = 0; j < offset.size(); ++j) v[j] = (CORBA::Double)offset[j];
925 (*_values)[i] = v;
926 i++;
927 }
928 freq = _freq;
929 values = _values;
930 } catch (const std::exception& exc) {
931 throw Error(exc.what());
932 }
933 }
934
935 void Graph::setShort(ID edgeId, CORBA::Boolean isShort) {
936 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
937 try {
938 edge->setShort(isShort);
939 } catch (const std::exception& exc) {
940 throw Error(exc.what());
941 }
942 }
943
944 bool Graph::isShort(ID edgeId) {
945 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
946 try {
947 return edge->isShort();
948 } catch (const std::exception& exc) {
949 throw Error(exc.what());
950 }
951 }
952
953 Long Graph::autoBuild(const char* graphName, const Names_t& grippers,
954 const Names_t& objects, const Namess_t& handlesPerObject,
955 const Namess_t& shapesPreObject, const Names_t& envNames,
956 const Rules& rulesList) {
957 std::vector<graph::helper::Rule> rules(rulesList.length());
958
959 for (ULong i = 0; i < rulesList.length(); ++i) {
960 setRule(rulesList[i], rules[i]);
961 }
962 try {
963 graph::GraphPtr_t g = graph::helper::graphBuilder(
964 problemSolver(), graphName,
965 corbaServer::toStrings<std::vector<std::string> >(grippers),
966 toObjectVector(objects, handlesPerObject, shapesPreObject),
967 corbaServer::toStrings<std::vector<std::string> >(envNames), rules);
968
969 return (Long)g->id();
970 } catch (const std::exception& exc) {
971 throw Error(exc.what());
972 }
973 }
974
975 void Graph::setWeight(ID edgeId, const Long weight) {
976 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
977 try {
978 edge->stateFrom()->updateWeight(edge, weight);
979 } catch (const std::exception& exc) {
980 throw Error(exc.what());
981 }
982 }
983
984 Long Graph::getWeight(ID edgeId) {
985 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId);
986 try {
987 return (Long)edge->stateFrom()->getWeight(edge);
988 } catch (const std::exception& exc) {
989 throw Error(exc.what());
990 }
991 }
992
993 char* Graph::getName(ID elmtId) {
994 try {
995 return corbaServer::c_str(graph()->get(elmtId).lock()->name());
996 } catch (std::exception& e) {
997 throw Error(e.what());
998 }
999 }
1000
1001 void Graph::initialize() {
1002 try {
1003 problemSolver()->initConstraintGraph();
1004 } catch (const std::exception& exc) {
1005 throw Error(exc.what());
1006 }
1007 }
1008
1009 void Graph::getRelativeMotionMatrix(ID edgeId, intSeqSeq_out matrix) {
1010 try {
1011 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId, true);
1012 matrix = matrixToIntSeqSeq(edge->relativeMotion().cast<CORBA::Long>());
1013 } catch (const std::exception& exc) {
1014 throw Error(exc.what());
1015 }
1016 }
1017
1018 void Graph::getSecurityMarginMatrixForEdge(ID edgeId, floatSeqSeq_out matrix) {
1019 try {
1020 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId, true);
1021 matrix = corbaServer::matrixToFloatSeqSeq(edge->securityMargins());
1022 } catch (const std::exception& exc) {
1023 throw Error(exc.what());
1024 }
1025 }
1026
1027 void Graph::setSecurityMarginForEdge(ID edgeId, const char* joint1,
1028 const char* joint2, double margin) {
1029 try {
1030 graph::EdgePtr_t edge = getComp<graph::Edge>(edgeId, true);
1031 DevicePtr_t robot(edge->parentGraph()->robot());
1032 JointPtr_t j1(robot->getJointByName(joint1));
1033 JointPtr_t j2(robot->getJointByName(joint2));
1034 size_type i1 = 0;
1035 if (j1) {
1036 i1 = j1->index();
1037 }
1038 size_type i2 = 0;
1039 if (j2) {
1040 i2 = j2->index();
1041 }
1042 edge->securityMarginForPair(i1, i2, margin);
1043 } catch (const std::exception& exc) {
1044 throw Error(exc.what());
1045 }
1046 }
1047
1048 } // namespace impl
1049 } // namespace manipulation
1050 } // namespace hpp
1051