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;
47 serial = std::make_shared<SerialQuery>(
data, install_signal_handler);
49 serial = std::make_shared<SerialStream>(
55 init(install_signal_handler);
61 init(install_signal_handler);
62 serial->connect(dev, baud);
70 size_t rows = A.size1();
71 size_t cols = A.size2();
73 assert(rows == B.size1());
74 assert(cols == B.size2());
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);
83 C(i, j) = (a < 0.0) ? std::numeric_limits<float>::min() : std::numeric_limits<float>::max();
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;
110 float deltaYaw = 0.0f;
111 float leftWheelDist = 0.0f;
112 float rightWheelDist = 0.0f;
113 float wheelDistDiff = 0.0f;
116 int16_t angleField = 0;
121 std::memcpy(&distance, &distanceRaw,
sizeof(distance));
122 deltaDist = distance / 1000.0;
126 std::memcpy(&angleField, &angleRaw,
sizeof(angleField));
130 wheelDistDiff = 2.0 * angleField / 1000.0;
131 leftWheelDist = deltaDist - (wheelDistDiff / 2.0);
132 rightWheelDist = deltaDist + (wheelDistDiff / 2.0);
147 deltaYaw = angleField * (
util::PI / 180.0);
149 leftWheelDist = deltaDist - (wheelDistDiff / 2.0);
150 rightWheelDist = deltaDist + (wheelDistDiff / 2.0);
158 prevTicksLeft = totalTicksLeft;
159 prevTicksRight = totalTicksRight;
174 deltaDist = (rightWheelDist + leftWheelDist) / 2.0;
176 wheelDistDiff = rightWheelDist - leftWheelDist;
187 float dtHistorySum = 0;
192 auto dtAverage = dtHistorySum /
dtHistory.size();
199 deltaX = deltaDist * cos(
pose.
yaw);
200 deltaY = deltaDist * sin(
pose.
yaw);
202 float turnRadius = (
model.
getAxleLength() / 2.0) * (leftWheelDist + rightWheelDist) / wheelDistDiff;
204 deltaY = -turnRadius * (cos(
pose.
yaw + deltaYaw) - cos(
pose.
yaw));
211 vel.
x = deltaDist / dtAverage;
213 vel.
yaw = deltaYaw / dtAverage;
224 float cosYawAndHalfDelta = cos(
pose.
yaw + (deltaYaw / 2.0));
225 float sinYawAndHalfDelta = sin(
pose.
yaw + (deltaYaw / 2.0));
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);
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);
241 Matrix FincT = boost::numeric::ublas::trans(Finc);
246 Fp(0, 2) = (-deltaDist) * sinYawAndHalfDelta;
249 Fp(1, 2) = deltaDist * cosYawAndHalfDelta;
253 Matrix FpT = boost::numeric::ublas::trans(Fp);
255 Matrix velCovar = ublas::prod(invCovar, FincT);
256 velCovar = ublas::prod(Finc, velCovar);
269 poseCovarTmp = ublas::prod(Fp, poseCovarTmp);
294 bool timeout =
false;
297 float retryInterval = 5;
301 if (difftime(now, start) > maxWait) {
303 CERR(
"[create::Create] ",
"failed to connect over serial: timeout");
306 usleep(retryInterval * 1000000);
307 COUT(
"[create::Create] ",
"retrying to establish serial connection...");
334 CERR(
"[create::Create] ",
"protocol version 2 does not support turning robot off");
352 CERR(
"[create::Create] ",
"cannot set robot to mode '" << mode <<
"'");
370 if (day < 0 || day > 6 ||
375 uint8_t cmd[4] = {
OC_DATE, day, hour, min };
376 return serial->send(cmd, 4);
384 int16_t vel_mm = roundf(boundedVel * 1000);
385 int16_t radius_mm = roundf(radius * 1000);
388 if (radius_mm != -32768 && radius_mm != 32767 &&
389 radius_mm != -1 && radius_mm != 1) {
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)
400 return serial->send(cmd, 5);
409 int16_t leftCmd = roundf(boundedLeftVel * 1000);
410 int16_t rightCmd = roundf(boundedRightVel * 1000);
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)
418 return serial->send(cmd, 5);
422 if (boundedLeftVel != boundedRightVel) {
424 (boundedLeftVel - boundedRightVel);
431 if (boundedLeftVel == -boundedRightVel || std::abs(roundf(radius * 1000)) <= 1) {
433 vel = boundedRightVel;
435 vel = (std::abs(boundedLeftVel) + std::abs(boundedRightVel)) / 2.0 * ((boundedLeftVel + boundedRightVel) > 0 ? 1.0 : -1.0);
453 static const int16_t PWM_COUNTS = 255;
455 if (leftWheel < -1.0 || leftWheel > 1.0 ||
456 rightWheel < -1.0 || rightWheel > 1.0)
459 int16_t leftPwm = roundf(leftWheel * PWM_COUNTS);
460 int16_t rightPwm = roundf(rightWheel * PWM_COUNTS);
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)
469 return serial->send(cmd, 5);
480 if (main < -1.0 || main > 1.0 ||
481 side < -1.0 || side > 1.0 ||
482 vacuum < -1.0 || vacuum > 1.0)
491 static_cast<uint8_t
>((side != 0.0 ? 1 : 0) |
492 (vacuum != 0.0 ? 2 : 0) |
493 (main != 0.0 ? 4 : 0))
495 return serial->send(cmd, 2);
504 return serial->send(cmd, 4);
527 return serial->send(cmd, 4);
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)
587 return serial->send(cmd, 5);
591 const uint8_t& songLength,
592 const uint8_t* notes,
593 const float* durations)
const {
596 std::vector<uint8_t> cmd(2 * songLength + 3);
601 for (i = 3; i < 2 * songLength + 3; i = i + 2) {
602 if (durations[j] < 0 || durations[j] >= 4)
604 duration = durations[j] * 64;
606 cmd[i + 1] = duration;
610 return serial->send(cmd.data(), cmd.size());
616 uint8_t cmd[2] = {
OC_PLAY, songNumber };
617 return serial->send(cmd, 2);
629 CERR(
"[create::Create] ",
"Wheeldrop sensor not supported!");
639 CERR(
"[create::Create] ",
"Wheeldrop sensor not supported!");
649 CERR(
"[create::Create] ",
"Wheeldrop sensor not supported!");
659 CERR(
"[create::Create] ",
"Left bumper not supported!");
669 CERR(
"[create::Create] ",
"Right bumper not supported!");
679 CERR(
"[create::Create] ",
"Wall sensor not supported!");
695 CERR(
"[create::Create] ",
"Cliff sensors not supported!");
705 CERR(
"[create::Create] ",
"Left cliff sensors not supported!");
715 CERR(
"[create::Create] ",
"Front left cliff sensors not supported!");
725 CERR(
"[create::Create] ",
"Rightt cliff sensors not supported!");
735 CERR(
"[create::Create] ",
"Front right cliff sensors not supported!");
745 CERR(
"[create::Create] ",
"Virtual Wall sensor not supported!");
755 CERR(
"[create::Create] ",
"Dirt detector not supported!");
765 CERR(
"[create::Create] ",
"Omni IR sensor not supported!");
775 CERR(
"[create::Create] ",
"Left IR sensor not supported!");
785 CERR(
"[create::Create] ",
"Right IR sensor not supported!");
793 assert(chargeState <= 5);
797 CERR(
"[create::Create] ",
"Charging state not supported!");
807 CERR(
"[create::Create] ",
"Buttons not supported!");
814 CERR(
"[create::Create] ",
"Clock button is not supported!");
819 CERR(
"[create::Create] ",
"Buttons not supported!");
826 CERR(
"[create::Create] ",
"Schedule button is not supported!");
831 CERR(
"[create::Create] ",
"Buttons not supported!");
841 CERR(
"[create::Create] ",
"Buttons not supported!");
851 CERR(
"[create::Create] ",
"Buttons not supported!");
861 CERR(
"[create::Create] ",
"Buttons not supported!");
871 CERR(
"[create::Create] ",
"Buttons not supported!");
881 CERR(
"[create::Create] ",
"Buttons not supported!");
891 CERR(
"[create::Create] ",
"Voltage sensor not supported!");
901 CERR(
"[create::Create] ",
"Current sensor not supported!");
911 CERR(
"[create::Create] ",
"Temperature sensor not supported!");
921 CERR(
"[create::Create] ",
"Battery charge not supported!");
931 CERR(
"[create::Create] ",
"Battery capacity not supported!");
941 CERR(
"[create::Create] ",
"Light sensors not supported!");
951 CERR(
"[create::Create] ",
"Light sensors not supported!");
961 CERR(
"[create::Create] ",
"Light sensors not supported!");
971 CERR(
"[create::Create] ",
"Light sensors not supported!");
981 CERR(
"[create::Create] ",
"Light sensors not supported!");
991 CERR(
"[create::Create] ",
"Light sensors not supported!");
1001 CERR(
"[create::Create] ",
"Light sensors not supported!");
1011 CERR(
"[create::Create] ",
"Light sensors not supported!");
1021 CERR(
"[create::Create] ",
"Light sensors not supported!");
1031 CERR(
"[create::Create] ",
"Light sensors not supported!");
1041 CERR(
"[create::Create] ",
"Light sensors not supported!");
1051 CERR(
"[create::Create] ",
"Light sensors not supported!");
1061 CERR(
"[create::Create] ",
"Stasis sensor not supported!");
1071 CERR(
"[create::Create] ",
"Overcurrent sensor not supported!");
1081 CERR(
"[create::Create] ",
"Overcurrent sensor not supported!");
1091 CERR(
"[create::Create] ",
"Overcurrent sensor not supported!");
1136 return serial->getNumCorruptPackets();
1140 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)
void setDtHistoryLength(const uint8_t &dtHistoryLength)
Set dtHistoryLength parameter. Used to configure the size of the buffer for calculating average time ...
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.
void init(bool install_signal_handler)
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
Create(RobotModel model=RobotModel::CREATE_2, bool install_signal_handler=true)
Default constructor.
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)
std::chrono::time_point< std::chrono::steady_clock > prevOnDataTime
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
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)
bool setAllMotors(const float &mainPower, const float &sidePower, const float &vacuumPower)
Set the power of all motors.
void disconnect()
Disconnect from serial.
static const uint8_t STREAM_HEADER
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.
std::deque< float > dtHistory
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.