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 
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()const;
125 
126  b2Transform travel_transform();
127 
128  bool isTurning()const{
129  return direction==LEFT || direction==RIGHT;
130  }
131 
132  bool isGoingStraight()const{
133  return direction==DEFAULT || direction==STOP;
134  }
135 
136 };
137 
138 
144  b2Transform pose=b2Transform_zero;
145  BodyFeatures Di, Dn;
146  enum WHAT_D_FLAG{DI, DN};
147 
148  StateDifference()=default;
149 
150  StateDifference(const State& s1, const State& s2){
151  init(s1, s2);
152  }
153 
154  float sum(){
155  return sum_r()+sum_D(Di)+ sum_D(Dn);
156  }
157 
161  float sum_r(){
162  return fabs(pose.p.x)+fabs(pose.p.y)+fabs(pose.q.GetAngle());
163  }
164 
170  float sum_D_pos(const BodyFeatures& bf){
171  return fabs(bf.pose.p.x)+fabs(bf.pose.p.y)+bf.pose.q.GetAngle();
172  }
173 
179  float sum_D_shape(const BodyFeatures& bf){
180  return fabs(bf.width())+fabs(bf.length());
181  }
182 
188  float sum_D(const BodyFeatures& bf){
189  return sum_D_pos(bf)+sum_D_shape(bf);
190  }
191 
197  float get_sum(int mt);
198 
205  void init(const State& s1,const State& s2);
206 
212 
222  void fill_valid_bodyfeatures(BodyFeatures & bf, const State& s1, const State& s2, WHAT_D_FLAG flag);
223 };
224 
225 
226 typedef boost::adjacency_list<boost::setS, boost::vecS, boost::bidirectionalS, State, Edge> TransitionSystem;
227 
228 typedef boost::graph_traits<TransitionSystem>::vertex_iterator vertexIterator;
229 typedef boost::graph_traits<TransitionSystem>::vertex_descriptor vertexDescriptor;
230 typedef boost::graph_traits<TransitionSystem>::edge_descriptor edgeDescriptor;
231 typedef boost::graph_traits<TransitionSystem>::edge_iterator edgeIterator;
232 
233 //SPECIAL VERTICES
234 const vertexDescriptor DUMMY=1;
235 
242 const vertexDescriptor MOVING_VERTEX=0;
243 
248 struct is_not_v{
249  is_not_v(){}
255  is_not_v(vertexDescriptor _cv): cv(_cv){}
256 
257  bool operator()(edgeDescriptor e){
258  return e.m_target!=cv;
259  }
260 
261  private:
262  vertexDescriptor cv=0;
263 };
264 
269 struct Connected{
270  Connected(){}
271  Connected(TransitionSystem * ts): g(ts){}
272 
273  bool operator()(const vertexDescriptor& v)const{
274  bool in= boost::in_degree(v, *g)>0;
275  bool out =boost::out_degree(v, *g)>0;
276  return (in || out) || v==0 ;
277  }
278 private:
279 TransitionSystem * g=NULL;
280 };
281 
282 
283 
284 namespace gt{
285 
293  void fill(simResult sr, State* s=NULL, Edge* e=NULL);
294 
298  int simToMotorStep(int simstep);
299 
307  int distanceToSimStep(const float& s, const float& ds);
308 
318  void update(edgeDescriptor e, std::pair <State, Edge> sk, TransitionSystem& g, bool current, int it);
328  void set(edgeDescriptor e, std::pair <State, Edge>sk, TransitionSystem&, bool current, int it);
329 
330 
331  std::pair< bool, edgeDescriptor> getMostLikely(TransitionSystem&,std::vector<edgeDescriptor>, int);
332 
333  std::vector <edgeDescriptor> outEdges(TransitionSystem&, vertexDescriptor, Direction); //returns a vector containing all the out-edges of a vertex which have the specified direction
334 
335  Disturbance getExpectedDisturbance(TransitionSystem&, vertexDescriptor, Direction, int);
336 
345  std::pair <bool,edgeDescriptor> visitedEdge(const std::vector <edgeDescriptor>& es, TransitionSystem& g, vertexDescriptor cv=TransitionSystem::null_vertex());
346 
347 
348  std::pair <edgeDescriptor, bool> add_edge(const vertexDescriptor&, const vertexDescriptor &, TransitionSystem&, const int &, Direction d=UNDEFINED); //wrapper around boost function, disallows edges to self
349 
356  bool check_edge_direction(const std::pair<edgeDescriptor, bool> &, TransitionSystem&, Direction);
367  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
368 
369 
370 
371 }
372 
373 struct InPlan{
374  InPlan()=default;
375 
376  InPlan(std::vector <vertexDescriptor>* _p):plan(_p){}
377 
378  bool operator()(const edgeDescriptor & e)const{
379  return (check_vector_for(*plan, e.m_target)!=plan->end());
380  }
381 
382  private:
383  std::vector<vertexDescriptor> *plan;
384 };
385 
386 
387 
388 struct NotSelfEdge{
389  NotSelfEdge()=default;
390  NotSelfEdge(TransitionSystem * _g): g(_g){}
391 
392  bool operator()(const edgeDescriptor & e) const {
393  bool not_self= e.m_source!=e.m_target && (*g)[e].step!=0 ;
394  // if (e.m_source==e.m_target){
395  // auto def_kin =(*default_kinematics.find((*g)[e.m_target].direction)).second;
396 
397  // }
398  return not_self;
399  }
400  private:
401  TransitionSystem * g=NULL;
402 };
403 
410 struct ViableEdge{
411  ViableEdge()=default;
412  ViableEdge(TransitionSystem * _g): g(_g){}
413 
414  bool operator()(const edgeDescriptor & e) const {
415  NotSelfEdge nse(g);
416  bool not_self= nse(e) || e.m_source==e.m_target && (*g)[e].step!=0 && (*g)[e].it_observed>=0;
417  return not_self;
418  }
419  private:
420  TransitionSystem * g=NULL;
421 };
422 
424  InviableEdge()=default;
425  InviableEdge(TransitionSystem * _g): g(_g){}
426 
427  bool operator()(const edgeDescriptor & e) const {
428  ViableEdge ve(g);
429  return !ve(e);
430  }
431 
432 private:
433 TransitionSystem * g=NULL;
434 };
435 
437  SameIteration()=default;
438  SameIteration(TransitionSystem & _g, int _i): g(_g), iteration(_i){}
439 
440  bool operator()(const edgeDescriptor & e) const {
441  return g[e].it_observed==iteration;
442  }
443  private:
444  TransitionSystem & g;
445  int iteration=-1;
446 };
447 
448 
449 
450 typedef boost::filtered_graph<TransitionSystem, ViableEdge, Connected> FilteredTS;
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:47
Definition: threshold.h:10
Definition: graphTools.h:453
A closed hybrid control loop. It has an initial disturbance representing the continuous state and a d...
Definition: task.h:45
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:269
Definition: disturbance.h:114
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:373
Definition: graphTools.h:423
Definition: graphTools.h:388
Definition: graphTools.h:436
Contains the differences between the contiuous components of two hybrid states.
Definition: graphTools.h:143
float sum_D(const BodyFeatures &bf)
Total difference in disturbance pose and shape combined.
Definition: graphTools.h:188
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:170
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:179
float sum_r()
Total difference in "global" robot pose.
Definition: graphTools.h:161
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:410
Used as a predicate, gives info on whether a vertex is the current vertex.
Definition: graphTools.h:248
is_not_v(vertexDescriptor _cv)
Constructor assigns current vertex.
Definition: graphTools.h:255
Definition: disturbance.h:270