Bratmobile
graphTools.h
1 #ifndef GENERAL_H
2 #define GENERAL_H
3 #include <set>
4 #include <opencv2/calib3d.hpp> //LMEDS
5 #include <vector>
6 #include <utility> // for std::pair
7 #include <algorithm> // for std::for_each
8 #include <boost/graph/graph_traits.hpp>
9 #include <boost/graph/adjacency_list.hpp>
10 #include <boost/graph/filtered_graph.hpp>
11 #include <boost/graph/graph_utility.hpp>
12 #include <map>
13 #include <boost/property_map/property_map.hpp> //property map
14 #include <boost/graph/copy.hpp>
15 #include <utility>
16 #include "disturbance.h"
17 #include "box2d_helpers.h"
18 
19 const float NAIVE_PHI=10.0;
20 
21 class Task;
22 enum VERTEX_LABEL {UNLABELED, MOVING, ESCAPE, ESCAPE2};
23 
28 struct CompareValue{
29  CompareValue()=default;
30  template <class V, class M>
31  bool operator()(const std::tuple<V,M, float> & p1, const std::tuple<V, M, float> &p2) const{
32  return std::get<2>(p1)< std::get<2>(p2);
33  }
34 };
35 
40 struct Edge{
41  float probability=1.0;
42  int step=0;
43  int it_observed=-1; //last iteration where this edge was observed
44  bool overrideZeroSteps=false; //set to true if an edge with no steps should not be considered a self-edge
45 
46  Edge()=default;
47 
48  float weighted_probability(int it){
49  float result=0;
50  if (it_observed>=0){
51  result=probability*float(it_observed)/float(it);
52  }
53  return result;
54  }
55 
62  bool enableOverride();
63 };
64 
69 struct State{
70  Disturbance Di; //initial Disturbance
71  Disturbance Dn; //new Disturbance
72  b2Transform endPose = b2Transform_zero, start = b2Transform_zero;
73  simResult::resultType outcome;
74  std::vector <Direction> options;
75  bool filled =0;
76  int nObs=0;
77  float phi=NAIVE_PHI; //arbitrarily large phi
78  VERTEX_LABEL label=VERTEX_LABEL::UNLABELED;
79  Direction direction=DEFAULT;
80 
81 
82 
83  State()=default;
84 
85  State(const b2Transform &_start): start(_start){}
86 
87  State(const b2Transform &_start, const Disturbance& di, const Direction & dir): start(_start), Di(di), direction(dir){}
88 
92  bool visited(){
93  return phi<NAIVE_PHI;
94  }
95 
100  void resetVisited(){
101  phi=NAIVE_PHI;
102  }
103 
107  b2Transform start_from_Di()const;
108 
112  b2Transform start_from_Dn()const;
113 
117  b2Transform end_from_Dn()const;
118 
122  b2Transform end_from_Di()const;
123 
124  float distance();
125 
126  b2Transform travel_transform();
127 
128  bool isTurning(){
129  return direction==LEFT || direction==RIGHT;
130  }
131 
132  bool isGoingStraight(){
133  return direction==DEFAULT || direction==STOP;
134  }
135 };
136 
137 
143  b2Transform pose=b2Transform_zero;
144  BodyFeatures Di, Dn;
145  enum WHAT_D_FLAG{DI, DN};
146 
147  StateDifference()=default;
148 
149  StateDifference(const State& s1, const State& s2){
150  init(s1, s2);
151  }
152 
153  float sum(){
154  return sum_r()+sum_D(Di)+ sum_D(Dn);
155  }
156 
160  float sum_r(){
161  return fabs(pose.p.x)+fabs(pose.p.y)+fabs(pose.q.GetAngle());
162  }
163 
169  float sum_D_pos(const BodyFeatures& bf){
170  return fabs(bf.pose.p.x)+fabs(bf.pose.p.y)+bf.pose.q.GetAngle();
171  }
172 
178  float sum_D_shape(const BodyFeatures& bf){
179  return fabs(bf.width())+fabs(bf.length());
180  }
181 
187  float sum_D(const BodyFeatures& bf){
188  return sum_D_pos(bf)+sum_D_shape(bf);
189  }
190 
196  float get_sum(int mt);
197 
204  void init(const State& s1,const State& s2);
205 
211 
221  void fill_valid_bodyfeatures(BodyFeatures & bf, const State& s1, const State& s2, WHAT_D_FLAG flag);
222 };
223 
224 
225 typedef boost::adjacency_list<boost::setS, boost::vecS, boost::bidirectionalS, State, Edge> TransitionSystem;
226 
227 typedef boost::graph_traits<TransitionSystem>::vertex_iterator vertexIterator;
228 typedef boost::graph_traits<TransitionSystem>::vertex_descriptor vertexDescriptor;
229 typedef boost::graph_traits<TransitionSystem>::edge_descriptor edgeDescriptor;
230 typedef boost::graph_traits<TransitionSystem>::edge_iterator edgeIterator;
231 
232 //SPECIAL VERTICES
233 const vertexDescriptor DUMMY=1;
234 
241 const vertexDescriptor MOVING_VERTEX=0;
242 
247 struct is_not_v{
248  is_not_v(){}
254  is_not_v(vertexDescriptor _cv): cv(_cv){}
255 
256  bool operator()(edgeDescriptor e){
257  return e.m_target!=cv;
258  }
259 
260  private:
261  vertexDescriptor cv=0;
262 };
263 
268 struct Connected{
269  Connected(){}
270  Connected(TransitionSystem * ts): g(ts){}
271 
272  bool operator()(const vertexDescriptor& v)const{
273  bool in= boost::in_degree(v, *g)>0;
274  bool out =boost::out_degree(v, *g)>0;
275  return (in || out) || v==0 ;
276  }
277 private:
278 TransitionSystem * g=NULL;
279 };
280 
281 
282 
283 namespace gt{
284 
292  void fill(simResult sr, State* s=NULL, Edge* e=NULL);
293 
297  int simToMotorStep(int simstep);
298 
306  int distanceToSimStep(const float& s, const float& ds);
307 
317  void update(edgeDescriptor e, std::pair <State, Edge> sk, TransitionSystem& g, bool current, int it);
327  void set(edgeDescriptor e, std::pair <State, Edge>sk, TransitionSystem&, bool current, int it);
328 
329 
330  std::pair< bool, edgeDescriptor> getMostLikely(TransitionSystem&,std::vector<edgeDescriptor>, int);
331 
332  std::vector <edgeDescriptor> outEdges(TransitionSystem&, vertexDescriptor, Direction); //returns a vector containing all the out-edges of a vertex which have the specified direction
333 
334  Disturbance getExpectedDisturbance(TransitionSystem&, vertexDescriptor, Direction, int);
335 
344  std::pair <bool,edgeDescriptor> visitedEdge(const std::vector <edgeDescriptor>& es, TransitionSystem& g, vertexDescriptor cv=TransitionSystem::null_vertex());
345 
346 
347  std::pair <edgeDescriptor, bool> add_edge(const vertexDescriptor&, const vertexDescriptor &, TransitionSystem&, const int &, Direction d=UNDEFINED); //wrapper around boost function, disallows edges to self
348 
355  bool check_edge_direction(const std::pair<edgeDescriptor, bool> &, TransitionSystem&, Direction);
366  std::vector<vertexDescriptor>::iterator to_task_end(edgeDescriptor &e, TransitionSystem &g, const std::vector<vertexDescriptor> & plan, std::vector<vertexDescriptor>::iterator it); //in a vector, finds vertices belonging to the same task and skips to the end fo the task
367 
368 
369 
370 }
371 
372 struct InPlan{
373  InPlan()=default;
374 
375  InPlan(std::vector <vertexDescriptor>* _p):plan(_p){}
376 
377  bool operator()(const edgeDescriptor & e)const{
378  return (check_vector_for(*plan, e.m_target)!=plan->end());
379  }
380 
381  private:
382  std::vector<vertexDescriptor> *plan;
383 };
384 
385 
386 
387 struct NotSelfEdge{
388  NotSelfEdge()=default;
389  NotSelfEdge(TransitionSystem * _g): g(_g){}
390 
391  bool operator()(const edgeDescriptor & e) const {
392  bool not_self= e.m_source!=e.m_target && (*g)[e].step!=0 ;
393  // if (e.m_source==e.m_target){
394  // auto def_kin =(*default_kinematics.find((*g)[e.m_target].direction)).second;
395 
396  // }
397  return not_self;
398  }
399  private:
400  TransitionSystem * g=NULL;
401 };
402 
409 struct ViableEdge{
410  ViableEdge()=default;
411  ViableEdge(TransitionSystem * _g): g(_g){}
412 
413  bool operator()(const edgeDescriptor & e) const {
414  NotSelfEdge nse(g);
415  bool not_self= nse(e) || e.m_source==e.m_target && (*g)[e].step!=0;
416  return not_self;
417  }
418  private:
419  TransitionSystem * g=NULL;
420 };
421 
422 // struct InviableEdge{
423 // InviableEdge()=default;
424 // InviableEdge(TransitionSystem * _g): g(_g){}
425 
426 // bool operator()(const edgeDescriptor & e) const {
427 // ViableEdge ve(g);
428 // return !ve(e);
429 // }
430 
431 // private:
432 // TransitionSystem * g=NULL;
433 // };
434 
436  SameIteration()=default;
437  SameIteration(TransitionSystem & _g, int _i): g(_g), iteration(_i){}
438 
439  bool operator()(const edgeDescriptor & e) const {
440  return g[e].it_observed==iteration;
441  }
442  private:
443  TransitionSystem & g;
444  int iteration=-1;
445 };
446 
447 
448 
449 typedef boost::filtered_graph<TransitionSystem, ViableEdge, Connected> FilteredTS;
450 //typedef boost::filtered_graph<TransitionSystem, boost::keep_all, Visited> VisitedTS;
451 
452 
454  public:
455  //@brief {_FALSE=0, D_NEW=2, DN_POSE=3, _TRUE=1, ANY=4, D_INIT=5, ABSTRACT=6, DI_POSE=7, DN_SHAPE=8, DI_SHAPE=9, POSE=10};
456  enum MATCH_TYPE {_FALSE, D_NEW, DN_POSE, _TRUE, ANY, D_INIT, ABSTRACT, DI_POSE, DN_SHAPE, DI_SHAPE, POSE};
457 
458  float mu=0.001;
459  StateMatcher()=default;
460 
461  struct StateMatch{
462 
463  bool exact(){
464  return pose() && abstract();
465  }
466 
467  bool pose(){
468  return position && angle;
469  }
470 
471  bool abstract(){ //states match Di and Dn regardless of objective pose
472  return Di_exact() && Dn_exact();
473  }
474 
475  bool Di_exact(){
476  return Di_position && Di_angle && Di_shape;
477  }
478 
479  bool Dn_exact(){
480  return Dn_position && Dn_angle && Dn_shape;
481  }
482 
483  bool Di_pose(){
484  return Di_position && Di_angle;
485  }
486 
487  bool Dn_pose(){
488  return Dn_position && Dn_angle;
489  }
490 
491  bool shape_Di(){
492  return Di_shape;
493  }
494 
495  bool shape_Dn(){
496  return Dn_shape;
497  }
498  bool Dn(){
499  return Dn_shape && Dn_pose();
500  }
501 
502  bool Di(){
503  return Di_shape && Di_pose();
504  }
505 
506  StateMatch() =default;
507 
508  StateMatch(const StateDifference& sd, Threshold threshold, float coefficient=1){
509  position = sd.pose.p.Length()<(threshold.for_robot_position()*coefficient);
510  angle=fabs(sd.pose.q.GetAngle())<threshold.for_robot_angle();
511  Bundle Dn=threshold.for_Dn(), Di=threshold.for_Di();
512  Dn_position= sd.Dn.pose.p.Length()<(Dn.radius()*coefficient);
513  Di_position= sd.Di.pose.p.Length()<(Di.radius()*coefficient);
514  Dn_angle=fabs(sd.Dn.pose.q.GetAngle())<Dn.get_angle();
515  Di_angle=fabs(sd.Di.pose.q.GetAngle())<Di.get_angle();
516  bool Dn_below_threshold_w=fabs(sd.Dn.width())<(Dn.get_width()*coefficient*2);
517  bool Dn_below_threshold_l=fabs(sd.Dn.length())<(Dn.get_length()*coefficient*2);
518  bool Di_below_threshold_w=fabs(sd.Di.width())<(Dn.get_width()*coefficient*2);
519  bool Di_below_threshold_l=fabs(sd.Di.length())<(Dn.get_length()*coefficient*2);
520  Dn_shape= Dn_below_threshold_l && Dn_below_threshold_w;
521  Di_shape= Di_below_threshold_l && Di_below_threshold_w;
522 
523  }
524 
525  StateMatcher::MATCH_TYPE what(){
526  if (exact()){ //match position and disturbance
527  return _TRUE;
528  }
529  else if (abstract()){
530  return ABSTRACT;
531  }
532  else if (Dn_exact()){
533  return D_NEW;
534  }
535  else if (Di_exact()){
536  return D_INIT;
537  }
538  else if (Dn_pose()){
539  return DN_POSE;
540  }
541  else if (Di_pose()){
542  return DI_POSE;
543  }
544  else if (shape_Dn()){
545  return DN_SHAPE;
546  }
547  else if (shape_Di()){
548  return DI_SHAPE;
549  }
550  else{
551  return _FALSE;
552  }
553  }
554 
555  private:
556 
557  bool position=false;
558  bool angle=false;
559  bool Di_position=false;
560  bool Di_angle=false;
561  bool Di_shape=false;
562  bool Dn_position=false;
563  bool Dn_angle=false;
564  bool Dn_shape=false;
565  };
566 
567  bool match_equal(const MATCH_TYPE& candidate, const MATCH_TYPE& desired);
568 
569  MATCH_TYPE isMatch(const StateDifference &, const Threshold &, float endDistance=0); //endDistance=endpose
570 
571  MATCH_TYPE isMatch(const State & s, const State& candidate, const Threshold &, const State* src=NULL, StateDifference * _sd=NULL); //first state: state to find a match for, second state: candidate match
572 
573  //std::pair<MATCH_TYPE, vertexDescriptor> match_vertex(TransitionSystem, vertexDescriptor, Direction, State, StateMatcher::MATCH_TYPE mt=StateMatcher::_TRUE); //find match amoung vertex out edges
574 
575  float get_coefficient(const float &);
576  private:
577 
578 
579  const float COEFFICIENT_INCREASE_THRESHOLD=0.0;
580 };
581 
582 typedef std::pair<StateMatcher::MATCH_TYPE, vertexDescriptor> VertexMatch;
583 
584 #endif
Definition: disturbance.h:45
Definition: threshold.h:10
Definition: graphTools.h:453
Definition: task.h:19
Definition: threshold.h:91
Bundle for_Dn() const
Returns a bundle of thresholds for the initial disturbance.
Definition: threshold.h:121
Bundle for_Di() const
Returns a bundle of thresholds for the initial disturbance.
Definition: threshold.h:114
Compares the last float in a tuple.
Definition: graphTools.h:28
Predicate: gives info on whether a vertex has connections or is a singleton.
Definition: graphTools.h:268
Definition: disturbance.h:112
Edges connecting states in the transition system.
Definition: graphTools.h:40
bool enableOverride()
If this edge has zero steps, it sets override to true.
Definition: graphTools.cpp:40
Definition: graphTools.h:372
Definition: graphTools.h:387
Definition: graphTools.h:435
Contains the differences between the contiuous components of two hybrid states.
Definition: graphTools.h:142
float sum_D(const BodyFeatures &bf)
Total difference in disturbance pose and shape combined.
Definition: graphTools.h:187
void fill_valid_bodyfeatures(BodyFeatures &bf, const State &s1, const State &s2, WHAT_D_FLAG flag)
Fills the bodyfeatures match with differences between disturbances in the two states....
Definition: graphTools.cpp:100
void init(const State &s1, const State &s2)
Initialises the difference object using two states we want to compare.
Definition: graphTools.cpp:73
float get_sum(int mt)
Returns difference in certain aspects we want to match between states.
Definition: graphTools.cpp:52
float sum_D_pos(const BodyFeatures &bf)
Total difference in disturbance pose.
Definition: graphTools.h:169
void fill_invalid_bodyfeatures(BodyFeatures &)
Fills bf match with large values indicating no match.
Definition: graphTools.cpp:92
float sum_D_shape(const BodyFeatures &bf)
Total difference in disturbance shape.
Definition: graphTools.h:178
float sum_r()
Total difference in "global" robot pose.
Definition: graphTools.h:160
Definition: graphTools.h:461
Hybrid states in the transition system.
Definition: graphTools.h:69
bool visited()
Whether this state has been visited in exploration using evaluation function phi as proxy.
Definition: graphTools.h:92
void resetVisited()
Sets the phi value to its naive value (call to visited() will return false)
Definition: graphTools.h:100
b2Transform end_from_Dn() const
Return transformation from end to Di position.
Definition: graphTools.cpp:17
b2Transform end_from_Di() const
Return transformation from end to Di position.
Definition: graphTools.cpp:25
b2Transform start_from_Dn() const
Return transformation from start to Dn position.
Definition: graphTools.cpp:10
b2Transform start_from_Di() const
Return transformation from start to Di position.
Definition: graphTools.cpp:3
Predicate: gives info on whether an edge is worth keeping. Namely, the edge is either not a self-edge...
Definition: graphTools.h:409
Used as a predicate, gives info on whether a vertex is the current vertex.
Definition: graphTools.h:247
is_not_v(vertexDescriptor _cv)
Constructor assigns current vertex.
Definition: graphTools.h:254
Definition: disturbance.h:268