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=simResult::successful;
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  State()=default;
83 
84  State(const b2Transform &_start): start(_start){}
85 
86  State(const b2Transform &_start, const Disturbance& di, const Direction & dir): start(_start), Di(di), direction(dir){}
87 
91  bool visited(){
92  return phi<NAIVE_PHI;
93  }
94 
99  void resetVisited(){
100  phi=NAIVE_PHI;
101  }
102 
106  b2Transform start_from_Di()const;
107 
111  b2Transform start_from_Dn()const;
112 
116  b2Transform end_from_Dn()const;
117 
121  b2Transform end_from_Di()const;
122 
123  float distance()const;
124 
125  b2Transform travel_transform();
126 
127  bool isTurning()const{
128  return direction==LEFT || direction==RIGHT;
129  }
130 
131  bool isGoingStraight()const{
132  return direction==DEFAULT || direction==STOP;
133  }
134 
135 
136 
137  // float gamma(){
138  // Angle a(atan2(end_from_Dn().p.y, end_from_Dn().p.y));
139  // Distance d(end_from_Dn().p.Length());
140  // return getStanda
141  // }
142 
143 };
144 
145 
151  b2Transform pose=b2Transform_zero;
152  BodyFeatures Di, Dn;
153  enum WHAT_D_FLAG{DI, DN};
154 
155  StateDifference()=default;
156 
157  StateDifference(const State& s1, const State& s2){
158  init(s1, s2);
159  }
160 
161  float sum(){
162  return sum_r()+sum_D(Di)+ sum_D(Dn);
163  }
164 
168  float sum_r(){
169  return fabs(pose.p.x)+fabs(pose.p.y)+fabs(pose.q.GetAngle());
170  }
171 
177  float sum_D_pos(const BodyFeatures& bf){
178  return fabs(bf.pose.p.x)+fabs(bf.pose.p.y)+bf.pose.q.GetAngle();
179  }
180 
186  float sum_D_shape(const BodyFeatures& bf){
187  return fabs(bf.width())+fabs(bf.length());
188  }
189 
195  float sum_D(const BodyFeatures& bf){
196  return sum_D_pos(bf)+sum_D_shape(bf);
197  }
198 
204  float get_sum(int mt);
205 
212  void init(const State& s1,const State& s2);
213 
219 
229  void fill_valid_bodyfeatures(BodyFeatures & bf, const State& s1, const State& s2, WHAT_D_FLAG flag);
230 };
231 
232 
233 typedef boost::adjacency_list<boost::setS, boost::vecS, boost::bidirectionalS, State, Edge> TransitionSystem;
234 
235 typedef boost::graph_traits<TransitionSystem>::vertex_iterator vertexIterator;
236 typedef boost::graph_traits<TransitionSystem>::vertex_descriptor vertexDescriptor;
237 typedef boost::graph_traits<TransitionSystem>::edge_descriptor edgeDescriptor;
238 typedef boost::graph_traits<TransitionSystem>::edge_iterator edgeIterator;
239 
240 //SPECIAL VERTICES
247 const vertexDescriptor MOVING_VERTEX=0;
248 
254 const vertexDescriptor DUMMY=1;
255 
256 
261 struct is_not_v{
262  is_not_v(){}
268  is_not_v(vertexDescriptor _cv): cv(_cv){}
269 
270  bool operator()(edgeDescriptor e){
271  return e.m_target!=cv;
272  }
273 
274  private:
275  vertexDescriptor cv=0;
276 };
277 
282 struct Connected{
283  Connected(){}
284  Connected(TransitionSystem * ts): g(ts){}
285 
286  bool operator()(const vertexDescriptor& v)const{
287  bool in= boost::in_degree(v, *g)>0;
288  bool out =boost::out_degree(v, *g)>0;
289  return (in || out) || v==0 ;
290  }
291 private:
292 TransitionSystem * g=NULL;
293 };
294 
295 
296 
297 namespace gt{
298 
306  void fill(simResult sr, State* s=NULL, Edge* e=NULL);
307 
311  int simToMotorStep(int simstep);
312 
320  int distanceToSimStep(const float& s, const float& ds);
321 
331  void update(edgeDescriptor e, std::pair <State, Edge> sk, TransitionSystem& g, bool current, int it);
341  void set(edgeDescriptor e, std::pair <State, Edge>sk, TransitionSystem&, bool current, int it);
342 
343 
344  std::pair< bool, edgeDescriptor> getMostLikely(TransitionSystem&,std::vector<edgeDescriptor>, int);
345 
346  std::vector <edgeDescriptor> outEdges(TransitionSystem&, vertexDescriptor, Direction); //returns a vector containing all the out-edges of a vertex which have the specified direction
347 
348  Disturbance getExpectedDisturbance(TransitionSystem&, vertexDescriptor, Direction, int);
349 
358  std::pair <bool,edgeDescriptor> visitedEdge(const std::vector <edgeDescriptor>& es, TransitionSystem& g, vertexDescriptor cv=TransitionSystem::null_vertex());
359 
360 
361  std::pair <edgeDescriptor, bool> add_edge(const vertexDescriptor&, const vertexDescriptor &, TransitionSystem&, const int &, Direction d=UNDEFINED); //wrapper around boost function, disallows edges to self
362 
369  bool check_edge_direction(const std::pair<edgeDescriptor, bool> &, TransitionSystem&, Direction);
380  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
381 
382 
383 
384 }
385 
386 struct InPlan{
387  InPlan()=default;
388 
389  InPlan(std::vector <vertexDescriptor>* _p):plan(_p){}
390 
391  bool operator()(const edgeDescriptor & e)const{
392  return (check_vector_for(*plan, e.m_target)!=plan->end());
393  }
394 
395  private:
396  std::vector<vertexDescriptor> *plan;
397 };
398 
399 
400 
401 struct NotSelfEdge{
402  NotSelfEdge()=default;
403  NotSelfEdge(TransitionSystem * _g): g(_g){}
404 
405  bool operator()(const edgeDescriptor & e) const {
406  bool not_self= e.m_source!=e.m_target && (*g)[e].step!=0 ;
407  // if (e.m_source==e.m_target){
408  // auto def_kin =(*default_kinematics.find((*g)[e.m_target].direction)).second;
409 
410  // }
411  return not_self;
412  }
413  private:
414  TransitionSystem * g=NULL;
415 };
416 
423 struct ViableEdge{
424  ViableEdge()=default;
425  ViableEdge(TransitionSystem * _g): g(_g){}
426 
427  bool operator()(const edgeDescriptor & e) const {
428  NotSelfEdge nse(g);
429  bool not_self= nse(e) || e.m_source==e.m_target && (*g)[e].step!=0 && (*g)[e].it_observed>=0;
430  return not_self;
431  }
432  private:
433  TransitionSystem * g=NULL;
434 };
435 
437  InviableEdge()=default;
438  InviableEdge(TransitionSystem * _g): g(_g){}
439 
440  bool operator()(const edgeDescriptor & e) const {
441  ViableEdge ve(g);
442  return !ve(e);
443  }
444 
445 private:
446 TransitionSystem * g=NULL;
447 };
448 
450  SameIteration()=default;
451  SameIteration(TransitionSystem & _g, int _i): g(_g), iteration(_i){}
452 
453  bool operator()(const edgeDescriptor & e) const {
454  return g[e].it_observed==iteration;
455  }
456  private:
457  TransitionSystem & g;
458  int iteration=-1;
459 };
460 
461 
462 
463 typedef boost::filtered_graph<TransitionSystem, ViableEdge, Connected> FilteredTS;
464 
465 
467  public:
468  //@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};
469  enum MATCH_TYPE {_FALSE, D_NEW, DN_POSE, _TRUE, ANY, D_INIT, ABSTRACT, DI_POSE, DN_SHAPE, DI_SHAPE, POSE, D_SHAPES};
470 
471  float mu=0.001;
472  StateMatcher()=default;
473 
474  struct StateMatch{
475 
476  bool exact(){
477  return pose() && abstract();
478  }
479 
480  bool pose(){
481  return position && angle;
482  }
483 
484  bool abstract(){ //states match Di and Dn regardless of objective pose
485  return Di_exact() && Dn_exact();
486  }
487 
488  bool Di_exact(){
489  return Di_position && Di_angle && Di_shape;
490  }
491 
492  bool Dn_exact(){
493  return Dn_position && Dn_angle && Dn_shape;
494  }
495 
496  bool Di_pose(){
497  return Di_position && Di_angle;
498  }
499 
500  bool Dn_pose(){
501  return Dn_position && Dn_angle;
502  }
503 
504  bool shape_Di(){
505  return Di_shape;
506  }
507 
508  bool shape_Dn(){
509  return Dn_shape;
510  }
511  bool Dn(){
512  return Dn_shape && Dn_pose();
513  }
514 
515  bool Di(){
516  return Di_shape && Di_pose();
517  }
518 
519  bool D_shapes(){
520  return Dn_shape && Di_shape;
521  }
522 
523  StateMatch() =default;
524 
525  StateMatch(const StateDifference& sd,const Threshold& threshold, float coefficient=1){
526  position = sd.pose.p.Length()<(threshold.for_robot_position()*coefficient);
527  angle=fabs(sd.pose.q.GetAngle())<threshold.for_robot_angle();
528  Bundle Dn=threshold.for_Dn(), Di=threshold.for_Di();
529  Dn_position= sd.Dn.pose.p.Length()<(Dn.radius()*coefficient);
530  Di_position= sd.Di.pose.p.Length()<(Di.radius()*coefficient);
531  Dn_angle=fabs(sd.Dn.pose.q.GetAngle())<Dn.get_angle();
532  Di_angle=fabs(sd.Di.pose.q.GetAngle())<Di.get_angle();
533  bool Dn_below_threshold_w=fabs(sd.Dn.width())<(Dn.get_width()*coefficient*2);
534  bool Dn_below_threshold_l=fabs(sd.Dn.length())<(Dn.get_length()*coefficient*2);
535  bool Di_below_threshold_w=fabs(sd.Di.width())<(Dn.get_width()*coefficient*2);
536  bool Di_below_threshold_l=fabs(sd.Di.length())<(Dn.get_length()*coefficient*2);
537  Dn_shape= Dn_below_threshold_l && Dn_below_threshold_w;
538  Di_shape= Di_below_threshold_l && Di_below_threshold_w;
539 
540  }
541 
542  StateMatcher::MATCH_TYPE what(){
543  if (exact()){ //match position and disturbance
544  return _TRUE;
545  }
546  else if (abstract()){
547  return ABSTRACT;
548  }
549  else if (Dn_exact()){
550  return D_NEW;
551  }
552  else if (Di_exact()){
553  return D_INIT;
554  }
555  else if (D_shapes()){
556  return D_SHAPES;
557  }
558  else if (Dn_pose()){
559  return DN_POSE;
560  }
561  else if (Di_pose()){
562  return DI_POSE;
563  }
564  else if (shape_Dn()){
565  return DN_SHAPE;
566  }
567  else if (shape_Di()){
568  return DI_SHAPE;
569  }
570  else{
571  return _FALSE;
572  }
573  }
574 
575  private:
576 
577  bool position=false;
578  bool angle=false;
579  bool Di_position=false;
580  bool Di_angle=false;
581  bool Di_shape=false;
582  bool Dn_position=false;
583  bool Dn_angle=false;
584  bool Dn_shape=false;
585  };
586 
587  bool match_equal(const MATCH_TYPE& candidate, const MATCH_TYPE& desired);
588 
589  MATCH_TYPE isMatch(const StateDifference &, const Threshold &, float endDistance=0); //endDistance=endpose
590 
591  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
592 
593  //std::pair<MATCH_TYPE, vertexDescriptor> match_vertex(TransitionSystem, vertexDescriptor, Direction, State, StateMatcher::MATCH_TYPE mt=StateMatcher::_TRUE); //find match amoung vertex out edges
594 
595  float get_coefficient(const float &);
596  private:
597 
598 
599  const float COEFFICIENT_INCREASE_THRESHOLD=0.0;
600 };
601 
602 typedef std::pair<StateMatcher::MATCH_TYPE, vertexDescriptor> VertexMatch;
603 
604 #endif
Definition: threshold.h:10
Definition: graphTools.h:466
A closed hybrid control loop. It has an initial disturbance representing the continuous state and a d...
Definition: task.h:47
Definition: threshold.h:91
Bundle for_Dn() const
Returns a bundle of thresholds for the initial disturbance.
Definition: threshold.h:126
Bundle for_Di() const
Returns a bundle of thresholds for the initial disturbance.
Definition: threshold.h:119
Definition: disturbance.h:47
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:282
Definition: disturbance.h:113
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:41
Definition: graphTools.h:386
Definition: graphTools.h:436
Definition: graphTools.h:401
Definition: graphTools.h:449
Contains the differences between the contiuous components of two hybrid states.
Definition: graphTools.h:150
float sum_D(const BodyFeatures &bf)
Total difference in disturbance pose and shape combined.
Definition: graphTools.h:195
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:101
void init(const State &s1, const State &s2)
Initialises the difference object using two states we want to compare.
Definition: graphTools.cpp:74
float get_sum(int mt)
Returns difference in certain aspects we want to match between states.
Definition: graphTools.cpp:53
float sum_D_pos(const BodyFeatures &bf)
Total difference in disturbance pose.
Definition: graphTools.h:177
void fill_invalid_bodyfeatures(BodyFeatures &)
Fills bf match with large values indicating no match.
Definition: graphTools.cpp:93
float sum_D_shape(const BodyFeatures &bf)
Total difference in disturbance shape.
Definition: graphTools.h:186
float sum_r()
Total difference in "global" robot pose.
Definition: graphTools.h:168
Definition: graphTools.h:474
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:91
void resetVisited()
Sets the phi value to its naive value (call to visited() will return false)
Definition: graphTools.h:99
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:423
Used as a predicate, gives info on whether a vertex is the current vertex.
Definition: graphTools.h:261
is_not_v(vertexDescriptor _cv)
Constructor assigns current vertex.
Definition: graphTools.h:268
Definition: disturbance.h:269