RSeries astromech firmware
Stance.h
Go to the documentation of this file.
1 #ifndef Stance_h
2 #define Stance_h
3 
4 #include "ReelTwo.h"
5 #include "core/SetupEvent.h"
6 #include "core/AnimatedEvent.h"
7 #include "core/CommandEvent.h"
8 #include "Orientation.h"
9 #include "USBSabertooth_NB.h"
10 
11 #ifndef SABER_SERIAL
12  #ifdef HAVE_HWSERIAL2
13  #define SABER_SERIAL Serial2
14  #endif
15 #endif
16 
17 #define MOTOR_FULL_POWER 2047
18 #define TILT_MOTOR_FULL_POWER 2047
19 #define MOTOR_HALF_3QUARTERS 1400
20 #define MOTOR_HALF_POWER 1024
21 #define MOTOR_QUARTER_POWER 300
22 
23 #define YOKE_ANGLE_2LEGS_TARGET -13
24 #define YOKE_ANGLE_2LEGS_LIMIT -10 /* limit switch triggers at -10 */
25 
26 #define YOKE_ANGLE_3LEGS_TARGET 23
27 #define YOKE_ANGLE_2TO3LEGS_SLOWDOWN 20
28 
29 #define YOKE_ANGLE_CENTER_LEG_START -10
30 
35 {
36 public:
41  Stance( HardwareSerial& saberSerialPort,
42  byte tiltUpPin = 6,
43  byte tiltDownPin = 7,
44  byte legUpPin = 8,
45  byte legDownPin = 9,
46  byte legPotPin = A0,
47  byte saberAddress = 128) :
48  fSaberSerialInit(saberSerialPort),
49  fSaberSerial(saberSerialPort),
50  fST(fSaberSerial, saberAddress),
51  fTiltUpPin(tiltUpPin),
52  fTiltDownPin(tiltDownPin),
53  fLegUpPin(legUpPin),
54  fLegDownPin(legDownPin),
55  fLegPotPin(legPotPin)
56  {
57  for (unsigned i = 0; i < SizeOfArray(fLegPotReading); i++)
58  fLegPotReading[i] = 0;
59  }
60 
61  Stance( byte tiltUpPin = 6,
62  byte tiltDownPin = 7,
63  byte legUpPin = 8,
64  byte legDownPin = 9,
65  byte legPotPin = A0,
66  byte saberAddress = 128) :
67  Stance(SABER_SERIAL, tiltUpPin, tiltDownPin, legUpPin, legDownPin, legPotPin, saberAddress)
68  {
69  }
70 
72  {
73  fBodyIMU = &bodyIMU;
74  fTiltIMU = &tiltIMU;
75  }
76 
77  virtual void handleCommand(const char* cmd) override
78  {
79  if (strcmp(cmd, "TWOLEGS") == 0)
80  {
82  }
83  else if (strcmp(cmd, "THREELEGS") == 0)
84  {
86  }
87  }
88 
92  inline bool isTwoLegged()
93  {
94  return (fLegHappy == 0 && fTiltHappy == 0 && fStance == 1);
95  }
96 
100  inline bool isThreeLegged()
101  {
102  return (fLegHappy == 0 && fTiltHappy == 0 && fStance == 2);
103  }
104 
108  inline bool isValid()
109  {
110  return isTwoLegged() || isThreeLegged();
111  }
112 
117  {
118  fStanceTarget = 1;
119  }
120 
125  {
126  fStanceTarget = 2;
127  }
128 
132  virtual void setup() override
133  {
134  pinMode(fTiltUpPin, INPUT_PULLUP);
135  pinMode(fTiltDownPin, INPUT_PULLUP);
136  pinMode(fLegUpPin, INPUT_PULLUP);
137  pinMode(fLegDownPin, INPUT_PULLUP);
138  pinMode(fLegPotPin, INPUT);
139  DEBUG_PRINT("fTiltUpPin : "); DEBUG_PRINTLN(fTiltUpPin);
140  DEBUG_PRINT("fTiltDownPin : "); DEBUG_PRINTLN(fTiltDownPin);
141  DEBUG_PRINT("fLegUpPin : "); DEBUG_PRINTLN(fLegUpPin);
142  DEBUG_PRINT("fLegDownPin : "); DEBUG_PRINTLN(fLegDownPin);
143  DEBUG_PRINT("fLegPotPin : "); DEBUG_PRINTLN(fLegPotPin);
144  // fST.async_getBattery(1, 0); // start cycle by requesting battery voltage with context 0
145  }
146 
150  virtual void animate() override
151  {
152  // int result = 0;
153  // int context = 0;
154  uint32_t currentMillis = millis();
155 
156  // if (fSaberSerial.reply_available(&result, &context))
157  // {
158  // switch (context)
159  // {
160  // case SABERTOOTH_GET_ERROR: // Error or timeout
161  // case SABERTOOTH_GET_TIMED_OUT:
162  // fST.async_getBattery(1, 0); // reset the cycle by starting from the beginning
163  // break;
164 
165  // case 0: // Battery
166  // fBattery = result;
167  // fST.async_getCurrent(1, 1); // next request: get motor 1 current with context 1
168  // break;
169 
170  // case 1: // Current 1
171  // fCurrentChannel1 = result;
172  // fST.async_getCurrent(2, 2); // next request: get motor 2 current with context 2
173  // break;
174 
175  // case 2: // Current 2
176  // fCurrentChannel2 = result;
177  // fST.async_getBattery( 1, 0 ); // next request: get battery voltage with context 0
178  // break;
179  // }
180  // fLastStatusMillis = currentMillis;
181  // }
182  // if (currentMillis - fLastStatusMillis >= kMaxStatusInterval)
183  // {
184  // // Status has not been updated for kMaxStatusInterval milliseconds. Something is wrong.
185  // DEBUG_PRINTLN("Sabretooth not responding");
186  // }
187 
188  fLegDn = digitalRead(fLegDownPin);
189  fLegUp = digitalRead(fLegUpPin);
190  fTiltDn = digitalRead(fTiltDownPin);
191  fTiltUp = digitalRead(fTiltUpPin);
192  // Map leg pot position value to 0..100 (top..bottom)
193 
194  // subtract the last reading:
195  fLegPotTotal = fLegPotTotal - fLegPotReading[fLegPotIndex];
196  // read from the sensor:
197  fLegPotReading[fLegPotIndex] = analogRead(fLegPotPin);
198  // add the reading to the total:
199  fLegPotTotal = fLegPotTotal + fLegPotReading[fLegPotIndex++];
200  if (fLegPotIndex >= SizeOfArray(fLegPotReading))
201  {
202  fLegPotIndex = 0;
203  }
204  fLegPos = map(fLegPotTotal / SizeOfArray(fLegPotReading), 0, 1023, 0, 50);
205  if (fTiltDn == 0)
206  {
207  // when the tilt down switch opens, the timer starts
208  fShowTimeThreeToTwo = 0;
209  }
210  if (fTiltUp == 0)
211  {
212  // when the tilt down switch opens, the timer starts
213  fShowTimeTwoToThree = 0;
214  }
215  if (currentMillis - fLastDisplayMillis >= kDisplayInterval || lastMotor1 != 0 || lastMotor2 != 0 || fLegPos != fLegLastPos)
216  {
217  fLastDisplayMillis = currentMillis;
218  Display();
219  }
220  if (currentMillis - fLastStanceMillis >= kStanceInterval)
221  {
222  fLastStanceMillis = currentMillis;
223  CheckStance();
224  }
225  Move();
226  // advance fShowTimeThreeToTwo every 100ms.
227  if (currentMillis - fLastShowTimeMillis >= kShowTimeInterval)
228  {
229  fLastShowTimeMillis = currentMillis;
230  fShowTimeThreeToTwo++;
231  fShowTimeTwoToThree++;
232  }
233  fLegLastPos = fLegPos;
234  }
235 
236 private:
237  class USBSabertoothSerialInit
238  {
239  public:
240  USBSabertoothSerialInit(HardwareSerial& port)
241  {
242  // 9600 is the default baud rate for Sabertooth Packet Serial.
243  port.begin(9600);
244  }
245  };
246  USBSabertoothSerialInit fSaberSerialInit;
247  USBSabertoothSerial fSaberSerial;
248  USBSabertooth fST;
249 
250  byte fTiltUpPin;
251  byte fTiltDownPin;
252  byte fLegUpPin;
253  byte fLegDownPin;
254  byte fLegPotPin;
255 
256  int fTiltUp = 0;
257  int fTiltDn = 0;
258  int fLegUp = 0;
259  int fLegDn = 0;
260  int fStance = 0;
261  int fStanceTarget = 0;
262  int fLegHappy = 0;
263  int fTiltHappy = 0;
264  unsigned fLegPotIndex = 0;
265  int fLegPotReading[10];
266  int fLegPotTotal = 0;
267  int fLegPos = 0;
268  int fLegLastPos = -1;
269 
270  int fBattery = 0;
271  int fCurrentChannel1 = 0;
272  int fCurrentChannel2 = 0;
273 
274  Orientation* fBodyIMU = NULL;
275  Orientation* fTiltIMU = NULL;
276 
277  uint32_t fLastDisplayMillis = 0;
278  uint32_t fLastStanceMillis = 0;
279  uint32_t fLastShowTimeMillis = 0;
280  uint32_t fLastStatusMillis = 0;
281  uint32_t fShowTimeThreeToTwo = 0;
282  uint32_t fShowTimeTwoToThree = 0;
283 
284  static const int kDisplayInterval = 1000;
285  static const int kStanceInterval = 100;
286  static const int kShowTimeInterval = 100;
287  static const int kMaxStatusInterval = 5000;
288 
289  int lastMotor1 = -1;
290  int lastMotor2 = -1;
291 
292  void legMotorUp()
293  {
294  if (lastMotor1 != -MOTOR_FULL_POWER)
295  {
296  DEBUG_PRINTLN("LEG MOTOR UP");
297  lastMotor1 = -MOTOR_FULL_POWER;
298  }
299  fST.motor(1, -MOTOR_FULL_POWER); // Go reverse at full power
300  }
301 
302  void legMotorUpSlow()
303  {
304  if (lastMotor1 != -MOTOR_QUARTER_POWER)
305  {
306  DEBUG_PRINTLN("LEG MOTOR UP SLOW");
307  lastMotor1 = -MOTOR_QUARTER_POWER;
308  }
309  fST.motor(1, -MOTOR_QUARTER_POWER);
310  }
311 
312  void legMotorDown()
313  {
314  if (lastMotor1 != MOTOR_FULL_POWER)
315  {
316  DEBUG_PRINTLN("LEG MOTOR DOWN");
317  lastMotor1 = MOTOR_FULL_POWER;
318  }
319  fST.motor(1, MOTOR_FULL_POWER); // Go forward at full power
320  }
321 
322  void legMotorDownSlow()
323  {
324  if (lastMotor1 != MOTOR_HALF_POWER)
325  {
326  DEBUG_PRINTLN("LEG MOTOR DOWN SLOW");
327  lastMotor1 = MOTOR_HALF_POWER;
328  }
329  fST.motor(1, MOTOR_HALF_POWER); // Go forward at three quarters impulse
330  }
331 
332  void legMotorStop()
333  {
334  if (lastMotor1 != 0)
335  {
336  DEBUG_PRINTLN("LEG STOP");
337  lastMotor1 = 0;
338  }
339  fST.motor(1, 0); // Stop.
340  fLegHappy = 0;
341  }
342 
343  void tiltMotorUp()
344  {
345  if (lastMotor2 != -TILT_MOTOR_FULL_POWER)
346  {
347  DEBUG_PRINTLN("TILT MOTOR UP");
348  lastMotor2 = -TILT_MOTOR_FULL_POWER;
349  }
350  fST.motor(2, -TILT_MOTOR_FULL_POWER); // Go reverse at full power
351  }
352 
353  void tiltMotorDown()
354  {
355  if (lastMotor2 != TILT_MOTOR_FULL_POWER)
356  {
357  DEBUG_PRINTLN("TILT MOTOR DOWN");
358  lastMotor2 = TILT_MOTOR_FULL_POWER;
359  }
360  fST.motor(2, TILT_MOTOR_FULL_POWER); // Go forward at full power
361  }
362 
363  void tiltMotorDownSlow()
364  {
365  if (lastMotor2 != MOTOR_QUARTER_POWER)
366  {
367  DEBUG_PRINTLN("TILT MOTOR DOWN SLOW");
368  lastMotor2 = MOTOR_QUARTER_POWER;
369  }
370  fST.motor(2, MOTOR_QUARTER_POWER); // Go forward at quarter impulse
371  }
372 
373  void tiltMotorStop()
374  {
375  if (lastMotor2 != 0)
376  {
377  DEBUG_PRINTLN("TILT STOP");
378  lastMotor2 = 0;
379  }
380  fST.motor(2, 0); // Stop.
381  fTiltHappy = 0;
382  }
383 
384  void motorStopNow()
385  {
386  if (lastMotor1 != 0 || lastMotor2 != 0)
387  {
388  DEBUG_PRINTLN("STOP NOW");
389  }
390  legMotorStop();
391  tiltMotorStop();
392  }
393 
399  void MoveLegDn()
400  {
401  if (fLegDn == 0)
402  {
403  legMotorStop();
404  }
405  else if (fLegDn == 1)
406  {
407  legMotorDown();
408  }
409  }
410 
411  void MoveLegUp()
412  {
413  if (fLegUp == 0)
414  {
415  legMotorStop();
416  }
417  else if (fLegUp == 1)
418  {
419  legMotorUp();
420  }
421  }
422 
423  void MoveTiltDn()
424  {
425  if (fTiltDn == 0)
426  {
427  tiltMotorStop();
428  }
429  else if (fTiltDn == 1)
430  {
431  tiltMotorDown();
432  }
433  }
434 
435  void MoveTiltUp()
436  {
437  if (fTiltUp == 0)
438  {
439  tiltMotorStop();
440  }
441  else if (fTiltUp == 1)
442  {
443  tiltMotorUp();
444  }
445  }
446 
452  void CheckStance()
453  {
454  float yokeAnkle = getYokeAngle();
455  if (fLegHappy == 0 && fTiltHappy == 0)
456  {
457  if (fLegUp == 0 && fLegDn == 1 && fTiltUp == 0 && fTiltDn == 1)
458  {
459  // Two legged
460  fStance = 1;
461  }
462  if (fLegUp == 1 && fLegDn == 0 && fTiltUp == 1 && fTiltDn == 0)
463  {
464  // Three legged
465  fStance = 2;
466  }
467  if (fLegUp == 0 && fLegDn == 1 && fTiltUp == 1 && fTiltDn == 1)
468  {
469  fStance = 3;
470  }
471  if (fLegUp == 1 && fLegDn == 1 && fTiltUp == 0 && fTiltDn == 1)
472  {
473  fStance = 4;
474  }
475  if (fLegUp == 1 && fLegDn == 0 && fTiltUp == 0 && fTiltDn == 1)
476  {
477  fStance = 4;
478  }
479  if (fLegUp == 1 && fLegDn == 0 && fTiltUp == 1 && fTiltDn == 1)
480  {
481  fStance = 5;
482  }
483  if (fLegUp == 1 && fLegDn == 1 && fTiltUp == 1 && fTiltDn == 0)
484  {
485  fStance = 6;
486  }
487  if (fLegUp == 1 && fLegDn == 1 && fTiltUp == 1 && fTiltDn == 1)
488  {
489  fStance = 7;
490  }
491  }
492  }
493 
494  void Move()
495  {
496  // there is no stance target 0, so turn off your motors and do nothing.
497  if (fStanceTarget == 0)
498  {
499  motorStopNow();
500  return;
501  }
502  // if you are told to go where you are, then do nothing
503  if (fStanceTarget == fStance)
504  {
505  motorStopNow();
506  return;
507  }
508  // Stance 7 is bad, all 4 switches open, no idea where anything is. do nothing.
509  if (fStance == 7)
510  {
511  motorStopNow();
512  return;
513  }
514  // if you are in three legs and told to go to 2
515  if (fStanceTarget == 1 && fStance == 2)
516  {
517  fLegHappy = 1;
518  fTiltHappy = 1;
519  ThreeToTwo();
520  }
521  // This is the first of the slight unknowns, target is two legs, look up to stance 3, the center leg is up, but the tilt is unknown.
522  //You are either standing on two legs, or already in a pile on the ground. Cant hurt to try tilting up.
523  if (fStanceTarget == 1 && fStance == 3)
524  {
525  fTiltHappy = 1;
526  MoveTiltUp();
527  }
528  // Target two legs, tilt is up, center leg unknown, Can not hurt to try and lift the leg again.
529  if (fStanceTarget == 1 && fStance == 4)
530  {
531  fLegHappy = 1;
532  MoveLegUp();
533  }
534  // Target is two legs, center foot is down, tilt is unknown, too risky do nothing.
535  if (fStanceTarget == 1 && fStance == 5)
536  {
537  motorStopNow();
538  return;
539  }
540  // target is two legs, tilt is down, center leg is unknown, too risky, do nothing.
541  if (fStanceTarget == 1 && fStance == 6)
542  {
543  motorStopNow();
544  return;
545  }
546  // target is three legs, stance is two legs, run two to three.
547  if (fStanceTarget == 2 && fStance == 1)
548  {
549  fLegHappy = 1;
550  fTiltHappy = 1;
551  TwoToThree();
552  }
553  //Target is three legs. center leg is up, tilt is unknown, safer to do nothing, Recover from stance 3 with the up command
554  if (fStanceTarget == 2 && fStance == 3)
555  {
556  motorStopNow();
557  return;
558  }
559  // target is three legs, but don't know where the center leg is. Best to not try this,
560  // recover from stance 4 with the up command,
561  if (fStanceTarget == 2 && fStance == 4)
562  {
563  motorStopNow();
564  return;
565  }
566  // Target is three legs, the center foot is down, tilt is unknownm. either on 3 legs now, or a smoking mess,
567  // nothing to loose in trying to tilt down again
568  if (fStanceTarget == 2 && fStance == 5)
569  {
570  fTiltHappy = 1;
571  MoveTiltDn();
572  }
573  // kinda like above, Target is 3 legs, tilt is down, center leg is unknown, ......got nothing to loose.
574  if (fStanceTarget == 2 && fStance == 6)
575  {
576  fLegHappy = 1;
577  MoveLegDn();
578  }
579  }
580 
586  void TwoToThree()
587  {
588  float yokeAnkle = getYokeAngle();
589  fTiltDn = digitalRead(fTiltDownPin);
590  fLegDn = digitalRead(fLegDownPin);
591 
592  if (fLegDn == 0)
593  {
594  legMotorStop();
595  }
596  // Delay starting until yoke ankle is greater than YOKE_ANGLE_CENTER_LEG_START
597  else if (fLegDn == 1 /*&& yokeAnkle >= YOKE_ANGLE_CENTER_LEG_START*/)
598  {
599  if (fLegPos < 40 && yokeAnkle < YOKE_ANGLE_3LEGS_TARGET)
600  legMotorDown();
601  else if (yokeAnkle < YOKE_ANGLE_3LEGS_TARGET)
602  legMotorStop();
603  else
604  legMotorDown();
605  }
606  if (fTiltDn == 0 || yokeAnkle >= YOKE_ANGLE_3LEGS_TARGET)
607  {
608  Serial.print("STOP : yokeAnkle="); Serial.println(yokeAnkle);
609  tiltMotorStop();
610  }
611  else if (fTiltDn == 1)
612  {
613  // if (yokeAnkle >= YOKE_ANGLE_2TO3LEGS_SLOWDOWN)
614  // {
615  // Serial.print("HALFSPEED : yokeAnkle="); Serial.println(yokeAnkle);
616  // tiltMotorDownSlow();
617  // }
618  // else
619  {
620  tiltMotorDown();
621  }
622  }
623  }
624 
629  void ThreeToTwo()
630  {
631  float yokeAnkle = getYokeAngle();
632  fTiltUp = digitalRead(fTiltUpPin);
633  fLegUp = digitalRead(fLegUpPin);
634  fTiltDn = digitalRead(fTiltDownPin);
635 
636  // First if the center leg is up, do nothing.
637  // DEBUG_PRINTLN(" Transition to Two Legs");
638  if (fLegUp == 0)
639  {
640  legMotorStop();
641  }
642  // If leg up is open AND the timer is in the first 20 steps then lift the center leg at 25 percent speed
643  if (fLegUp == 1 && fShowTimeThreeToTwo >= 22 && fShowTimeThreeToTwo <= 26)
644  {
645  legMotorUpSlow();
646  }
647  // If leg up is open AND the timer is over 21 steps then lift the center leg at full speed
648  if (fLegUp == 1 && fShowTimeThreeToTwo >= 27)
649  {
650  legMotorUp();
651  }
652  // at the same time, tilt up till the switch is closed
653  if (fTiltUp == 0 || yokeAnkle <= YOKE_ANGLE_2LEGS_TARGET)
654  {
655  tiltMotorStop();
656  }
657  if (fTiltUp == 1)
658  {
659  tiltMotorUp();
660  }
661  }
662 
663  float getYokeAngle()
664  {
665  // Return yoke angle or NaN if no sensors are available
666  return (fBodyIMU != NULL && fTiltIMU != NULL) ? fBodyIMU->getRoll() - fTiltIMU->getRoll() : 0.0 / 0.0;
667  }
668 
669  void Display()
670  {
671  // DEBUG_PRINT(F(" Battery "));
672  // DEBUG_PRINT(fBattery);
673  // DEBUG_PRINT(F(" CH1 "));
674  // DEBUG_PRINT(fCurrentChannel1);
675  // DEBUG_PRINT(F(" CH2 "));
676  // DEBUG_PRINTLN(fCurrentChannel2);
677 
678  DEBUG_PRINT(F(" Tilt Up "));
679  DEBUG_PRINT(fTiltUp);
680  DEBUG_PRINT(F(" Tilt Down "));
681  DEBUG_PRINT(fTiltDn);
682  DEBUG_PRINT(F(" Leg Up "));
683  DEBUG_PRINT(fLegUp);
684  DEBUG_PRINT(F(" Leg Down "));
685  DEBUG_PRINT(fLegDn);
686  DEBUG_PRINT(F(" Leg Pos "));
687  DEBUG_PRINT(fLegPos);
688 
689  DEBUG_PRINT(F(" Stance "));
690  DEBUG_PRINT(fStance);
691  DEBUG_PRINT(F(" Stance Target "));
692  DEBUG_PRINT(fStanceTarget);
693  DEBUG_PRINT(F(" Leg Happy "));
694  DEBUG_PRINT(fLegHappy);
695  DEBUG_PRINT(F(" Tilt Happy "));
696  DEBUG_PRINT(fTiltHappy);
697  DEBUG_PRINT(F(" Show Time "));
698  DEBUG_PRINT(fShowTimeThreeToTwo);
699  DEBUG_PRINT(F(" "));
700  DEBUG_PRINT(fShowTimeTwoToThree);
701  if (fBodyIMU != NULL)
702  {
703  DEBUG_PRINT(F(" Tilt Angle "));
704  DEBUG_PRINT(getYokeAngle());
705  }
706  DEBUG_PRINTLN(F(""));
707  }
708 };
709 #endif
CommandEvent
Base class for all command enabled devices. CommandEvent::handleCommand() is called for each device e...
Definition: CommandEvent.h:17
Orientation.h
DEBUG_PRINT
#define DEBUG_PRINT(s)
Definition: ReelTwo.h:189
TILT_MOTOR_FULL_POWER
#define TILT_MOTOR_FULL_POWER
Definition: Stance.h:18
ReelTwo.h
SetupEvent.h
AnimatedEvent
Base class for all animated devices. AnimatedEvent::animate() is called for each device once through ...
Definition: AnimatedEvent.h:18
Stance::isThreeLegged
bool isThreeLegged()
Returns true if the current stance is three legged.
Definition: Stance.h:100
SetupEvent
Base class for all devices that require setup that cannot happen in the constructor....
Definition: SetupEvent.h:15
MOTOR_HALF_POWER
#define MOTOR_HALF_POWER
Definition: Stance.h:20
AnimatedEvent.h
DEBUG_PRINTLN
#define DEBUG_PRINTLN(s)
Definition: ReelTwo.h:188
Stance::Stance
Stance(byte tiltUpPin=6, byte tiltDownPin=7, byte legUpPin=8, byte legDownPin=9, byte legPotPin=A0, byte saberAddress=128)
Definition: Stance.h:61
Stance::setOrientationSensors
void setOrientationSensors(Orientation &bodyIMU, Orientation &tiltIMU)
Definition: Stance.h:71
Stance::isTwoLegged
bool isTwoLegged()
Returns true if the current stance is two legged.
Definition: Stance.h:92
Stance
Manages transition from 2 to 3 legged stance using 4 limit switches.
Definition: Stance.h:34
Stance::setup
virtual void setup() override
Perform any initialzation not possible in the constructor.
Definition: Stance.h:132
Stance::isValid
bool isValid()
Returns true if the current stance is either two legged or three legged.
Definition: Stance.h:108
Stance::changeToThreeLegged
void changeToThreeLegged()
Initiate a transition to three legged mode.
Definition: Stance.h:124
MOTOR_FULL_POWER
#define MOTOR_FULL_POWER
Definition: Stance.h:17
Stance::animate
virtual void animate() override
Check status of Sabertooth and limit switches and manage transition if one has been initiated.
Definition: Stance.h:150
YOKE_ANGLE_3LEGS_TARGET
#define YOKE_ANGLE_3LEGS_TARGET
Definition: Stance.h:26
Stance::handleCommand
virtual void handleCommand(const char *cmd) override
Subclasses should implement this function to process commands specific to their device.
Definition: Stance.h:77
MOTOR_QUARTER_POWER
#define MOTOR_QUARTER_POWER
Definition: Stance.h:21
Stance::changeToTwoLegged
void changeToTwoLegged()
Initiate a transition to two legged mode.
Definition: Stance.h:116
CommandEvent.h
YOKE_ANGLE_2LEGS_TARGET
#define YOKE_ANGLE_2LEGS_TARGET
Definition: Stance.h:23
SizeOfArray
#define SizeOfArray(arr)
Definition: ReelTwo.h:213
Stance::Stance
Stance(HardwareSerial &saberSerialPort, byte tiltUpPin=6, byte tiltDownPin=7, byte legUpPin=8, byte legDownPin=9, byte legPotPin=A0, byte saberAddress=128)
Constructor.
Definition: Stance.h:41
Orientation::getRoll
float getRoll()
Returns the last recorded roll.
Definition: Orientation.h:71
Orientation
Encapsulates an Adafruit BNO055 IMU.
Definition: Orientation.h:19