create.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <cmath>
3 #include <ctime>
4 #include <memory>
5 #include <assert.h>
6 
7 #include "create/create.h"
8 
9 #define GET_DATA(id) (data->getPacket(id)->getData())
10 #define BOUND_CONST(val,min,max) (val<min?min:(val>max?max:val))
11 #define BOUND(val,min,max) (val = BOUND_CONST(val,min,max))
12 
13 namespace create {
14 
15  namespace ublas = boost::numeric::ublas;
16 
17  void Create::init(bool install_signal_handler) {
18  mainMotorPower = 0;
19  sideMotorPower = 0;
20  vacuumMotorPower = 0;
21  debrisLED = 0;
22  spotLED = 0;
23  dockLED = 0;
24  checkLED = 0;
25  powerLED = 0;
27  prevTicksLeft = 0;
28  prevTicksRight = 0;
29  totalLeftDist = 0.0;
30  totalRightDist = 0.0;
31  firstOnData = true;
32  mode = MODE_OFF;
33  pose.x = 0;
34  pose.y = 0;
35  pose.yaw = 0;
36  pose.covariance = std::vector<float>(9, 0.0);
37  vel.x = 0;
38  vel.y = 0;
39  vel.yaw = 0;
40  vel.covariance = std::vector<float>(9, 0.0);
41  poseCovar = Matrix(3, 3, 0.0);
42  requestedLeftVel = 0;
44  dtHistoryLength = 100;
45  data = std::shared_ptr<Data>(new Data(model.getVersion()));
46  if (model.getVersion() == V_1) {
47  serial = std::make_shared<SerialQuery>(data, install_signal_handler);
48  } else {
49  serial = std::make_shared<SerialStream>(
50  data, create::util::STREAM_HEADER, install_signal_handler);
51  }
52  }
53 
54  Create::Create(RobotModel m, bool install_signal_handler) : model(m) {
55  init(install_signal_handler);
56  }
57 
58  Create::Create(const std::string& dev, const int& baud, RobotModel m, bool install_signal_handler)
59  : model(m)
60  {
61  init(install_signal_handler);
62  serial->connect(dev, baud);
63  }
64 
66  disconnect();
67  }
68 
69  Create::Matrix Create::addMatrices(const Matrix &A, const Matrix &B) const {
70  size_t rows = A.size1();
71  size_t cols = A.size2();
72 
73  assert(rows == B.size1());
74  assert(cols == B.size2());
75 
76  Matrix C(rows, cols);
77  for (size_t i = 0u; i < rows; i++) {
78  for (size_t j = 0u; j < cols; j++) {
79  const float a = A(i, j);
80  const float b = B(i, j);
81  if (util::willFloatOverflow(a, b)) {
82  // If overflow, set to float min or max depending on direction of overflow
83  C(i, j) = (a < 0.0) ? std::numeric_limits<float>::min() : std::numeric_limits<float>::max();
84  }
85  else {
86  C(i, j) = a + b;
87  }
88  }
89  }
90  return C;
91  }
92 
93  void Create::onData() {
94  if (firstOnData) {
95  if (model.getVersion() >= V_3) {
96  // Initialize tick counts
99  }
100  prevOnDataTime = std::chrono::steady_clock::now();
101  firstOnData = false;
102  }
103 
104  // Get current time
105  auto curTime = std::chrono::steady_clock::now();
106  float dt = static_cast<std::chrono::duration<float>>(curTime - prevOnDataTime).count();
107  float deltaDist = 0.0f;
108  float deltaX = 0.0f;
109  float deltaY = 0.0f;
110  float deltaYaw = 0.0f;
111  float leftWheelDist = 0.0f;
112  float rightWheelDist = 0.0f;
113  float wheelDistDiff = 0.0f;
114 
115  // Protocol versions 1 and 2 use distance and angle fields for odometry
116  int16_t angleField = 0;
117  if (model.getVersion() <= V_2) {
118  // This is a standards compliant way of doing unsigned to signed conversion
119  uint16_t distanceRaw = GET_DATA(ID_DISTANCE);
120  int16_t distance;
121  std::memcpy(&distance, &distanceRaw, sizeof(distance));
122  deltaDist = distance / 1000.0; // mm -> m
123 
124  // Angle is processed differently in versions 1 and 2
125  uint16_t angleRaw = GET_DATA(ID_ANGLE);
126  std::memcpy(&angleField, &angleRaw, sizeof(angleField));
127  }
128 
129  if (model.getVersion() == V_1) {
130  wheelDistDiff = 2.0 * angleField / 1000.0;
131  leftWheelDist = deltaDist - (wheelDistDiff / 2.0);
132  rightWheelDist = deltaDist + (wheelDistDiff / 2.0);
133  deltaYaw = wheelDistDiff / model.getAxleLength();
134  } else if (model.getVersion() == V_2) {
135  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
136  * Certain older Creates have major problems with odometry *
137  * http://answers.ros.org/question/31935/createroomba-odometry/ *
138  * *
139  * All Creates have an issue with rounding of the angle field, which causes *
140  * major errors to accumulate in the odometry yaw. *
141  * http://wiki.tekkotsu.org/index.php/Create_Odometry_Bug *
142  * https://github.com/AutonomyLab/create_autonomy/issues/28 *
143  * *
144  * TODO: Consider using velocity command as substitute for pose estimation *
145  * to mitigate both of these problems. *
146  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
147  deltaYaw = angleField * (util::PI / 180.0); // D2R
148  wheelDistDiff = model.getAxleLength() * deltaYaw;
149  leftWheelDist = deltaDist - (wheelDistDiff / 2.0);
150  rightWheelDist = deltaDist + (wheelDistDiff / 2.0);
151  } else if (model.getVersion() >= V_3) {
152  // Get cumulative ticks (wraps around at 65535)
153  uint16_t totalTicksLeft = GET_DATA(ID_LEFT_ENC);
154  uint16_t totalTicksRight = GET_DATA(ID_RIGHT_ENC);
155  // Compute ticks since last update
156  int ticksLeft = totalTicksLeft - prevTicksLeft;
157  int ticksRight = totalTicksRight - prevTicksRight;
158  prevTicksLeft = totalTicksLeft;
159  prevTicksRight = totalTicksRight;
160 
161  // Handle wrap around
162  if (fabs(ticksLeft) > 0.9 * util::V_3_MAX_ENCODER_TICKS) {
163  ticksLeft = (ticksLeft % util::V_3_MAX_ENCODER_TICKS) + 1;
164  }
165  if (fabs(ticksRight) > 0.9 * util::V_3_MAX_ENCODER_TICKS) {
166  ticksRight = (ticksRight % util::V_3_MAX_ENCODER_TICKS) + 1;
167  }
168 
169  // Compute distance travelled by each wheel
170  leftWheelDist = (ticksLeft / util::V_3_TICKS_PER_REV)
172  rightWheelDist = (ticksRight / util::V_3_TICKS_PER_REV)
174  deltaDist = (rightWheelDist + leftWheelDist) / 2.0;
175 
176  wheelDistDiff = rightWheelDist - leftWheelDist;
177  deltaYaw = wheelDistDiff / model.getAxleLength();
178  }
179 
180  // determine average dt over window
181  dtHistory.push_front(dt);
182 
183  if (dtHistory.size() > dtHistoryLength){
184  dtHistory.pop_back();
185  }
186 
187  float dtHistorySum = 0;
188  for (auto it = dtHistory.cbegin(); it != dtHistory.cend(); ++it)
189  {
190  dtHistorySum += *it;
191  }
192  auto dtAverage = dtHistorySum / dtHistory.size();
193 
194  measuredLeftVel = leftWheelDist / dtAverage;
195  measuredRightVel = rightWheelDist / dtAverage;
196 
197  // Moving straight
198  if (fabs(wheelDistDiff) < util::EPS) {
199  deltaX = deltaDist * cos(pose.yaw);
200  deltaY = deltaDist * sin(pose.yaw);
201  } else {
202  float turnRadius = (model.getAxleLength() / 2.0) * (leftWheelDist + rightWheelDist) / wheelDistDiff;
203  deltaX = turnRadius * (sin(pose.yaw + deltaYaw) - sin(pose.yaw));
204  deltaY = -turnRadius * (cos(pose.yaw + deltaYaw) - cos(pose.yaw));
205  }
206 
207  totalLeftDist += leftWheelDist;
208  totalRightDist += rightWheelDist;
209 
210  if (fabs(dtAverage) > util::EPS) {
211  vel.x = deltaDist / dtAverage;
212  vel.y = 0.0;
213  vel.yaw = deltaYaw / dtAverage;
214  } else {
215  vel.x = 0.0;
216  vel.y = 0.0;
217  vel.yaw = 0.0;
218  }
219 
220  // Update covariances
221  // Ref: "Introduction to Autonomous Mobile Robots" (Siegwart 2004, page 189)
222  float kr = 1.0; // TODO: Perform experiments to find these nondeterministic parameters
223  float kl = 1.0;
224  float cosYawAndHalfDelta = cos(pose.yaw + (deltaYaw / 2.0)); // deltaX?
225  float sinYawAndHalfDelta = sin(pose.yaw + (deltaYaw / 2.0)); // deltaY?
226  float distOverTwoWB = deltaDist / (model.getAxleLength() * 2.0);
227 
228  Matrix invCovar(2, 2);
229  invCovar(0, 0) = kr * fabs(rightWheelDist);
230  invCovar(0, 1) = 0.0;
231  invCovar(1, 0) = 0.0;
232  invCovar(1, 1) = kl * fabs(leftWheelDist);
233 
234  Matrix Finc(3, 2);
235  Finc(0, 0) = (cosYawAndHalfDelta / 2.0) - (distOverTwoWB * sinYawAndHalfDelta);
236  Finc(0, 1) = (cosYawAndHalfDelta / 2.0) + (distOverTwoWB * sinYawAndHalfDelta);
237  Finc(1, 0) = (sinYawAndHalfDelta / 2.0) + (distOverTwoWB * cosYawAndHalfDelta);
238  Finc(1, 1) = (sinYawAndHalfDelta / 2.0) - (distOverTwoWB * cosYawAndHalfDelta);
239  Finc(2, 0) = (1.0 / model.getAxleLength());
240  Finc(2, 1) = (-1.0 / model.getAxleLength());
241  Matrix FincT = boost::numeric::ublas::trans(Finc);
242 
243  Matrix Fp(3, 3);
244  Fp(0, 0) = 1.0;
245  Fp(0, 1) = 0.0;
246  Fp(0, 2) = (-deltaDist) * sinYawAndHalfDelta;
247  Fp(1, 0) = 0.0;
248  Fp(1, 1) = 1.0;
249  Fp(1, 2) = deltaDist * cosYawAndHalfDelta;
250  Fp(2, 0) = 0.0;
251  Fp(2, 1) = 0.0;
252  Fp(2, 2) = 1.0;
253  Matrix FpT = boost::numeric::ublas::trans(Fp);
254 
255  Matrix velCovar = ublas::prod(invCovar, FincT);
256  velCovar = ublas::prod(Finc, velCovar);
257 
258  vel.covariance[0] = velCovar(0, 0);
259  vel.covariance[1] = velCovar(0, 1);
260  vel.covariance[2] = velCovar(0, 2);
261  vel.covariance[3] = velCovar(1, 0);
262  vel.covariance[4] = velCovar(1, 1);
263  vel.covariance[5] = velCovar(1, 2);
264  vel.covariance[6] = velCovar(2, 0);
265  vel.covariance[7] = velCovar(2, 1);
266  vel.covariance[8] = velCovar(2, 2);
267 
268  Matrix poseCovarTmp = ublas::prod(poseCovar, FpT);
269  poseCovarTmp = ublas::prod(Fp, poseCovarTmp);
270  poseCovar = addMatrices(poseCovarTmp, velCovar);
271 
272  pose.covariance[0] = poseCovar(0, 0);
273  pose.covariance[1] = poseCovar(0, 1);
274  pose.covariance[2] = poseCovar(0, 2);
275  pose.covariance[3] = poseCovar(1, 0);
276  pose.covariance[4] = poseCovar(1, 1);
277  pose.covariance[5] = poseCovar(1, 2);
278  pose.covariance[6] = poseCovar(2, 0);
279  pose.covariance[7] = poseCovar(2, 1);
280  pose.covariance[8] = poseCovar(2, 2);
281 
282  // Update pose
283  pose.x += deltaX;
284  pose.y += deltaY;
285  pose.yaw = util::normalizeAngle(pose.yaw + deltaYaw);
286 
287  prevOnDataTime = curTime;
288 
289  // Make user registered callbacks, if any
290  // TODO
291  }
292 
293  bool Create::connect(const std::string& port, const int& baud) {
294  bool timeout = false;
295  time_t start, now;
296  float maxWait = 30; // seconds
297  float retryInterval = 5; //seconds
298  time(&start);
299  while (!serial->connect(port, baud, std::bind(&Create::onData, this)) && !timeout) {
300  time(&now);
301  if (difftime(now, start) > maxWait) {
302  timeout = true;
303  CERR("[create::Create] ", "failed to connect over serial: timeout");
304  }
305  else {
306  usleep(retryInterval * 1000000);
307  COUT("[create::Create] ", "retrying to establish serial connection...");
308  }
309  }
310 
311  return !timeout;
312  }
313 
315  serial->disconnect();
316  firstOnData = true;
317  }
318 
319  //void Create::reset() {
320  // serial->sendOpcode(OC_RESET);
321  // serial->reset(); // better
322  // TODO : Should we request reading packets again?
323  //}
324 
326  if (model.getVersion() == V_1){
327  // Switch to safe mode (required for compatibility with V_1)
328  if (!(serial->sendOpcode(OC_START) && serial->sendOpcode(OC_CONTROL))) return false;
329  }
330  bool ret = false;
331  switch (mode) {
332  case MODE_OFF:
333  if (model.getVersion() == V_2) {
334  CERR("[create::Create] ", "protocol version 2 does not support turning robot off");
335  ret = false;
336  } else {
337  ret = serial->sendOpcode(OC_POWER);
338  }
339  break;
340  case MODE_PASSIVE:
341  ret = serial->sendOpcode(OC_START);
342  break;
343  case MODE_SAFE:
344  if (model.getVersion() > V_1) {
345  ret = serial->sendOpcode(OC_SAFE);
346  }
347  break;
348  case MODE_FULL:
349  ret = serial->sendOpcode(OC_FULL);
350  break;
351  default:
352  CERR("[create::Create] ", "cannot set robot to mode '" << mode << "'");
353  ret = false;
354  }
355  if (ret) {
356  this->mode = mode;
357  }
358  return ret;
359  }
360 
361  bool Create::clean(const CleanMode& mode) {
362  return serial->sendOpcode((Opcode) mode);
363  }
364 
365  bool Create::dock() const {
366  return serial->sendOpcode(OC_DOCK);
367  }
368 
369  bool Create::setDate(const DayOfWeek& day, const uint8_t& hour, const uint8_t& min) const {
370  if (day < 0 || day > 6 ||
371  hour > 23 ||
372  min > 59)
373  return false;
374 
375  uint8_t cmd[4] = { OC_DATE, day, hour, min };
376  return serial->send(cmd, 4);
377  }
378 
379  bool Create::driveRadius(const float& vel, const float& radius) {
380  // Bound velocity
381  float boundedVel = BOUND_CONST(vel, -model.getMaxVelocity(), model.getMaxVelocity());
382 
383  // Expects each parameter as two bytes each and in millimeters
384  int16_t vel_mm = roundf(boundedVel * 1000);
385  int16_t radius_mm = roundf(radius * 1000);
386 
387  // Bound radius if not a special case
388  if (radius_mm != -32768 && radius_mm != 32767 &&
389  radius_mm != -1 && radius_mm != 1) {
390  BOUND(radius_mm, -util::MAX_RADIUS * 1000, util::MAX_RADIUS * 1000);
391  }
392 
393  uint8_t cmd[5] = { OC_DRIVE,
394  static_cast<uint8_t>(vel_mm >> 8),
395  static_cast<uint8_t>(vel_mm & 0xff),
396  static_cast<uint8_t>(radius_mm >> 8),
397  static_cast<uint8_t>(radius_mm & 0xff)
398  };
399 
400  return serial->send(cmd, 5);
401  }
402 
403  bool Create::driveWheels(const float& leftVel, const float& rightVel) {
404  const float boundedLeftVel = BOUND_CONST(leftVel, -model.getMaxVelocity(), model.getMaxVelocity());
405  const float boundedRightVel = BOUND_CONST(rightVel, -model.getMaxVelocity(), model.getMaxVelocity());
406  requestedLeftVel = boundedLeftVel;
407  requestedRightVel = boundedRightVel;
408  if (model.getVersion() > V_1) {
409  int16_t leftCmd = roundf(boundedLeftVel * 1000);
410  int16_t rightCmd = roundf(boundedRightVel * 1000);
411 
412  uint8_t cmd[5] = { OC_DRIVE_DIRECT,
413  static_cast<uint8_t>(rightCmd >> 8),
414  static_cast<uint8_t>(rightCmd & 0xff),
415  static_cast<uint8_t>(leftCmd >> 8),
416  static_cast<uint8_t>(leftCmd & 0xff)
417  };
418  return serial->send(cmd, 5);
419  } else {
420  float radius;
421  // Prevent divide by zero when driving straight
422  if (boundedLeftVel != boundedRightVel) {
423  radius = -((model.getAxleLength() / 2.0) * (boundedLeftVel + boundedRightVel)) /
424  (boundedLeftVel - boundedRightVel);
425  } else {
426  radius = util::STRAIGHT_RADIUS;
427  }
428 
429  float vel;
430  // Fix signs for spin in place
431  if (boundedLeftVel == -boundedRightVel || std::abs(roundf(radius * 1000)) <= 1) {
432  radius = util::IN_PLACE_RADIUS;
433  vel = boundedRightVel;
434  } else {
435  vel = (std::abs(boundedLeftVel) + std::abs(boundedRightVel)) / 2.0 * ((boundedLeftVel + boundedRightVel) > 0 ? 1.0 : -1.0);
436  }
437 
438  // Radius turns have a maximum radius of 2.0 meters
439  // When the radius is > 2 but <= 10, use a 2 meter radius
440  // When it is > 10, drive straight
441  // TODO: alternate between these 2 meter radius and straight to
442  // fake a larger radius
443  if (radius > 10.0) {
444  radius = util::STRAIGHT_RADIUS;
445  }
446 
447  return driveRadius(vel, radius);
448  }
449  }
450 
451  bool Create::driveWheelsPwm(const float& leftWheel, const float& rightWheel)
452  {
453  static const int16_t PWM_COUNTS = 255;
454 
455  if (leftWheel < -1.0 || leftWheel > 1.0 ||
456  rightWheel < -1.0 || rightWheel > 1.0)
457  return false;
458 
459  int16_t leftPwm = roundf(leftWheel * PWM_COUNTS);
460  int16_t rightPwm = roundf(rightWheel * PWM_COUNTS);
461 
462  uint8_t cmd[5] = { OC_DRIVE_PWM,
463  static_cast<uint8_t>(rightPwm >> 8),
464  static_cast<uint8_t>(rightPwm & 0xff),
465  static_cast<uint8_t>(leftPwm >> 8),
466  static_cast<uint8_t>(leftPwm & 0xff)
467  };
468 
469  return serial->send(cmd, 5);
470  }
471 
472  bool Create::drive(const float& xVel, const float& angularVel) {
473  // Compute left and right wheel velocities
474  float leftVel = xVel - ((model.getAxleLength() / 2.0) * angularVel);
475  float rightVel = xVel + ((model.getAxleLength() / 2.0) * angularVel);
476  return driveWheels(leftVel, rightVel);
477  }
478 
479  bool Create::setAllMotors(const float& main, const float& side, const float& vacuum) {
480  if (main < -1.0 || main > 1.0 ||
481  side < -1.0 || side > 1.0 ||
482  vacuum < -1.0 || vacuum > 1.0)
483  return false;
484 
485  mainMotorPower = roundf(main * 127);
486  sideMotorPower = roundf(side * 127);
487  vacuumMotorPower = roundf(vacuum * 127);
488 
489  if (model.getVersion() == V_1) {
490  uint8_t cmd[2] = { OC_MOTORS,
491  static_cast<uint8_t>((side != 0.0 ? 1 : 0) |
492  (vacuum != 0.0 ? 2 : 0) |
493  (main != 0.0 ? 4 : 0))
494  };
495  return serial->send(cmd, 2);
496  }
497 
498  uint8_t cmd[4] = { OC_MOTORS_PWM,
502  };
503 
504  return serial->send(cmd, 4);
505  }
506 
507  bool Create::setMainMotor(const float& main) {
508  return setAllMotors(main, static_cast<float>(sideMotorPower) / 127.0, static_cast<float>(vacuumMotorPower) / 127.0);
509  }
510 
511  bool Create::setSideMotor(const float& side) {
512  return setAllMotors(static_cast<float>(mainMotorPower) / 127.0, side, static_cast<float>(vacuumMotorPower) / 127.0);
513  }
514 
515  bool Create::setVacuumMotor(const float& vacuum) {
516  return setAllMotors(static_cast<float>(mainMotorPower) / 127.0, static_cast<float>(sideMotorPower) / 127.0, vacuum);
517  }
518 
520  uint8_t LEDByte = debrisLED + spotLED + dockLED + checkLED;
521  uint8_t cmd[4] = { OC_LEDS,
522  LEDByte,
523  powerLED,
525  };
526 
527  return serial->send(cmd, 4);
528  }
529 
530  bool Create::enableDebrisLED(const bool& enable) {
531  if (enable)
533  else
534  debrisLED = 0;
535  return updateLEDs();
536  }
537 
538  bool Create::enableSpotLED(const bool& enable) {
539  if (enable)
540  spotLED = LED_SPOT;
541  else
542  spotLED = 0;
543  return updateLEDs();
544  }
545 
546  bool Create::enableDockLED(const bool& enable) {
547  if (enable)
548  dockLED = LED_DOCK;
549  else
550  dockLED = 0;
551  return updateLEDs();
552  }
553 
554  bool Create::enableCheckRobotLED(const bool& enable) {
555  if (enable)
557  else
558  checkLED = 0;
559  return updateLEDs();
560  }
561 
562  bool Create::setPowerLED(const uint8_t& power, const uint8_t& intensity) {
563  powerLED = power;
564  powerLEDIntensity = intensity;
565  return updateLEDs();
566  }
567 
568  //void Create::setDigits(uint8_t digit1, uint8_t digit2,
569  // uint8_t digit3, uint8_t digit4) {
570  //}
571 
572  bool Create::setDigitsASCII(const uint8_t& digit1, const uint8_t& digit2,
573  const uint8_t& digit3, const uint8_t& digit4) const {
574  if (digit1 < 32 || digit1 > 126 ||
575  digit2 < 32 || digit2 > 126 ||
576  digit3 < 32 || digit3 > 126 ||
577  digit4 < 32 || digit4 > 126)
578  return false;
579 
580  uint8_t cmd[5] = { OC_DIGIT_LEDS_ASCII,
581  digit1,
582  digit2,
583  digit3,
584  digit4
585  };
586 
587  return serial->send(cmd, 5);
588  }
589 
590  bool Create::defineSong(const uint8_t& songNumber,
591  const uint8_t& songLength,
592  const uint8_t* notes,
593  const float* durations) const {
594  int i, j;
595  uint8_t duration;
596  std::vector<uint8_t> cmd(2 * songLength + 3);
597  cmd[0] = OC_SONG;
598  cmd[1] = songNumber;
599  cmd[2] = songLength;
600  j = 0;
601  for (i = 3; i < 2 * songLength + 3; i = i + 2) {
602  if (durations[j] < 0 || durations[j] >= 4)
603  return false;
604  duration = durations[j] * 64;
605  cmd[i] = notes[j];
606  cmd[i + 1] = duration;
607  j++;
608  }
609 
610  return serial->send(cmd.data(), cmd.size());
611  }
612 
613  bool Create::playSong(const uint8_t& songNumber) const {
614  if (songNumber > 4)
615  return false;
616  uint8_t cmd[2] = { OC_PLAY, songNumber };
617  return serial->send(cmd, 2);
618  }
619 
621  this->dtHistoryLength = dtHistoryLength;
622  }
623 
624  bool Create::isWheeldrop() const {
625  if (data->isValidPacketID(ID_BUMP_WHEELDROP)) {
626  return (GET_DATA(ID_BUMP_WHEELDROP) & 0x0C) != 0;
627  }
628  else {
629  CERR("[create::Create] ", "Wheeldrop sensor not supported!");
630  return false;
631  }
632  }
633 
634  bool Create::isLeftWheeldrop() const {
635  if (data->isValidPacketID(ID_BUMP_WHEELDROP)) {
636  return (GET_DATA(ID_BUMP_WHEELDROP) & 0x08) != 0;
637  }
638  else {
639  CERR("[create::Create] ", "Wheeldrop sensor not supported!");
640  return false;
641  }
642  }
643 
645  if (data->isValidPacketID(ID_BUMP_WHEELDROP)) {
646  return (GET_DATA(ID_BUMP_WHEELDROP) & 0x04) != 0;
647  }
648  else {
649  CERR("[create::Create] ", "Wheeldrop sensor not supported!");
650  return false;
651  }
652  }
653 
654  bool Create::isLeftBumper() const {
655  if (data->isValidPacketID(ID_BUMP_WHEELDROP)) {
656  return (GET_DATA(ID_BUMP_WHEELDROP) & 0x02) != 0;
657  }
658  else {
659  CERR("[create::Create] ", "Left bumper not supported!");
660  return false;
661  }
662  }
663 
664  bool Create::isRightBumper() const {
665  if (data->isValidPacketID(ID_BUMP_WHEELDROP)) {
666  return (GET_DATA(ID_BUMP_WHEELDROP) & 0x01) != 0;
667  }
668  else {
669  CERR("[create::Create] ", "Right bumper not supported!");
670  return false;
671  }
672  }
673 
674  bool Create::isWall() const {
675  if (data->isValidPacketID(ID_WALL)) {
676  return GET_DATA(ID_WALL) == 1;
677  }
678  else {
679  CERR("[create::Create] ", "Wall sensor not supported!");
680  return false;
681  }
682  }
683 
684  bool Create::isCliff() const {
685  if (data->isValidPacketID(ID_CLIFF_LEFT) &&
686  data->isValidPacketID(ID_CLIFF_FRONT_LEFT) &&
687  data->isValidPacketID(ID_CLIFF_FRONT_RIGHT) &&
688  data->isValidPacketID(ID_CLIFF_RIGHT)) {
689  return GET_DATA(ID_CLIFF_LEFT) == 1 ||
692  GET_DATA(ID_CLIFF_RIGHT) == 1;
693  }
694  else {
695  CERR("[create::Create] ", "Cliff sensors not supported!");
696  return false;
697  }
698  }
699 
700  bool Create::isCliffLeft() const {
701  if (data->isValidPacketID(ID_CLIFF_LEFT)) {
702  return GET_DATA(ID_CLIFF_LEFT) == 1;
703  }
704  else {
705  CERR("[create::Create] ", "Left cliff sensors not supported!");
706  return false;
707  }
708  }
709 
711  if (data->isValidPacketID(ID_CLIFF_FRONT_LEFT)) {
712  return GET_DATA(ID_CLIFF_FRONT_LEFT) == 1;
713  }
714  else {
715  CERR("[create::Create] ", "Front left cliff sensors not supported!");
716  return false;
717  }
718  }
719 
720  bool Create::isCliffRight() const {
721  if (data->isValidPacketID(ID_CLIFF_RIGHT)) {
722  return GET_DATA(ID_CLIFF_RIGHT) == 1;
723  }
724  else {
725  CERR("[create::Create] ", "Rightt cliff sensors not supported!");
726  return false;
727  }
728  }
729 
731  if (data->isValidPacketID(ID_CLIFF_FRONT_RIGHT)) {
732  return GET_DATA(ID_CLIFF_FRONT_RIGHT) == 1;
733  }
734  else {
735  CERR("[create::Create] ", "Front right cliff sensors not supported!");
736  return false;
737  }
738  }
739 
740  bool Create::isVirtualWall() const {
741  if (data->isValidPacketID(ID_VIRTUAL_WALL)) {
742  return GET_DATA(ID_VIRTUAL_WALL);
743  }
744  else {
745  CERR("[create::Create] ", "Virtual Wall sensor not supported!");
746  return false;
747  }
748  }
749 
750  uint8_t Create::getDirtDetect() const {
751  if (data->isValidPacketID(ID_DIRT_DETECT_LEFT)) {
753  }
754  else {
755  CERR("[create::Create] ", "Dirt detector not supported!");
756  return -1;
757  }
758  }
759 
760  uint8_t Create::getIROmni() const {
761  if (data->isValidPacketID(ID_IR_OMNI)) {
762  return GET_DATA(ID_IR_OMNI);
763  }
764  else {
765  CERR("[create::Create] ", "Omni IR sensor not supported!");
766  return -1;
767  }
768  }
769 
770  uint8_t Create::getIRLeft() const {
771  if (data->isValidPacketID(ID_IR_LEFT)) {
772  return GET_DATA(ID_IR_LEFT);
773  }
774  else {
775  CERR("[create::Create] ", "Left IR sensor not supported!");
776  return -1;
777  }
778  }
779 
780  uint8_t Create::getIRRight() const {
781  if (data->isValidPacketID(ID_IR_RIGHT)) {
782  return GET_DATA(ID_IR_RIGHT);
783  }
784  else {
785  CERR("[create::Create] ", "Right IR sensor not supported!");
786  return -1;
787  }
788  }
789 
791  if (data->isValidPacketID(ID_CHARGE_STATE)) {
792  uint8_t chargeState = GET_DATA(ID_CHARGE_STATE);
793  assert(chargeState <= 5);
794  return (ChargingState) chargeState;
795  }
796  else {
797  CERR("[create::Create] ", "Charging state not supported!");
798  return CHARGE_FAULT;
799  }
800  }
801 
803  if (data->isValidPacketID(ID_BUTTONS)) {
804  return (GET_DATA(ID_BUTTONS) & 0x01) != 0;
805  }
806  else {
807  CERR("[create::Create] ", "Buttons not supported!");
808  return false;
809  }
810  }
811 
812  // Not supported by any 600 series firmware
814  CERR("[create::Create] ", "Clock button is not supported!");
815  if (data->isValidPacketID(ID_BUTTONS)) {
816  return (GET_DATA(ID_BUTTONS) & 0x80) != 0;
817  }
818  else {
819  CERR("[create::Create] ", "Buttons not supported!");
820  return false;
821  }
822  }
823 
824  // Not supported by any 600 series firmware
826  CERR("[create::Create] ", "Schedule button is not supported!");
827  if (data->isValidPacketID(ID_BUTTONS)) {
828  return (GET_DATA(ID_BUTTONS) & 0x40) != 0;
829  }
830  else {
831  CERR("[create::Create] ", "Buttons not supported!");
832  return false;
833  }
834  }
835 
837  if (data->isValidPacketID(ID_BUTTONS)) {
838  return (GET_DATA(ID_BUTTONS) & 0x20) != 0;
839  }
840  else {
841  CERR("[create::Create] ", "Buttons not supported!");
842  return false;
843  }
844  }
845 
847  if (data->isValidPacketID(ID_BUTTONS)) {
848  return (GET_DATA(ID_BUTTONS) & 0x10) != 0;
849  }
850  else {
851  CERR("[create::Create] ", "Buttons not supported!");
852  return false;
853  }
854  }
855 
857  if (data->isValidPacketID(ID_BUTTONS)) {
858  return (GET_DATA(ID_BUTTONS) & 0x08) != 0;
859  }
860  else {
861  CERR("[create::Create] ", "Buttons not supported!");
862  return false;
863  }
864  }
865 
867  if (data->isValidPacketID(ID_BUTTONS)) {
868  return (GET_DATA(ID_BUTTONS) & 0x04) != 0;
869  }
870  else {
871  CERR("[create::Create] ", "Buttons not supported!");
872  return false;
873  }
874  }
875 
877  if (data->isValidPacketID(ID_BUTTONS)) {
878  return (GET_DATA(ID_BUTTONS) & 0x02) != 0;
879  }
880  else {
881  CERR("[create::Create] ", "Buttons not supported!");
882  return false;
883  }
884  }
885 
886  float Create::getVoltage() const {
887  if (data->isValidPacketID(ID_VOLTAGE)) {
888  return (GET_DATA(ID_VOLTAGE) / 1000.0);
889  }
890  else {
891  CERR("[create::Create] ", "Voltage sensor not supported!");
892  return 0;
893  }
894  }
895 
896  float Create::getCurrent() const {
897  if (data->isValidPacketID(ID_VOLTAGE)) {
898  return (((int16_t)GET_DATA(ID_CURRENT)) / 1000.0);
899  }
900  else {
901  CERR("[create::Create] ", "Current sensor not supported!");
902  return 0;
903  }
904  }
905 
906  int8_t Create::getTemperature() const {
907  if (data->isValidPacketID(ID_TEMP)) {
908  return (int8_t) GET_DATA(ID_TEMP);
909  }
910  else {
911  CERR("[create::Create] ", "Temperature sensor not supported!");
912  return 0;
913  }
914  }
915 
916  float Create::getBatteryCharge() const {
917  if (data->isValidPacketID(ID_CHARGE)) {
918  return (GET_DATA(ID_CHARGE) / 1000.0);
919  }
920  else {
921  CERR("[create::Create] ", "Battery charge not supported!");
922  return 0;
923  }
924  }
925 
927  if (data->isValidPacketID(ID_CAPACITY)) {
928  return (GET_DATA(ID_CAPACITY) / 1000.0);
929  }
930  else {
931  CERR("[create::Create] ", "Battery capacity not supported!");
932  return 0;
933  }
934  }
935 
937  if (data->isValidPacketID(ID_LIGHT)) {
938  return (GET_DATA(ID_LIGHT) & 0x01) != 0;
939  }
940  else {
941  CERR("[create::Create] ", "Light sensors not supported!");
942  return false;
943  }
944  }
945 
947  if (data->isValidPacketID(ID_LIGHT)) {
948  return (GET_DATA(ID_LIGHT) & 0x02) != 0;
949  }
950  else {
951  CERR("[create::Create] ", "Light sensors not supported!");
952  return false;
953  }
954  }
955 
957  if (data->isValidPacketID(ID_LIGHT)) {
958  return (GET_DATA(ID_LIGHT) & 0x04) != 0;
959  }
960  else {
961  CERR("[create::Create] ", "Light sensors not supported!");
962  return false;
963  }
964  }
965 
967  if (data->isValidPacketID(ID_LIGHT)) {
968  return (GET_DATA(ID_LIGHT) & 0x08) != 0;
969  }
970  else {
971  CERR("[create::Create] ", "Light sensors not supported!");
972  return false;
973  }
974  }
975 
977  if (data->isValidPacketID(ID_LIGHT)) {
978  return (GET_DATA(ID_LIGHT) & 0x10) != 0;
979  }
980  else {
981  CERR("[create::Create] ", "Light sensors not supported!");
982  return false;
983  }
984  }
985 
987  if (data->isValidPacketID(ID_LIGHT)) {
988  return (GET_DATA(ID_LIGHT) & 0x20) != 0;
989  }
990  else {
991  CERR("[create::Create] ", "Light sensors not supported!");
992  return false;
993  }
994  }
995 
996  uint16_t Create::getLightSignalLeft() const {
997  if (data->isValidPacketID(ID_LIGHT_LEFT)) {
998  return GET_DATA(ID_LIGHT_LEFT);
999  }
1000  else {
1001  CERR("[create::Create] ", "Light sensors not supported!");
1002  return 0;
1003  }
1004  }
1005 
1007  if (data->isValidPacketID(ID_LIGHT_FRONT_LEFT)) {
1008  return GET_DATA(ID_LIGHT_FRONT_LEFT);
1009  }
1010  else {
1011  CERR("[create::Create] ", "Light sensors not supported!");
1012  return 0;
1013  }
1014  }
1015 
1017  if (data->isValidPacketID(ID_LIGHT_CENTER_LEFT)) {
1019  }
1020  else {
1021  CERR("[create::Create] ", "Light sensors not supported!");
1022  return 0;
1023  }
1024  }
1025 
1026  uint16_t Create::getLightSignalRight() const {
1027  if (data->isValidPacketID(ID_LIGHT_RIGHT)) {
1028  return GET_DATA(ID_LIGHT_RIGHT);
1029  }
1030  else {
1031  CERR("[create::Create] ", "Light sensors not supported!");
1032  return 0;
1033  }
1034  }
1035 
1037  if (data->isValidPacketID(ID_LIGHT_FRONT_RIGHT)) {
1039  }
1040  else {
1041  CERR("[create::Create] ", "Light sensors not supported!");
1042  return 0;
1043  }
1044  }
1045 
1047  if (data->isValidPacketID(ID_LIGHT_CENTER_RIGHT)) {
1049  }
1050  else {
1051  CERR("[create::Create] ", "Light sensors not supported!");
1052  return 0;
1053  }
1054  }
1055 
1057  if (data->isValidPacketID(ID_STASIS)) {
1058  return GET_DATA(ID_STASIS) == 1;
1059  }
1060  else {
1061  CERR("[create::Create] ", "Stasis sensor not supported!");
1062  return false;
1063  }
1064  }
1065 
1067  if (data->isValidPacketID(ID_OVERCURRENTS)) {
1068  return (GET_DATA(ID_OVERCURRENTS) & 0x01) != 0;
1069  }
1070  else {
1071  CERR("[create::Create] ", "Overcurrent sensor not supported!");
1072  return false;
1073  }
1074  }
1075 
1077  if (data->isValidPacketID(ID_OVERCURRENTS)) {
1078  return (GET_DATA(ID_OVERCURRENTS) & 0x04) != 0;
1079  }
1080  else {
1081  CERR("[create::Create] ", "Overcurrent sensor not supported!");
1082  return false;
1083  }
1084  }
1085 
1087  if (data->isValidPacketID(ID_OVERCURRENTS)) {
1088  return (GET_DATA(ID_OVERCURRENTS) & 0x18) != 0;
1089  }
1090  else {
1091  CERR("[create::Create] ", "Overcurrent sensor not supported!");
1092  return false;
1093  }
1094  }
1095 
1097  return totalLeftDist;
1098  }
1099 
1101  return totalRightDist;
1102  }
1103 
1105  return measuredLeftVel;
1106  }
1107 
1109  return measuredRightVel;
1110  }
1111 
1113  return requestedLeftVel;
1114  }
1115 
1117  return requestedRightVel;
1118  }
1119 
1121  if (data->isValidPacketID(ID_OI_MODE)) {
1123  }
1124  return mode;
1125  }
1126 
1128  return pose;
1129  }
1130 
1132  return vel;
1133  }
1134 
1135  uint64_t Create::getNumCorruptPackets() const {
1136  return serial->getNumCorruptPackets();
1137  }
1138 
1139  uint64_t Create::getTotalPackets() const {
1140  return serial->getTotalPackets();
1141  }
1142 
1143 } // end namespace
uint64_t getTotalPackets() const
Get the total number of serial packets received (including corrupt packets) since first connecting to...
Definition: create.cpp:1139
ChargingState
Definition: types.h:216
bool setSideMotor(const float &power)
Set the power to the side brush motor.
Definition: create.cpp:511
static const float PI
Definition: util.h:49
uint8_t getIROmni() const
Get value of 8-bit IR character currently being received by omnidirectional sensor.
Definition: create.cpp:760
float totalLeftDist
Definition: create.h:81
create::Vel vel
Definition: create.h:77
uint8_t dockLED
Definition: create.h:69
uint8_t powerLEDIntensity
Definition: create.h:72
bool isLeftWheeldrop() const
Definition: create.cpp:634
float y
Definition: types.h:277
static const float IN_PLACE_RADIUS
Definition: util.h:48
float totalRightDist
Definition: create.h:82
float getMeasuredRightWheelVel() const
Get the measured velocity of the right wheel.
Definition: create.cpp:1108
bool setVacuumMotor(const float &power)
Set the power to the vacuum motor.
Definition: create.cpp:515
bool isWheeldrop() const
Definition: create.cpp:624
bool isWheelOvercurrent() const
Definition: create.cpp:1086
bool firstOnData
Definition: create.h:83
bool isLightBumperFrontLeft() const
Definition: create.cpp:946
bool setDigitsASCII(const uint8_t &digit1, const uint8_t &digit2, const uint8_t &digit3, const uint8_t &digit4) const
Set the four 7-segment display digits from left to right with ASCII codes. Any code out side the acce...
Definition: create.cpp:572
float requestedRightVel
Definition: create.h:93
bool isCliffRight() const
Definition: create.cpp:720
bool isLeftBumper() const
Definition: create.cpp:654
float yaw
Definition: types.h:278
create::ChargingState getChargingState() const
Get the current charging state.
Definition: create.cpp:790
bool driveWheels(const float &leftWheel, const float &rightWheel)
Set the velocities for the left and right wheels.
Definition: create.cpp:403
bool dock() const
Starts the docking behaviour. Changes mode to MODE_PASSIVE.
Definition: create.cpp:365
uint32_t prevTicksRight
Definition: create.h:80
create::Pose pose
Definition: create.h:76
int8_t getTemperature() const
Get the temperature of battery.
Definition: create.cpp:906
bool isHourButtonPressed() const
Get state of &#39;hour&#39; button.
Definition: create.cpp:846
uint8_t dtHistoryLength
Definition: create.h:86
bool isClockButtonPressed() const
Not supported by any firmware!
Definition: create.cpp:813
uint16_t getLightSignalFrontLeft() const
Get the signal strength from the front-left light sensor.
Definition: create.cpp:1006
bool isLightBumperCenterRight() const
Definition: create.cpp:966
float getRequestedLeftWheelVel() const
Get the requested velocity of the left wheel. This value is bounded at the maximum velocity of the ro...
Definition: create.cpp:1112
#define BOUND(val, min, max)
Definition: create.cpp:11
uint8_t spotLED
Definition: create.h:68
void setDtHistoryLength(const uint8_t &dtHistoryLength)
Set dtHistoryLength parameter. Used to configure the size of the buffer for calculating average time ...
Definition: create.cpp:620
bool setDate(const create::DayOfWeek &day, const uint8_t &hour, const uint8_t &min) const
Sets the internal clock of Create.
Definition: create.cpp:369
Opcode
Definition: types.h:154
float getRightWheelDistance() const
Get the total distance the right wheel has moved.
Definition: create.cpp:1100
create::Pose getPose() const
Get the estimated pose of Create based on wheel encoders.
Definition: create.cpp:1127
Definition: create.h:48
uint8_t getDirtDetect() const
Get level of the dirt detect sensor.
Definition: create.cpp:750
uint8_t powerLED
Definition: create.h:71
float getRequestedRightWheelVel() const
Get the requested velocity of the right wheel. This value is bounded at the maximum velocity of the r...
Definition: create.cpp:1116
bool enableDockLED(const bool &enable)
Set the green "dock" LED on/off.
Definition: create.cpp:546
bool setPowerLED(const uint8_t &power, const uint8_t &intensity=255)
Set the center power LED.
Definition: create.cpp:562
bool isLightBumperFrontRight() const
Definition: create.cpp:976
float getBatteryCharge() const
Get battery&#39;s remaining charge.
Definition: create.cpp:916
uint8_t getIRRight() const
Get value of 8-bit IR character currently being received by right sensor.
Definition: create.cpp:780
void init(bool install_signal_handler)
Definition: create.cpp:17
float getCurrent() const
Get current flowing in/out of battery. A positive current implies Create is charging.
Definition: create.cpp:896
bool driveWheelsPwm(const float &leftWheel, const float &rightWheel)
Set the direct for the left and right wheels.
Definition: create.cpp:451
ProtocolVersion getVersion() const
Definition: types.cpp:27
CreateMode mode
Definition: create.h:74
std::shared_ptr< create::Data > data
Definition: create.h:102
Represents a robot pose.
Definition: types.h:275
bool isVirtualWall() const
Definition: create.cpp:740
bool isCliffFrontRight() const
Definition: create.cpp:730
bool playSong(const uint8_t &songNumber) const
Play a previously created song. This command will not work if a song was not already defined with the...
Definition: create.cpp:613
#define GET_DATA(id)
Definition: create.cpp:9
bool isMovingForward() const
Definition: create.cpp:1056
Matrix addMatrices(const Matrix &A, const Matrix &B) const
Definition: create.cpp:69
float measuredRightVel
Definition: create.h:91
std::vector< float > covariance
3x3 covariance matrix in row-major order.
Definition: types.h:283
create::Vel getVel() const
Get the estimated velocity of Create based on wheel encoders.
Definition: create.cpp:1131
uint64_t getNumCorruptPackets() const
Get the number of corrupt serial packets since first connecting to Create. This value is ideally zero...
Definition: create.cpp:1135
int main(int argc, char **argv)
uint16_t getLightSignalCenterLeft() const
Get the signal strength from the center-left light sensor.
Definition: create.cpp:1016
float getMaxVelocity() const
Definition: types.cpp:39
static const float V_3_TICKS_PER_REV
Definition: util.h:44
uint8_t sideMotorPower
Definition: create.h:63
std::shared_ptr< create::Serial > serial
Definition: create.h:103
#define CERR(prefix, msg)
Definition: util.h:38
bool isLightBumperLeft() const
Definition: create.cpp:936
bool clean(const create::CleanMode &mode=CLEAN_DEFAULT)
Starts a cleaning mode. Changes mode to MODE_PASSIVE.
Definition: create.cpp:361
float getWheelDiameter() const
Definition: types.cpp:43
uint8_t checkLED
Definition: create.h:70
Create(RobotModel model=RobotModel::CREATE_2, bool install_signal_handler=true)
Default constructor.
Definition: create.cpp:54
bool isScheduleButtonPressed() const
Not supported by any firmware!
Definition: create.cpp:825
bool enableCheckRobotLED(const bool &enable)
Set the orange "check Create" LED on/off.
Definition: create.cpp:554
bool driveRadius(const float &velocity, const float &radius)
Set the average wheel velocity and turning radius of Create.
Definition: create.cpp:379
static const uint32_t V_3_MAX_ENCODER_TICKS
Definition: util.h:45
bool enableSpotLED(const bool &enable)
Set the green "spot" LED on/off.
Definition: create.cpp:538
bool setMainMotor(const float &power)
Set the power to the main brush motor.
Definition: create.cpp:507
bool isMinButtonPressed() const
Get state of &#39;min&#39; button.
Definition: create.cpp:856
bool isCleanButtonPressed() const
Get state of &#39;clean&#39; button (&#39;play&#39; button on Create 1).
Definition: create.cpp:802
bool drive(const float &xVel, const float &angularVel)
Set the forward and angular velocity of Create.
Definition: create.cpp:472
bool isDockButtonPressed() const
Get state of &#39;dock&#39; button (&#39;advance&#39; button on Create 1).
Definition: create.cpp:866
float getMeasuredLeftWheelVel() const
Get the measured velocity of the left wheel.
Definition: create.cpp:1104
boost::numeric::ublas::matrix< float > Matrix
Definition: create.h:51
bool enableDebrisLED(const bool &enable)
Set the blue "debris" LED on/off.
Definition: create.cpp:530
#define BOUND_CONST(val, min, max)
Definition: create.cpp:10
float getVoltage() const
Get battery voltage.
Definition: create.cpp:886
uint16_t getLightSignalLeft() const
Get the signal strength from the left light sensor.
Definition: create.cpp:996
uint8_t vacuumMotorPower
Definition: create.h:64
float x
Definition: types.h:276
bool isMainBrushOvercurrent() const
Definition: create.cpp:1076
bool updateLEDs()
Definition: create.cpp:519
static const float MAX_RADIUS
Definition: util.h:46
bool isRightWheeldrop() const
Definition: create.cpp:644
bool isRightBumper() const
Definition: create.cpp:664
bool isDayButtonPressed() const
Get state of &#39;day&#39; button.
Definition: create.cpp:836
bool willFloatOverflow(const float a, const float b)
Definition: util.h:60
bool isWall() const
Definition: create.cpp:674
RobotModel model
Definition: create.h:60
std::chrono::time_point< std::chrono::steady_clock > prevOnDataTime
Definition: create.h:84
static const float EPS
Definition: util.h:51
uint16_t getLightSignalCenterRight() const
Get the signal strength from the center-right light sensor.
Definition: create.cpp:1046
static const float STRAIGHT_RADIUS
Definition: util.h:47
#define COUT(prefix, msg)
Definition: util.h:37
bool isSpotButtonPressed() const
Get state of &#39;spot&#39; button.
Definition: create.cpp:876
uint32_t prevTicksLeft
Definition: create.h:79
CleanMode
Definition: types.h:210
uint8_t debrisLED
Definition: create.h:67
bool isCliffFrontLeft() const
Definition: create.cpp:710
float measuredLeftVel
Definition: create.h:90
uint16_t getLightSignalRight() const
Get the signal strength from the right light sensor.
Definition: create.cpp:1026
bool isSideBrushOvercurrent() const
Definition: create.cpp:1066
float getBatteryCapacity() const
Get estimated battery charge capacity.
Definition: create.cpp:926
bool isCliffLeft() const
Definition: create.cpp:700
float requestedLeftVel
Definition: create.h:92
bool connect(const std::string &port, const int &baud)
Make a serial connection to Create.
Definition: create.cpp:293
uint8_t mainMotorPower
Definition: create.h:62
uint8_t getIRLeft() const
Get value of 8-bit IR character currently being received by left sensor.
Definition: create.cpp:770
bool isCliff() const
Definition: create.cpp:684
float normalizeAngle(const float &angle)
Definition: util.h:53
bool setAllMotors(const float &mainPower, const float &sidePower, const float &vacuumPower)
Set the power of all motors.
Definition: create.cpp:479
Matrix poseCovar
Definition: create.h:88
void disconnect()
Disconnect from serial.
Definition: create.cpp:314
void onData()
Definition: create.cpp:93
CreateMode
Definition: types.h:202
DayOfWeek
Definition: types.h:225
static const uint8_t STREAM_HEADER
Definition: util.h:43
float getAxleLength() const
Definition: types.cpp:31
float getLeftWheelDistance() const
Get the total distance the left wheel has moved.
Definition: create.cpp:1096
bool setMode(const create::CreateMode &mode)
Change Create mode.
Definition: create.cpp:325
create::CreateMode getMode()
Get the current mode reported by Create.
Definition: create.cpp:1120
~Create()
Attempts to disconnect from serial.
Definition: create.cpp:65
std::deque< float > dtHistory
Definition: create.h:85
bool isLightBumperRight() const
Definition: create.cpp:986
bool isLightBumperCenterLeft() const
Definition: create.cpp:956
uint16_t getLightSignalFrontRight() const
Get the signal strength from the front-right light sensor.
Definition: create.cpp:1036
bool defineSong(const uint8_t &songNumber, const uint8_t &songLength, const uint8_t *notes, const float *durations) const
Defines a song from the provided notes and labels it with a song number.
Definition: create.cpp:590


libcreate
Author(s): Jacob Perron
autogenerated on Sat May 8 2021 03:02:37