SmartVehicle-Basis
SmartFactory
DriveCtrl.cpp
Go to the documentation of this file.
1 
15 #include "DriveCtrl.h"
16 //=====PUBLIC====================================================================================
17 DriveCtrl::DriveCtrl() : currentState(State::idle), doActionFPtr(&DriveCtrl::doAction_idle) {
18  pController.SetTunings(pVal_p, pVal_i, pVal_d);
19  pController.SetOutputLimits(-255, 255);
20  pController.SetSampleTime(pSampleTime); // Sampletime in milliseconds
21  pController.SetMode(AUTOMATIC);
22  pController.SetControllerDirection(DIRECT);
23  DBINFO2ln(String("Kp: ") + String(pController.GetKp()) + String(" Ki: ") + String(pController.GetKi()) + String(" Kd: ") + String(pController.GetKd()));
24 }
25 
27  DBFUNCCALLln("DriveCtrl::loop()");
28  process((this->*doActionFPtr)()); //do actions
29 }
30 
31 void DriveCtrl::loop(Event currentEvent) {
32  DBFUNCCALLln("DriveCtrl::loop(Event)");
34  process((this->*doActionFPtr)()); //do actions
35 }
36 
38  return currentState;
39 }
40 //=====PRIVATE====================================================================================
42  DBFUNCCALL("DriveCtrl::process ");
43  DBEVENTln(String("DriveCtrl ") + String(decodeEvent(e)));
44  switch (currentState) {
45  case State::idle:
46  if (Event::TurnLeft == e) {
47  exitAction_idle(); // Exit-action current state
48  entryAction_turningLeft(); // Entry-actions next state
49  } else if (Event::TurnLeft == e) {
50  exitAction_idle(); // Exit-action current state
51  entryAction_turningLeft(); // Entry-actions next state
52  } else if (Event::TurnRight == e) {
53  exitAction_idle(); // Exit-action current state
54  entryAction_turningRight(); // Entry-actions next state
55  } else if (Event::TurnAround == e) {
56  exitAction_idle(); // Exit-action current state
57  entryAction_turningAround(); // Entry-actions next state
58  } else if (Event::FollowLineForward == e) {
59  exitAction_idle(); // Exit-action current state
60  entryAction_followingLineForward(); // Entry-actions next state
61  } else if (Event::FollowLineBackward == e) {
62  exitAction_idle(); // Exit-action current state
63  entryAction_followingLineBackward(); // Entry-actions next state
64  } else if (Event::Error == e) {
65  exitAction_idle(); // Exit-action current state
66  entryAction_errorState(); // Entry-actions next state
67  }
68  break;
69  case State::turningLeft:
70  if (Event::LineAligned == e) {
71  exitAction_turningLeft(); // Exit-action current state
72  entryAction_idle(); // Entry-actions next state
73  } else if (Event::Error == e) {
74  exitAction_turningLeft(); // Exit-action current state
75  entryAction_errorState(); // Entry-actions next state
76  }
77  break;
79  if (Event::LineAligned == e) {
80  exitAction_turningRight(); // Exit-action current state
81  entryAction_idle(); // Entry-actions next state
82  } else if (Event::Error == e) {
83  exitAction_turningRight(); // Exit-action current state
84  entryAction_errorState(); // Entry-actions next state
85  }
86  break;
88  if (Event::LineAligned == e) {
89  exitAction_turningAround(); // Exit-action current state
90  entryAction_idle(); // Entry-actions next state
91  } else if (Event::Error == e) {
92  exitAction_turningAround(); // Exit-action current state
93  entryAction_errorState(); // Entry-actions next state
94  }
95  break;
97  if (Event::FullLineDetected == e) {
98  exitAction_followingLineForward(); // Exit-action current state
99  entryAction_idle(); // Entry-actions next state
100  } else if (Event::Error == e) {
101  exitAction_followingLineForward(); // Exit-action current state
102  entryAction_errorState(); // Entry-actions next state
103  }
104  break;
106  if (Event::FullLineDetected == e) {
107  exitAction_followingLineBackward(); // Exit-action current state
108  entryAction_idle(); // Entry-actions next state
109  } else if (Event::Error == e) {
110  exitAction_followingLineBackward(); // Exit-action current state
111  entryAction_errorState(); // Entry-actions next state
112  }
113  break;
114  case State::errorState:
115  if (Event::Resume == e) {
116  exitAction_errorState(); // Exit-action current state
117  switch (lastStateBevorError) {
118  case State::idle:
119  entryAction_idle(); // Entry-actions next state
120  break;
121  case State::turningLeft:
122  entryAction_turningLeft(); // Entry-actions next state
123  break;
124  case State::turningRight:
125  entryAction_turningRight(); // Entry-actions next state
126  break;
128  entryAction_turningAround(); // Entry-actions next state
129  break;
131  entryAction_followingLineForward(); // Entry-actions next state
132  break;
134  entryAction_followingLineBackward(); // Entry-actions next state
135  break;
136  default:
137  break;
138  }
139  }
140  if (Event::Reset == e) {
141  exitAction_errorState(); // Exit-action current state
142  entryAction_resetState(); // Entry-actions next state
143  }
144  break;
145  case State::resetState:
146  if (Event::Resume == e) {
147  exitAction_resetState(); // Exit-action current state
148  entryAction_idle(); // Entry-actions next state
149  }
150  break;
151  default:
152  break;
153  }
154 }
155 //==idle==========================================================
157  DBSTATUSln("Drive Entering State: idle");
158  currentState = State::idle; // state transition
160  //Entry-Action
161 }
162 
164  DBINFO1ln("Drive State: idle");
165  //Generate the Event
166  return Event::NoEvent;
167 }
168 
170  DBSTATUSln("Drive Leaving State: idle");
171 }
172 
173 //==turningLeft==========================================================
175  DBSTATUSln("Drive Entering State: turningLeft");
176  currentState = State::turningLeft; // state transition
178  previousMillis = millis();
179  currentMillis = millis();
180  //Entry-Action
182 }
183 
185  DBINFO1ln("Drive State: turningLeft");
186  //Generate the Event
187  currentMillis = millis();
189  return Event::LineAligned;
190  }
191  return Event::NoEvent;
192 }
193 
195  DBSTATUSln("Drive Leaving State: turningLeft");
196  pDrive.stop();
197 }
198 
199 //==turningRight==========================================================
201  DBSTATUSln("Drive Entering State: turningRight");
202  currentState = State::turningRight; // state transition
204  previousMillis = millis();
205  currentMillis = millis();
206  //Entry-Action
208 }
209 
211  DBINFO1ln("Drive State: turningRight");
212  //Generate Event
213  currentMillis = millis();
215  return Event::LineAligned;
216  }
217  return Event::NoEvent;
218 }
219 
221  DBSTATUSln("Drive Leaving State: turningRight");
222  pDrive.stop();
223 }
224 
225 //==turningAround==========================================================
227  DBSTATUSln("Drive Entering State: turningAround");
228  currentState = State::turningAround; // state transition
230  previousMillis = millis();
231  currentMillis = millis();
232  //Entry-Action
233  // pDrive.turnonpoint(Drive::Direction::Right, TURNING_SPEED);
235 }
236 
238  DBINFO1ln("Drive State: turningAround");
239  //Generate the Event
240  int linedev = pEnvdetect.Linedeviation();
241  DBINFO2ln(linedev);
242  DBINFO2ln(abs(linedev));
243  currentMillis = millis();
244  if ((abs(linedev) < 2) && ((currentMillis - previousMillis) > ignoreSensorAroundMillis)) {
245  return Event::LineAligned;
246  }
247  return Event::NoEvent;
248 }
249 
251  DBSTATUSln("Drive Leaving State: turningAround");
252  pDrive.stop();
253 }
254 
255 //==followingLineForward==========================================================
257  DBSTATUSln("Drive Entering State: followingLineForward");
258  currentState = State::followingLineForward; // state transition
260  previousMillis = millis();
261  currentMillis = millis();
262  pController_Input = 0;
263  //Entry-Action
265 }
266 
268  DBINFO1ln("Drive State: followingLineForward");
269  //Generate the Event
270  // DBINFO3ln(pEnvdetect.Linedeviation());
271  int linedeviation = pEnvdetect.Linedeviation();
272  currentMillis = millis();
273  if ((abs(linedeviation) == 180) && ((currentMillis - previousMillis) > ignoreSensorTurnMillis)) {
275  } else if ((abs(linedeviation) == 200)) {
276  //Line lost
277  // return Event::FullLineDetected;
278  }
279  if ((linedeviation != 180) && (linedeviation != 200)) {
280  pController_Input = linedeviation;
281  }
282  DBINFO2ln(String("Controll-Input: ") + String(pController_Input));
283  pController.Compute();
284  DBINFO2ln(String("Controll-Correction: ") + String(pController_Output));
285  if (pController_Output > 0) {
287  } else if (pController_Output < 0) {
289  }
290 
291  return Event::NoEvent;
292 }
293 
295  DBSTATUSln("Drive Leaving State: followingLineForward");
296  pDrive.stop();
297 }
298 
299 //==followingLineBackward==========================================================
301  DBSTATUSln("Drive Entering State: followingLineBackward");
302  currentState = State::followingLineBackward; // state transition
304  previousMillis = millis();
305  currentMillis = millis();
306  pController_Input = 0;
307  //Entry-Action
308  // pController.SetControllerDirection(REVERSE);
309  // pController.SetTunings(1, 0, 0.01);
311  pDrive.turn(Drive::Direction::Right, 4); //correct motor power diffrence
312 }
313 
315  DBINFO1ln("Drive State: followingLineBackward");
316  //Generate the Event
317  // DBINFO3ln(pEnvdetect.Linedeviation());
318  int linedeviation = pEnvdetect.Linedeviation();
319  currentMillis = millis();
320  if ((abs(linedeviation) == 180) && ((currentMillis - previousMillis) > ignoreSensorTurnMillis)) {
322  }
323 
324  // } else if ((abs(linedeviation) == 200)) {
325  // //Line lost
326  // // return Event::FullLineDetected;
327  // }.
328  // if ((linedeviation != 180) && (linedeviation != 200)) {
329  // pController_Input = linedeviation;
330  // }
331  // DBINFO2ln(String("Controll-Input: ") + String(pController_Input));
332  // pController.Compute();
333  // DBINFO2ln(String("Controll-Correction: ") + String(pController_Output));
334  // if (pController_Output > 0) {
335  // pDrive.turn(Drive::Direction::Left, abs(pController_Output));
336  // } else if (pController_Output < 0) {
337  // pDrive.turn(Drive::Direction::Right, abs(pController_Output));
338  // }
339 
340  return Event::NoEvent;
341 }
342 
344  DBSTATUSln("Drive Leaving State: followingLineBackward");
345  pDrive.stop();
346  // pController.SetTunings(pVal_p, pVal_i, pVal_d);
347  // pController.SetControllerDirection(DIRECT);
348 }
349 
350 //==errorState========================================================
352  DBERROR("Drive Entering State: errorState");
354  currentState = State::errorState; // state transition
356  //Entry-Action
357  pDrive.stop();
358 }
359 
361  DBSTATUSln("Drive State: errorState");
362  //Generate the Event
363  return Event::NoEvent;
364 }
365 
367  DBSTATUSln("Drive Leaving State: errorState");
368 }
369 
370 //==resetState========================================================
372  DBERROR("Entering State: resetState");
373  currentState = State::resetState; // state transition
375 }
376 
378  DBINFO1ln("State: resetState");
379  //Generate the Event
380  return Event::NoEvent;
381 }
382 
384  DBSTATUSln("Leaving State: resetState");
385 }
386 
387 //============================================================================
388 //==Aux-Function==============================================================
390  switch (state) {
391  case State::idle:
392  return "State::idle";
393  break;
394  case State::turningLeft:
395  return "State::turningLeft";
396  case State::turningRight:
397  return "State::turningRight";
398  break;
400  return "State::turningAround";
401  break;
402  case State::errorState:
403  return "State::errorState";
404  break;
405  case State::resetState:
406  return "State::resetState";
407  break;
408  default:
409  return "ERROR: No matching state";
410  break;
411  }
412 }
413 
415  switch (event) {
416  case Event::TurnLeft:
417  return "Event::TurnLeft";
418  break;
419  case Event::TurnRight:
420  return "Event::TurnRight";
421  break;
422  case Event::TurnAround:
423  return "Event::TurnAround";
424  break;
426  return "Event::FollowLineForward";
427  break;
429  return "Event::FollowLineBackward";
430  break;
431  case Event::LineAligned:
432  return "Event::LineAligned";
433  break;
435  return "Event::FullLineDetected";
436  break;
437  case Event::Error:
438  return "Event::Error";
439  break;
440  case Event::Resume:
441  return "Event::Resume";
442  break;
443  case Event::Reset:
444  return "Event::Reset";
445  break;
446  case Event::NoEvent:
447  return "Event::NoEvent";
448  break;
449  default:
450  return "ERROR: No matching event";
451  break;
452  }
453 }
const unsigned int REDUCED_SPEED
Reduced operating speed.
void exitAction_followingLineForward()
executes the exit action of the followingLineForward
Definition: DriveCtrl.cpp:294
Contains the FSM to controll the Drive.
Definition: DriveCtrl.h:32
follow the line while driving forward state
const State getcurrentState()
Get the current State.
Definition: DriveCtrl.cpp:37
const unsigned int SPEED
Standard operating speed.
DriveCtrl::Event doAction_errorState()
main action of the errorState
Definition: DriveCtrl.cpp:360
void entryAction_idle()
executes the entry action of the idle
Definition: DriveCtrl.cpp:156
DriveCtrl::Event doAction_turningAround()
executes the main action of the turningAround
Definition: DriveCtrl.cpp:237
void entryAction_turningLeft()
executes the entry action of the turningLeft
Definition: DriveCtrl.cpp:174
Ext.: Error occured.
unsigned long currentMillis
will store current time
Definition: DriveCtrl.h:106
The Drive Controll class contains the FSM for the Drive.
Ext.: Reset after Error occured.
Ext.: Follow the line backwards.
PID pController
PID-Controller Object.
Definition: DriveCtrl.h:131
No event generated.
double pController_Output
Controller Output.
Definition: DriveCtrl.h:112
Drive pDrive
Drive Object.
Definition: DriveCtrl.h:132
EnvironmentDetection pEnvdetect
EnviromentDetection Object.
Definition: DriveCtrl.h:133
const unsigned long ignoreSensorTurnMillis
sets how long the sensors are ignored for a turn
Definition: DriveCtrl.h:108
void exitAction_turningLeft()
executes the exit action of the turningLeft
Definition: DriveCtrl.cpp:194
Event currentEvent
holds the current event of the FSM
Definition: DriveCtrl.h:97
double pVal_d
D-Value (independet of SamplingTime)
Definition: DriveCtrl.h:117
void drive(Direction direction, unsigned int speed)
Drive straight Forwards or Backwards.
Definition: Drive.cpp:29
State lastStateBevorError
holds the last state of the FSM so it's possible to resume after error
Definition: DriveCtrl.h:95
Ext.: Follow the line forwards.
void exitAction_idle()
executes the exit action of the idle
Definition: DriveCtrl.cpp:169
State currentState
holds the current state of the FSM
Definition: DriveCtrl.h:96
void process(Event e)
changes the state of the FSM based on the event
Definition: DriveCtrl.cpp:41
DriveCtrl::Event doAction_turningRight()
executes the main action of the turningRight
Definition: DriveCtrl.cpp:210
void exitAction_resetState()
exit action of the resetState
Definition: DriveCtrl.cpp:383
Event(DriveCtrl::* doActionFPtr)(void)
Functionpointer to call the current states do-function.
Definition: DriveCtrl.h:104
DriveCtrl::Event doAction_followingLineBackward()
executes the main action of the followingLineBackward
Definition: DriveCtrl.cpp:314
void entryAction_turningRight()
executes the entry action of the turningRight
Definition: DriveCtrl.cpp:200
void exitAction_turningAround()
executes the exit action of the turningAround
Definition: DriveCtrl.cpp:250
DriveCtrl::Event doAction_turningLeft()
executes the main action of the turningLeft
Definition: DriveCtrl.cpp:184
follow the line while driving backward state
Signal: Full line detected.
String decodeState(State state)
Decodes the State-Enum and returns a description.
Definition: DriveCtrl.cpp:389
String decodeEvent(Event event)
Decodes the Event-Enum and returns a description.
Definition: DriveCtrl.cpp:414
Signal: Line is alligned in the middle of the vehicle.
DriveCtrl::Event doAction_idle()
executes the main action of the idle
Definition: DriveCtrl.cpp:163
void stop()
Power of the Motor. Does not apply breaking.
Definition: Drive.cpp:110
double pVal_i
I-Value (independet of SamplingTime)
Definition: DriveCtrl.h:116
State
Enum holds all possible states.
Definition: DriveCtrl.h:56
double pVal_p
P-Value.
Definition: DriveCtrl.h:115
const int Linedeviation()
Recognise deviation from vehicle to line.
void turn(Direction direction, unsigned int speed)
Turn left or right. Speed will add to one Motor's actual speed and substract from the others depenig ...
Definition: Drive.cpp:53
int pSampleTime
Controler SampleTime in ms.
Definition: DriveCtrl.h:114
void entryAction_errorState()
entry action of the errorState
Definition: DriveCtrl.cpp:351
void entryAction_followingLineForward()
executes the entry action of the followingLineForward
Definition: DriveCtrl.cpp:256
double pController_Input
Controller Input.
Definition: DriveCtrl.h:111
const unsigned long ignoreSensorAroundMillis
sets how long the sensors are ignored for a turning around
Definition: DriveCtrl.h:109
DriveCtrl::Event doAction_followingLineForward()
executes the main action of the followingLineForward
Definition: DriveCtrl.cpp:267
void exitAction_followingLineBackward()
executes the exit action of the followingLineBackward
Definition: DriveCtrl.cpp:343
Event
Enum holds all possible events.
Definition: DriveCtrl.h:39
const unsigned int TURNING_SPEED
Turning speed.
void entryAction_followingLineBackward()
executes the entry action of the followingLineBackward
Definition: DriveCtrl.cpp:300
DriveCtrl::Event doAction_resetState()
main action of the resetState
Definition: DriveCtrl.cpp:377
Ext.: Turn around on position.
void loop()
Calls the do-function of the active state and hence generates Events.
Definition: DriveCtrl.cpp:26
void turnonpoint(Direction direction, unsigned int speed)
Turn on Point Drive on Motor Forward and the other Backward with the given speed.
Definition: Drive.cpp:87
void exitAction_turningRight()
executes the exit action of the turningRight
Definition: DriveCtrl.cpp:220
void entryAction_resetState()
entry action of the resetState
Definition: DriveCtrl.cpp:371
void exitAction_errorState()
exit action of the errorState
Definition: DriveCtrl.cpp:366
Ext.: Resume after Error occured.
unsigned long previousMillis
will store last time
Definition: DriveCtrl.h:107
DriveCtrl()
Construct a new Drive Ctrl object and set the currentState with idle state and initialize the PID-Con...
Definition: DriveCtrl.cpp:17
void entryAction_turningAround()
executes the entry action of the turningAround
Definition: DriveCtrl.cpp:226