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)) 15 namespace ublas = boost::numeric::ublas;
58 serial->connect(dev, baud);
66 size_t rows = A.size1();
67 size_t cols = A.size2();
69 assert(rows == B.size1());
70 assert(cols == B.size2());
73 for (
size_t i = 0u; i < rows; i++) {
74 for (
size_t j = 0u; j < cols; j++) {
75 const float a = A(i, j);
76 const float b = B(i, j);
79 C(i, j) = (a < 0.0) ? std::numeric_limits<float>::min() : std::numeric_limits<float>::max();
101 auto curTime = std::chrono::system_clock::now();
102 float dt =
static_cast<std::chrono::duration<float>
>(curTime -
prevOnDataTime).count();
103 float deltaDist, deltaX, deltaY, deltaYaw, leftWheelDist, rightWheelDist, wheelDistDiff;
111 std::memcpy(&distance, &distanceRaw,
sizeof(distance));
112 deltaDist = distance / 1000.0;
116 std::memcpy(&angleField, &angleRaw,
sizeof(angleField));
120 wheelDistDiff = 2.0 * angleField / 1000.0;
121 leftWheelDist = deltaDist - (wheelDistDiff / 2.0);
122 rightWheelDist = deltaDist + (wheelDistDiff / 2.0);
137 deltaYaw = angleField * (
util::PI / 180.0);
139 leftWheelDist = deltaDist - (wheelDistDiff / 2.0);
140 rightWheelDist = deltaDist + (wheelDistDiff / 2.0);
148 prevTicksLeft = totalTicksLeft;
149 prevTicksRight = totalTicksRight;
164 deltaDist = (rightWheelDist + leftWheelDist) / 2.0;
166 wheelDistDiff = rightWheelDist - leftWheelDist;
175 deltaX = deltaDist * cos(
pose.
yaw);
176 deltaY = deltaDist * sin(
pose.
yaw);
178 float turnRadius = (
model.
getAxleLength() / 2.0) * (leftWheelDist + rightWheelDist) / wheelDistDiff;
180 deltaY = -turnRadius * (cos(
pose.
yaw + deltaYaw) - cos(
pose.
yaw));
187 vel.
x = deltaDist / dt;
200 float cosYawAndHalfDelta = cos(
pose.
yaw + (deltaYaw / 2.0));
201 float sinYawAndHalfDelta = sin(
pose.
yaw + (deltaYaw / 2.0));
205 invCovar(0, 0) = kr * fabs(rightWheelDist);
206 invCovar(0, 1) = 0.0;
207 invCovar(1, 0) = 0.0;
208 invCovar(1, 1) = kl * fabs(leftWheelDist);
211 Finc(0, 0) = (cosYawAndHalfDelta / 2.0) - (distOverTwoWB * sinYawAndHalfDelta);
212 Finc(0, 1) = (cosYawAndHalfDelta / 2.0) + (distOverTwoWB * sinYawAndHalfDelta);
213 Finc(1, 0) = (sinYawAndHalfDelta / 2.0) + (distOverTwoWB * cosYawAndHalfDelta);
214 Finc(1, 1) = (sinYawAndHalfDelta / 2.0) - (distOverTwoWB * cosYawAndHalfDelta);
217 Matrix FincT = boost::numeric::ublas::trans(Finc);
222 Fp(0, 2) = (-deltaDist) * sinYawAndHalfDelta;
225 Fp(1, 2) = deltaDist * cosYawAndHalfDelta;
229 Matrix FpT = boost::numeric::ublas::trans(Fp);
231 Matrix velCovar = ublas::prod(invCovar, FincT);
232 velCovar = ublas::prod(Finc, velCovar);
245 poseCovarTmp = ublas::prod(Fp, poseCovarTmp);
270 bool timeout =
false;
273 float retryInterval = 5;
277 if (difftime(now, start) > maxWait) {
279 CERR(
"[create::Create] ",
"failed to connect over serial: timeout");
282 usleep(retryInterval * 1000000);
283 COUT(
"[create::Create] ",
"retrying to establish serial connection...");
310 CERR(
"[create::Create] ",
"protocol version 2 does not support turning robot off");
328 CERR(
"[create::Create] ",
"cannot set robot to mode '" << mode <<
"'");
346 if (day < 0 || day > 6 ||
351 uint8_t cmd[4] = {
OC_DATE, day, hour, min };
352 return serial->send(cmd, 4);
360 int16_t vel_mm = roundf(boundedVel * 1000);
361 int16_t radius_mm = roundf(radius * 1000);
364 if (radius_mm != -32768 && radius_mm != 32767 &&
365 radius_mm != -1 && radius_mm != 1) {
370 static_cast<uint8_t
>(vel_mm >> 8),
371 static_cast<uint8_t>(vel_mm & 0xff),
372 static_cast<uint8_t
>(radius_mm >> 8),
373 static_cast<uint8_t>(radius_mm & 0xff)
376 return serial->send(cmd, 5);
385 int16_t leftCmd = roundf(boundedLeftVel * 1000);
386 int16_t rightCmd = roundf(boundedRightVel * 1000);
389 static_cast<uint8_t
>(rightCmd >> 8),
390 static_cast<uint8_t>(rightCmd & 0xff),
391 static_cast<uint8_t
>(leftCmd >> 8),
392 static_cast<uint8_t>(leftCmd & 0xff)
394 return serial->send(cmd, 5);
398 if (boundedLeftVel != boundedRightVel) {
400 (boundedLeftVel - boundedRightVel);
407 if (boundedLeftVel == -boundedRightVel || std::abs(roundf(radius * 1000)) <= 1) {
409 vel = boundedRightVel;
411 vel = (std::abs(boundedLeftVel) + std::abs(boundedRightVel)) / 2.0 * ((boundedLeftVel + boundedRightVel) > 0 ? 1.0 : -1.0);
429 static const int16_t PWM_COUNTS = 255;
431 if (leftWheel < -1.0 || leftWheel > 1.0 ||
432 rightWheel < -1.0 || rightWheel > 1.0)
435 int16_t leftPwm = roundf(leftWheel * PWM_COUNTS);
436 int16_t rightPwm = roundf(rightWheel * PWM_COUNTS);
439 static_cast<uint8_t
>(rightPwm >> 8),
440 static_cast<uint8_t>(rightPwm & 0xff),
441 static_cast<uint8_t
>(leftPwm >> 8),
442 static_cast<uint8_t>(leftPwm & 0xff)
445 return serial->send(cmd, 5);
456 if (main < -1.0 || main > 1.0 ||
457 side < -1.0 || side > 1.0 ||
458 vacuum < -1.0 || vacuum > 1.0)
467 static_cast<uint8_t
>((side != 0.0 ? 1 : 0) |
468 (vacuum != 0.0 ? 2 : 0) |
469 (main != 0.0 ? 4 : 0))
471 return serial->send(cmd, 2);
480 return serial->send(cmd, 4);
503 return serial->send(cmd, 4);
549 const uint8_t& digit3,
const uint8_t& digit4)
const {
550 if (digit1 < 32 || digit1 > 126 ||
551 digit2 < 32 || digit2 > 126 ||
552 digit3 < 32 || digit3 > 126 ||
553 digit4 < 32 || digit4 > 126)
563 return serial->send(cmd, 5);
567 const uint8_t& songLength,
568 const uint8_t* notes,
569 const float* durations)
const {
572 std::vector<uint8_t> cmd(2 * songLength + 3);
577 for (i = 3; i < 2 * songLength + 3; i = i + 2) {
578 if (durations[j] < 0 || durations[j] >= 4)
580 duration = durations[j] * 64;
582 cmd[i + 1] = duration;
586 return serial->send(cmd.data(), cmd.size());
592 uint8_t cmd[2] = {
OC_PLAY, songNumber };
593 return serial->send(cmd, 2);
601 CERR(
"[create::Create] ",
"Wheeldrop sensor not supported!");
611 CERR(
"[create::Create] ",
"Wheeldrop sensor not supported!");
621 CERR(
"[create::Create] ",
"Wheeldrop sensor not supported!");
631 CERR(
"[create::Create] ",
"Left bumper not supported!");
641 CERR(
"[create::Create] ",
"Right bumper not supported!");
651 CERR(
"[create::Create] ",
"Wall sensor not supported!");
667 CERR(
"[create::Create] ",
"Cliff sensors not supported!");
677 CERR(
"[create::Create] ",
"Left cliff sensors not supported!");
687 CERR(
"[create::Create] ",
"Front left cliff sensors not supported!");
697 CERR(
"[create::Create] ",
"Rightt cliff sensors not supported!");
707 CERR(
"[create::Create] ",
"Front right cliff sensors not supported!");
717 CERR(
"[create::Create] ",
"Virtual Wall sensor not supported!");
727 CERR(
"[create::Create] ",
"Dirt detector not supported!");
737 CERR(
"[create::Create] ",
"Omni IR sensor not supported!");
747 CERR(
"[create::Create] ",
"Left IR sensor not supported!");
757 CERR(
"[create::Create] ",
"Right IR sensor not supported!");
765 assert(chargeState <= 5);
769 CERR(
"[create::Create] ",
"Charging state not supported!");
779 CERR(
"[create::Create] ",
"Buttons not supported!");
786 CERR(
"[create::Create] ",
"Clock button is not supported!");
791 CERR(
"[create::Create] ",
"Buttons not supported!");
798 CERR(
"[create::Create] ",
"Schedule button is not supported!");
803 CERR(
"[create::Create] ",
"Buttons not supported!");
813 CERR(
"[create::Create] ",
"Buttons not supported!");
823 CERR(
"[create::Create] ",
"Buttons not supported!");
833 CERR(
"[create::Create] ",
"Buttons not supported!");
843 CERR(
"[create::Create] ",
"Buttons not supported!");
853 CERR(
"[create::Create] ",
"Buttons not supported!");
863 CERR(
"[create::Create] ",
"Voltage sensor not supported!");
873 CERR(
"[create::Create] ",
"Current sensor not supported!");
883 CERR(
"[create::Create] ",
"Temperature sensor not supported!");
893 CERR(
"[create::Create] ",
"Battery charge not supported!");
903 CERR(
"[create::Create] ",
"Battery capacity not supported!");
913 CERR(
"[create::Create] ",
"Light sensors not supported!");
923 CERR(
"[create::Create] ",
"Light sensors not supported!");
933 CERR(
"[create::Create] ",
"Light sensors not supported!");
943 CERR(
"[create::Create] ",
"Light sensors not supported!");
953 CERR(
"[create::Create] ",
"Light sensors not supported!");
963 CERR(
"[create::Create] ",
"Light sensors not supported!");
973 CERR(
"[create::Create] ",
"Light sensors not supported!");
983 CERR(
"[create::Create] ",
"Light sensors not supported!");
993 CERR(
"[create::Create] ",
"Light sensors not supported!");
1003 CERR(
"[create::Create] ",
"Light sensors not supported!");
1013 CERR(
"[create::Create] ",
"Light sensors not supported!");
1023 CERR(
"[create::Create] ",
"Light sensors not supported!");
1033 CERR(
"[create::Create] ",
"Stasis sensor not supported!");
1043 CERR(
"[create::Create] ",
"Overcurrent sensor not supported!");
1053 CERR(
"[create::Create] ",
"Overcurrent sensor not supported!");
1063 CERR(
"[create::Create] ",
"Overcurrent sensor not supported!");
1108 return serial->getNumCorruptPackets();
1112 return serial->getTotalPackets();
uint64_t getTotalPackets() const
Get the total number of serial packets received (including corrupt packets) since first connecting to...
bool setSideMotor(const float &power)
Set the power to the side brush motor.
uint8_t getIROmni() const
Get value of 8-bit IR character currently being received by omnidirectional sensor.
uint8_t powerLEDIntensity
bool isLeftWheeldrop() const
static const float IN_PLACE_RADIUS
float getMeasuredRightWheelVel() const
Get the measured velocity of the right wheel.
bool setVacuumMotor(const float &power)
Set the power to the vacuum motor.
bool isWheelOvercurrent() const
bool isLightBumperFrontLeft() const
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...
bool isCliffRight() const
bool isLeftBumper() const
create::ChargingState getChargingState() const
Get the current charging state.
bool driveWheels(const float &leftWheel, const float &rightWheel)
Set the velocities for the left and right wheels.
bool dock() const
Starts the docking behaviour. Changes mode to MODE_PASSIVE.
int8_t getTemperature() const
Get the temperature of battery.
bool isHourButtonPressed() const
Get state of 'hour' button.
bool isClockButtonPressed() const
Not supported by any firmware!
uint16_t getLightSignalFrontLeft() const
Get the signal strength from the front-left light sensor.
bool isLightBumperCenterRight() const
float getRequestedLeftWheelVel() const
Get the requested velocity of the left wheel. This value is bounded at the maximum velocity of the ro...
#define BOUND(val, min, max)
bool setDate(const create::DayOfWeek &day, const uint8_t &hour, const uint8_t &min) const
Sets the internal clock of Create.
float getRightWheelDistance() const
Get the total distance the right wheel has moved.
create::Pose getPose() const
Get the estimated pose of Create based on wheel encoders.
uint8_t getDirtDetect() const
Get level of the dirt detect sensor.
float getRequestedRightWheelVel() const
Get the requested velocity of the right wheel. This value is bounded at the maximum velocity of the r...
bool enableDockLED(const bool &enable)
Set the green "dock" LED on/off.
bool setPowerLED(const uint8_t &power, const uint8_t &intensity=255)
Set the center power LED.
bool isLightBumperFrontRight() const
float getBatteryCharge() const
Get battery's remaining charge.
uint8_t getIRRight() const
Get value of 8-bit IR character currently being received by right sensor.
float getCurrent() const
Get current flowing in/out of battery. A positive current implies Create is charging.
bool driveWheelsPwm(const float &leftWheel, const float &rightWheel)
Set the direct for the left and right wheels.
ProtocolVersion getVersion() const
std::shared_ptr< create::Data > data
bool isVirtualWall() const
bool isCliffFrontRight() const
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...
bool isMovingForward() const
Matrix addMatrices(const Matrix &A, const Matrix &B) const
std::vector< float > covariance
3x3 covariance matrix in row-major order.
create::Vel getVel() const
Get the estimated velocity of Create based on wheel encoders.
uint64_t getNumCorruptPackets() const
Get the number of corrupt serial packets since first connecting to Create. This value is ideally zero...
int main(int argc, char **argv)
uint16_t getLightSignalCenterLeft() const
Get the signal strength from the center-left light sensor.
float getMaxVelocity() const
static const float V_3_TICKS_PER_REV
std::shared_ptr< create::Serial > serial
#define CERR(prefix, msg)
bool isLightBumperLeft() const
bool clean(const create::CleanMode &mode=CLEAN_DEFAULT)
Starts a cleaning mode. Changes mode to MODE_PASSIVE.
float getWheelDiameter() const
bool isScheduleButtonPressed() const
Not supported by any firmware!
bool enableCheckRobotLED(const bool &enable)
Set the orange "check Create" LED on/off.
bool driveRadius(const float &velocity, const float &radius)
Set the average wheel velocity and turning radius of Create.
static const uint32_t V_3_MAX_ENCODER_TICKS
bool enableSpotLED(const bool &enable)
Set the green "spot" LED on/off.
bool setMainMotor(const float &power)
Set the power to the main brush motor.
bool isMinButtonPressed() const
Get state of 'min' button.
bool isCleanButtonPressed() const
Get state of 'clean' button ('play' button on Create 1).
bool drive(const float &xVel, const float &angularVel)
Set the forward and angular velocity of Create.
bool isDockButtonPressed() const
Get state of 'dock' button ('advance' button on Create 1).
float getMeasuredLeftWheelVel() const
Get the measured velocity of the left wheel.
boost::numeric::ublas::matrix< float > Matrix
bool enableDebrisLED(const bool &enable)
Set the blue "debris" LED on/off.
#define BOUND_CONST(val, min, max)
float getVoltage() const
Get battery voltage.
uint16_t getLightSignalLeft() const
Get the signal strength from the left light sensor.
bool isMainBrushOvercurrent() const
static const float MAX_RADIUS
bool isRightWheeldrop() const
bool isRightBumper() const
bool isDayButtonPressed() const
Get state of 'day' button.
bool willFloatOverflow(const float a, const float b)
uint16_t getLightSignalCenterRight() const
Get the signal strength from the center-right light sensor.
static const float STRAIGHT_RADIUS
#define COUT(prefix, msg)
bool isSpotButtonPressed() const
Get state of 'spot' button.
bool isCliffFrontLeft() const
Create(RobotModel model=RobotModel::CREATE_2)
Default constructor.
uint16_t getLightSignalRight() const
Get the signal strength from the right light sensor.
bool isSideBrushOvercurrent() const
float getBatteryCapacity() const
Get estimated battery charge capacity.
bool connect(const std::string &port, const int &baud)
Make a serial connection to Create.
uint8_t getIRLeft() const
Get value of 8-bit IR character currently being received by left sensor.
float normalizeAngle(const float &angle)
std::chrono::time_point< std::chrono::system_clock > prevOnDataTime
bool setAllMotors(const float &mainPower, const float &sidePower, const float &vacuumPower)
Set the power of all motors.
void disconnect()
Disconnect from serial.
float getAxleLength() const
float getLeftWheelDistance() const
Get the total distance the left wheel has moved.
bool setMode(const create::CreateMode &mode)
Change Create mode.
create::CreateMode getMode()
Get the current mode reported by Create.
~Create()
Attempts to disconnect from serial.
bool isLightBumperRight() const
bool isLightBumperCenterLeft() const
uint16_t getLightSignalFrontRight() const
Get the signal strength from the front-right light sensor.
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.