SmartVehicle-Sortic
SmartFactory
NavigationCtrl.cpp
Go to the documentation of this file.
1 
16 #include "NavigationCtrl.h"
17 //=====PUBLIC====================================================================================
18 NavigationCtrl::NavigationCtrl() : currentState(State::endPoint), doActionFPtr(&NavigationCtrl::doAction_endPoint) {
19 }
20 
22  DBFUNCCALLln("NavigationCtrl::loop()");
23  process((this->*doActionFPtr)()); //do actions
24 }
25 
26 void NavigationCtrl::loop(Event currentEvent) {
27  DBFUNCCALLln("NavigationCtrl::loop(Event)");
29  process((this->*doActionFPtr)()); //do actions
30 }
31 
33  DBFUNCCALL("Current State: ");
35  return currentState;
36 }
37 
39  DBFUNCCALL("Current Sector: ");
40  return pActual.sector;
41 }
42 
44  DBFUNCCALL("Current line: ");
45  return pActual.line;
46 }
47 
48 void NavigationCtrl::setTargetPosition(Sector sector, const int line) {
49  DBFUNCCALLln("NavigationCtrl::setTargetPosition(Sector sector, const int line)");
50  pTarget.sector = sector;
51  pTarget.line = line;
52 }
53 
54 void NavigationCtrl::setActualPosition(Sector sector, const int line) {
55  DBFUNCCALLln("NavigationCtrl::setActualPosition(Sector sector, const int line)");
56  pActual.sector = sector;
57  pActual.line = line;
58 }
59 
61  DBFUNCCALLln("NavigationCtrl::giveToken()");
62  pActual.token = true;
63 }
64 
66  switch (sector) {
68  return "SorticHandover";
69  break;
71  return "SorticToHandover";
72  break;
74  return "SorticWaitForGateway";
75  break;
77  return "SorticGateway";
78  break;
80  return "TransitWaitForGatewaySortic";
81  break;
83  return "TransitToSortic";
84  break;
86  return "TransitToTransfer";
87  break;
88  case Sector::Parking:
89  return "Parking";
90  break;
92  return "TransitWaitForGatewayTransfer";
93  break;
95  return "TransferGateway";
96  break;
98  return "TransferWaitForGateway";
99  break;
101  return "TransferToHandover";
102  break;
104  return "TransferHandover";
105  break;
106 
107  default:
108  return "ERROR: No matching sector";
109  break;
110  }
111 }
112 
114  if (String("SorticHandover") == sector) {
115  return Sector::SorticHandover;
116  } else if (String("SorticToHandover") == sector) {
118  } else if (String("SorticWaitForGateway") == sector) {
120  } else if (String("TransitWaitForGatewaySortic") == sector) {
122  } else if (String("TransitToSortic") == sector) {
124  } else if (String("TransitToTransfer") == sector) {
126  } else if (String("Parking") == sector) {
127  return Sector::Parking;
128  } else if (String("TransitWaitForGatewayTransfer") == sector) {
130  } else if (String("TransferGateway") == sector) {
132  } else if (String("TransferWaitForGateway") == sector) {
134  } else if (String("TransferToHandover") == sector) {
136  } else if (String("TransferHandover") == sector) {
138  } else {
139  return Sector::error;
140  }
141 }
142 
143 //=====PRIVATE====================================================================================
145  DBFUNCCALL("NavigationCtrl::process ")
147  switch (currentState) {
148  case State::endPoint:
149  if (Event::MoveToTargetPosition == e) {
150  if ((pActual.sector == pTarget.sector) && (pActual.line == pTarget.line)) {
151  //Already in correct position?
152  DBSTATUSln("Navigation: Already in correct position");
153  break;
154  }
155  exitAction_endPoint(); // Exit-action current state
156  entryAction_toGateway(); // Entry-actions next state
157  } else if (Event::Error == e) {
158  exitAction_endPoint(); // Exit-action current state
159  entryAction_errorState(); // Entry-actions next state
160  }
161  break;
162  case State::toGateway:
163  if (Event::PosReached == e) {
164  exitAction_toGateway(); // Exit-action current state
165  entryAction_gateway(); // Entry-actions next state
166  } else if (Event::Error == e) {
167  exitAction_toGateway(); // Exit-action current state
168  entryAction_errorState(); // Entry-actions next state
169  }
170  break;
171  case State::gateway:
172  if (Event::PosTransitReached == e) {
173  exitAction_gateway(); // Exit-action current state
174  entryAction_crossTransit(); // Entry-actions next state
175  } else if (Event::PosEndPointReached == e) {
176  exitAction_gateway(); // Exit-action current state
177  entryAction_toEndPoint(); // Entry-actions next state
178  } else if (Event::Error == e) {
179  exitAction_gateway(); // Exit-action current state
180  entryAction_errorState(); // Entry-actions next state
181  }
182  break;
183  case State::crossTransit:
184  if (Event::PosReached == e) {
185  exitAction_crossTransit(); // Exit-action current state
186  entryAction_gateway(); // Entry-actions next state
187  } else if (Event::Error == e) {
188  exitAction_crossTransit(); // Exit-action current state
189  entryAction_errorState(); // Entry-actions next state
190  }
191  break;
192  case State::toEndPoint:
193  if (Event::PosEndPointReached == e) {
194  exitAction_toEndPoint(); // Exit-action current state
195  entryAction_endPoint(); // Entry-actions next state
196  } else if (Event::Error == e) {
197  exitAction_toEndPoint(); // Exit-action current state
198  entryAction_errorState(); // Entry-actions next state
199  }
200  break;
201  case State::errorState:
202  if (Event::Resume == e) {
203  exitAction_errorState(); // Exit-action current state
204  pDriveCtrl.loop(DriveCtrl::Event::Resume); //Pass Event to DriveCtrl
205  switch (lastStateBevorError) {
206  case State::endPoint:
207  entryAction_endPoint(); // Entry-actions next state
208  break;
209  case State::toGateway:
210  entryAction_toGateway(); // Entry-actions next state
211  break;
212  case State::gateway:
213  entryAction_gateway(); // Entry-actions next state
214  break;
215  case State::crossTransit:
216  entryAction_crossTransit(); // Entry-actions next state
217  break;
218  default:
219  break;
220  }
221  }
222  if (Event::Reset == e) {
223  exitAction_errorState(); // Exit-action current state
224  pDriveCtrl.loop(DriveCtrl::Event::Reset); // Pass Event to DriveCtrl
225  entryAction_resetState(); // Entry-actions next state
226  }
227  break;
228  case State::resetState:
229  if (Event::Resume == e) {
230  exitAction_resetState(); // Exit-action current state
231  pDriveCtrl.loop(DriveCtrl::Event::Resume); // Pass Event to DriveCtrl
232  entryAction_endPoint(); // Entry-actions next state
233  }
234  break;
235  default:
236  break;
237  }
238 }
239 //==endPoint==========================================================
241  DBSTATUSln("Navigation Entering State: endPoint");
242  currentState = State::endPoint; // state transition
244  //Entry-Action
249  }
250 
253  DBPOSln(decodeSector(pActual.sector) + String(" Line: ") + String(pActual.line));
254 }
255 
257  DBINFO1ln("Navigation State: endPoint");
258  //Generate the Event
259  return Event::NoEvent;
260 }
261 
263  DBSTATUSln("Navigation Leaving State: endPoint");
265 }
266 
267 //==toGateway==========================================================
269  DBSTATUSln("Navigation Entering State: toGateway");
270  currentState = State::toGateway; // state transition
272  //Entry-Action
273  //Update position
278  }
279  DBPOSln(decodeSector(pActual.sector) + String(" Line: ") + String(pActual.line));
280 }
281 
283  DBINFO1ln("Navigation State: toGateway");
284  //Generate the Event
285  switch (pCurrentSubState) {
286  case 0: //drive Backwards
287  pDriveCtrl.loop(DriveCtrl::Event::FollowLineBackward);
288  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
289  pCurrentSubState += 10;
290  }
291  break;
292  case 10: // turn Around
293  pDriveCtrl.loop(DriveCtrl::Event::TurnAround);
294  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
295  pCurrentSubState += 10;
296  }
297  break;
298  case 20: // drive forward once
299  pDriveCtrl.loop(DriveCtrl::Event::FollowLineForward);
300  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
301  pCurrentSubState = 0;
302  return Event::PosReached;
303  }
304  break;
305  default:
306  DBINFO1ln("Error. No matching State");
307  break;
308  }
309  return Event::NoEvent;
310 }
311 
313  DBSTATUSln("Navigation Leaving State: toGateway");
315 }
316 
317 //==gateway==========================================================
319  DBSTATUSln("Navigation Entering State: gateway");
320  currentState = State::gateway; // state transition
322  //Entry-Action
327  }
328  DBPOSln(decodeSector(pActual.sector) + String(" Line: ") + String(pActual.line));
329 }
330 
335  DBINFO2ln("Navigation State: gateway " + String(pCurrentSubState));
336  //Generate Event
337  switch (pCurrentSubState) {
338  case 0: // wait for Token
339  DBINFO2ln("Substate: WaitForToken");
340  DBINFO2ln("Token: " + String(pActual.token));
341  DBINFO2ln("Sector: " + decodeSector(pActual.sector));
342  if (pActual.token) {
343  //Update position
344  pActual.token = false;
348  pCurrentSubState = 10; //call next case
351  pCurrentSubState = 10; //call next case
354  pCurrentSubState = 10; //call next case
357  pCurrentSubState = 10; //call next case
358  }
359  DBPOSln(decodeSector(pActual.sector) + String(" Line: ") + String(pActual.line));
360  }
361  break;
362  case 10: // drive forward
363  DBINFO2ln("Substate: drive forward once");
364  pDriveCtrl.loop(DriveCtrl::Event::FollowLineForward);
365  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
366  pCurrentSubState = 20; //call next case
367  }
368  break;
369  case 20: // turn left/right depending on target and current orientation
370  DBINFO2ln("Substate: turn left or right");
371  if (pActual.line == pTarget.line) {
372  pSubStateLoopInc = 0; //reset back to zero
373  pCurrentSubState = 50; // jump direct to last substate -> driveForwardTwice
374  break;
375  }
376 
377  if (((pActual.line < pTarget.line) && (pActual.startSector != Sector::SorticHandover)) || //nach unten und von rechts
378  ((pActual.line > pTarget.line) && (pActual.startSector != Sector::TransferHandover))) { //nach oben und von links
379  pLastGatewayTurn = DriveCtrl::Event::TurnLeft;
381  } else if (((pActual.line > pTarget.line) && (pActual.startSector != Sector::SorticHandover)) || //nach oben und von rechts
382  ((pActual.line < pTarget.line) && (pActual.startSector != Sector::TransferHandover))) { //nach unten und von links
383  pLastGatewayTurn = DriveCtrl::Event::TurnRight;
385  }
386  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
387  pSubStateLoopInc = 0; //reset back to zero
388  pCurrentSubState = 30; //call next case
389  }
390  break;
391  case 30: // drive forward n times
392  DBINFO2("Substate: drive forward times: ");
395  pDriveCtrl.loop(DriveCtrl::Event::FollowLineForward);
396  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
397  pSubStateLoopInc += 1;
398  if (abs(pTarget.line - pActual.line) <= pSubStateLoopInc) {
399  pSubStateLoopInc = 0; //reset back to zero
400  pCurrentSubState = 40; //call next case
401  pActual.line = pTarget.line; //update actual line
402  }
403  }
404  break;
405  case 40: // turn left/right depending on target and current orientation
406  DBINFO2ln("Substate: turn left or right");
409  } else {
410  if (pLastGatewayTurn == DriveCtrl::Event::TurnLeft) {
411  pDriveCtrl.loop(DriveCtrl::Event::TurnRight);
412  } else {
413  pDriveCtrl.loop(DriveCtrl::Event::TurnLeft);
414  }
415  }
416  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
417  pCurrentSubState = 50; //call next case
418  }
419  break;
420  case 50: // drive forward twice
421  DBINFO2ln("Substate: drive forward twice");
422  pDriveCtrl.loop(DriveCtrl::Event::FollowLineForward);
423  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
424  pSubStateLoopInc += 1;
425  if (pSubStateLoopInc >= 2) {
426  pSubStateLoopInc = 0; //reset back to zero
427  // pSubStateLoopInc+= 10;
428  pCurrentSubState = 50;
429  pActual.token = false; //release token
430  DBPOSln(String("pTarget.sector: ") + decodeSector(pTarget.sector) + String(" pActual.startSector: ") + decodeSector(pActual.startSector));
432  tranistonce = false;
433  pCurrentSubState = 0;
435  } else {
436  pCurrentSubState = 0;
437  tranistonce = true;
439  }
440  }
441  }
442  break;
443  default:
444  DBINFO1ln("Error. No matching State");
445  break;
446  }
447  return Event::NoEvent;
448 }
449 
451  DBSTATUSln("Navigation Leaving State: gateway");
452  DBPOSln(String("lastSector: ") + decodeSector(pActual.lastSector) + String(" Actual: ") + decodeSector(pActual.sector));
453  DBPOSln(String("targetSector: ") + decodeSector(pTarget.sector));
455  // if ((pActual.lastSector == Sector::SorticGateway) &&
456  // (pTarget.sector == Sector::TransferHandover)) {
457  // pActual.sector = Sector::TransitToTransfer;
458  // } else if ((pActual.lastSector == Sector::TransferGateway) &&
459  // (pTarget.sector == Sector::TransferHandover)) {
460  // pActual.sector = Sector::TransferToHandover;
461  // } else if ((pActual.lastSector == Sector::SorticGateway) &&
462  // (pTarget.sector == Sector::SorticHandover)) {
463  // pActual.sector = Sector::SorticToHandover;
464  // } else if ((pActual.lastSector == Sector::TransferGateway) &&
465  // (pTarget.sector == Sector::SorticToHandover)) {
466  // pActual.sector = Sector::TransitToSortic;
467  // }
468  DBPOSln(String("lastSector: ") + decodeSector(pActual.lastSector) + String(" Actual: ") + decodeSector(pActual.sector));
469 }
470 
471 //==crossTransit==========================================================
473  DBSTATUSln("Navigation Entering State: crossTransit");
474  currentState = State::crossTransit; // state transition
476  //Entry-Action
477  DBPOSln(decodeSector(pActual.sector) + String(" Line: ") + String(pActual.line));
483  DBPOSln(decodeSector(pActual.sector) + String(" Line: ") + String(pActual.line));
484  }
485 }
486 
488  DBINFO1ln("Navigation State: crossTransit");
489  //Generate the Event
490  pDriveCtrl.loop(DriveCtrl::Event::FollowLineForward);
491  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
493  pSubStateLoopInc += 1;
494  if (pSubStateLoopInc >= 3) {
495  pSubStateLoopInc = 0; //reset back to zero
496  pCurrentSubState = 0;
497  return Event::PosReached;
498  }
499  }
500  return Event::NoEvent;
501 }
502 
504  DBSTATUSln("Navigation Leaving State: crossTransit");
506 }
507 
508 //==toEndPoint==========================================================
510  DBSTATUSln("Navigation Entering State: toEndPoint");
511  currentState = State::toEndPoint; // state transition
513  //Entry-Action
514  DBPOSln(decodeSector(pActual.sector) + String(" Line: ") + String(pActual.line));
520  }
521  DBPOSln(decodeSector(pActual.sector) + String(" Line: ") + String(pActual.line));
522 }
523 
525  DBINFO1ln("Navigation State: toEndPoint");
526  //Generate the Event
527  pDriveCtrl.loop(DriveCtrl::Event::FollowLineForward);
528  if (pDriveCtrl.getcurrentState() == DriveCtrl::State::idle) {
529  pSubStateLoopInc += 1;
530  if (pSubStateLoopInc >= 1) {
531  pSubStateLoopInc = 0; //reset back to zero
532  pCurrentSubState = 0;
534  }
535  }
536  return Event::NoEvent;
537 }
538 
540  DBSTATUSln("Navigation Leaving State: toEndPoint");
542 }
543 
544 //==errorState========================================================
546  DBSTATUSln("Navigation Entering State: errorState");
549  currentState = State::errorState; // state transition
551  //Entry-Action
552  pDriveCtrl.loop(DriveCtrl::Event::Error);
553 }
554 
556  DBINFO1ln("Navigation State: errorState");
557  //Generate the Event
558  return Event::NoEvent;
559 }
560 
562  DBSTATUSln("Navigation Leaving State: errorState");
563 }
564 
565 //==resetState========================================================
567  DBERROR("Entering State: resetState");
568  currentState = State::resetState; // state transition
570 }
571 
573  DBINFO1ln("State: resetState");
574  //Generate the Event
575  return Event::NoEvent;
576 }
577 
579  DBSTATUSln("Leaving State: resetState");
580  pActual = {}; //reset struct
581  pTarget = {}; //reset struct
582  tranistonce = true;
583  pCurrentSubState = 0;
585  pSubStateLoopInc = 0;
586 }
587 
588 //============================================================================
589 //==Aux-Function==============================================================
591  switch (state) {
592  case State::endPoint:
593  return "State::endPoint";
594  break;
595  case State::toGateway:
596  return "State::toGateway";
597  case State::gateway:
598  return "State::gateway";
599  break;
600  case State::crossTransit:
601  return "State::crossTransit";
602  break;
603  case State::toEndPoint:
604  return "State::toEndPoint";
605  break;
606  case State::errorState:
607  return "State::errorState";
608  break;
609  case State::resetState:
610  return "State::resetState";
611  break;
612  default:
613  return "ERROR: No matching state";
614  break;
615  }
616 }
617 
619  switch (event) {
621  return "Event::MoveToTargetPosition";
622  break;
624  return "Event::PosEndPointReached";
625  break;
627  return "Event::PosTransitReached";
628  break;
629  case Event::PosReached:
630  return "Event::PosReached";
631  break;
632  case Event::Error:
633  return "Event::Error";
634  break;
635  case Event::Resume:
636  return "Event::Resume";
637  break;
638  case Event::Reset:
639  return "Event::Reset";
640  break;
641  case Event::NoEvent:
642  return "Event::NoEvent";
643  break;
644  default:
645  return "ERROR: No matching event";
646  break;
647  }
648 }
#define DBEVENTln(x)
void entryAction_endPoint()
executes the entry action of the endPoint state.
const Sector getcurrentSector()
Get the current Sector.
Sector startSector
Startpoint from current path.
NavigationCtrl::Event doAction_toEndPoint()
executes the main action of the toEndPoint state.
int pCurrentSubState
Counter for the Current Substate.
#define DBINFO1ln(x)
void exitAction_resetState()
exit action of the resetState
void exitAction_endPoint()
executes the exit action of the endPoint state.
void entryAction_errorState()
entry action of the errorState state.
NavigationCtrl::Event doAction_toGateway()
executes the main action of the toGateway state.
Ext.: Reset after Error occured.
NavigationCtrl::Event doAction_errorState()
main action of the errorState state.
DriveCtrl pDriveCtrl
Navigation Object.
void giveToken()
give Token to access the Gateway
State lastStateBevorError
holds the last state of the FSM so it's possible to resume after error
int pLastSubStateBevorError
Holds the last Substate befor an Error occured.
NavigationCtrl()
Construct a new Navigation Ctrl object and initailize the currentState with endPoint state.
Ext: Resume after Error occured.
#define DBINFO2ln(x)
void entryAction_resetState()
entry action of the resetState
Ext: Start MoveToTargetPosition.
String decodeEvent(Event event)
Decodes the Event-Enum and returns a description.
NavigationCtrl::Event doAction_gateway()
executes the main action of the gateway state.
void exitAction_gateway()
executes the exit action of the gateway state.
State currentState
holds the current state of the FSM
void setTargetPosition(Sector sector, const int line)
Set the Target Position object.
Sector sector
actual sector
Transit - Wait for Gateway Transfer.
void exitAction_toGateway()
executes the exit action of the toGateway state.
Event(NavigationCtrl::* doActionFPtr)(void)
Functionpointer to call the current states do-function.
Sector lastSector
last sector
NavigationCtrl::Event doAction_endPoint()
executes the main action of the endPoint state. This is an Idel-state ->NoEvent generated
void loop()
Calls the do-function of the active state and hence generates Events.
bool token
token for gateway accees
NavigationCtrl::Event doAction_resetState()
main action of the resetState
struct NavigationCtrl::ActualPos pActual
NavigationCtrl::Event doAction_crossTransit()
executes the main action of the crossTransit state.
const State getcurrentState()
Get the current State.
void entryAction_gateway()
executes the entry action of the gateway state.
void process(Event e)
changes the state of the FSM based on the event
Contains the FSM for the Navigation.
String decodeState(State state)
Decodes the State-Enum and returns a description.
Event
Enum holds all possible events.
Parking (not used atm)
State
Enum holds all possible states for the Navigation.
Signal: Position reached.
void exitAction_crossTransit()
executes the exit action of the crossTransit state.
#define DBERROR(x)
Event currentEvent
holds the current event of the FSM
void exitAction_errorState()
exit action of the errorState state.
The Navigation Controll class contains the FSM for the Navigation.
#define DBINFO2(x)
#define DBPOSln(x)
#define DBFUNCCALLln(x)
#define DBSTATUSln(x)
String decodeSector(Sector sector)
Decodes the Sector-Enum and returns a description.
void entryAction_toGateway()
executes the entry action of the toGateway state.
Transit - Wait for Gateway Sortic.
#define DBFUNCCALL(x)
error for unknown sector
const int getcurrentLine()
Get the current Line.
int pSubStateLoopInc
Counter so you can call the same substatefunction multiple times.
struct NavigationCtrl::TargetPos pTarget
void setActualPosition(Sector sector, const int line)
Set the actual Position object.
void entryAction_toEndPoint()
executes the entry action of the toEndPoint state.
void exitAction_toEndPoint()
executes the exit action of the toEndPoint state.
DriveCtrl::Event pLastGatewayTurn
Variable which holds the last made turn in gateway.
void entryAction_crossTransit()
executes the entry action of the crossTransit state.
bool tranistonce
prevents an loop between transit and gateway
Sector sector
TargetSector.
Sector
Enum holds all possible sectors.