35 : model_(
create::RobotModel::CREATE_2),
39 is_running_slowly_(false)
41 std::string robot_model_name;
43 priv_nh_.
param<std::string>(
"robot_model", robot_model_name,
"CREATE_2");
50 if (robot_model_name ==
"ROOMBA_400")
54 else if (robot_model_name ==
"CREATE_1")
58 else if (robot_model_name ==
"CREATE_2")
64 ROS_FATAL_STREAM(
"[CREATE] Robot model \"" + robot_model_name +
"\" is not known.");
75 if (!robot_->connect(dev_, baud_))
77 ROS_FATAL(
"[CREATE] Failed to establish serial connection with Create.");
81 ROS_INFO(
"[CREATE] Connection established.");
87 ROS_INFO(
"[CREATE] Battery level %.2f %%", (robot_->getBatteryCharge() / robot_->getBatteryCapacity()) * 100.0);
105 for (
int i = 0; i < 36; i++)
162 ROS_INFO(
"[CREATE] Destruct sequence initiated.");
195 if (msg->data.size() < 1)
197 ROS_ERROR(
"[CREATE] No values provided to set power LED");
201 if (msg->data.size() < 2)
215 if (msg->data.size() < 1)
217 ROS_ERROR(
"[CREATE] No ASCII digits provided");
219 else if (msg->data.size() < 2)
223 else if (msg->data.size() < 3)
227 else if (msg->data.size() < 4)
238 ROS_ERROR(
"[CREATE] ASCII character out of range [32, 126]");
265 if (!
robot_->
defineSong(msg->song, msg->length, &(msg->notes.front()), &(msg->durations.front())))
267 ROS_ERROR_STREAM(
"[CREATE] Failed to define song " << msg->song <<
" of length " << msg->length);
283 ROS_ERROR_STREAM(
"[CREATE] Failed to set duty cycle " << msg->duty_cycle <<
" for side brush motor");
290 ROS_ERROR_STREAM(
"[CREATE] Failed to set duty cycle " << msg->duty_cycle <<
" for main motor");
297 ROS_ERROR_STREAM(
"[CREATE] Failed to set duty cycle " << msg->duty_cycle <<
" for vacuum motor");
326 const float charge_ratio = charge / capacity;
330 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"Charging fault reported by base");
332 else if (charge_ratio == 0)
334 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"Battery reports no charge");
336 else if (charge_ratio < 0.1)
338 stat.
summary(diagnostic_msgs::DiagnosticStatus::WARN,
"Battery reports less than 10% charge");
342 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Battery is OK");
345 stat.
add(
"Charge (Ah)", charge);
346 stat.
add(
"Capacity (Ah)", capacity);
351 switch (charging_state)
354 stat.
add(
"Charging state",
"Not charging");
357 stat.
add(
"Charging state",
"Reconditioning");
360 stat.
add(
"Charging state",
"Full charge");
363 stat.
add(
"Charging state",
"Trickle charging");
366 stat.
add(
"Charging state",
"Waiting");
369 stat.
add(
"Charging state",
"Fault");
380 stat.
summary(diagnostic_msgs::DiagnosticStatus::WARN,
"Wheeldrop detected");
384 stat.
summary(diagnostic_msgs::DiagnosticStatus::WARN,
"Cliff detected");
388 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"No safety issues detected");
391 stat.
add(
"Wheeldrop", is_wheeldrop);
392 stat.
add(
"Cliff", is_cliff);
403 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"Serial port to base not open");
405 else if (corrupt_packets)
407 stat.
summary(diagnostic_msgs::DiagnosticStatus::WARN,
408 "Corrupt packets detected. If the number of corrupt packets is increasing, data may be unreliable");
412 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Serial connection is good");
415 stat.
add(
"Corrupt packets", corrupt_packets);
416 stat.
add(
"Total packets", total_packets);
425 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"Unknown mode of operation");
428 stat.
summary(diagnostic_msgs::DiagnosticStatus::WARN,
"Mode is set to OFF");
431 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Mode is set to PASSIVE");
434 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Mode is set to SAFE");
437 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Mode is set to FULL");
446 stat.
summary(diagnostic_msgs::DiagnosticStatus::WARN,
"Internal loop running slowly");
450 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Maintaining loop frequency");
462 geometry_msgs::Quaternion quat =
tf2::toMsg(tf_quat);
496 tf_odom_.transform.translation.x = pose.
x;
497 tf_odom_.transform.translation.y = pose.
y;
535 switch (charging_state)
618 ROS_ERROR(
"[CREATE] Unknown mode detected");
673 ROS_WARN(
"[CREATE] Loop running slowly.");
678 int main(
int argc,
char** argv)
687 create_driver.
spin();
689 catch (std::runtime_error& ex)
bool isDockButtonPressed() const
void mainBrushMotor(const create_msgs::MotorSetpointConstPtr &msg)
void updateDriverDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
bool setSideMotor(const float &power)
create_msgs::Bumper bumper_msg_
bool isLightBumperLeft() const
bool isSpotButtonPressed() const
uint16_t getLightSignalLeft() const
void debrisLEDCallback(const std_msgs::BoolConstPtr &msg)
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
ros::Subscriber define_song_sub_
uint16_t getLightSignalCenterRight() const
ProtocolVersion getVersion() const
ros::Subscriber power_led_sub_
ros::Subscriber set_ascii_sub_
ros::Time last_cmd_vel_time_
create_msgs::Mode mode_msg_
void checkLEDCallback(const std_msgs::BoolConstPtr &msg)
ros::Subscriber dock_led_sub_
ros::Subscriber spot_led_sub_
bool setVacuumMotor(const float &power)
ros::Publisher wheel_joint_pub_
void updateSafetyDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
ros::Publisher voltage_pub_
void summary(unsigned char lvl, const std::string s)
ros::Publisher charging_state_pub_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void updateBatteryDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
float getWheelDiameter() const
static RobotModel CREATE_1
ros::Publisher omni_char_pub_
void setHardwareID(const std::string &hwid)
uint16_t getLightSignalRight() const
bool isHourButtonPressed() const
ros::Publisher min_btn_pub_
void publishButtonPresses() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
ros::Publisher bumper_pub_
void add(const std::string &name, TaskFunction f)
bool setDigitsASCII(const uint8_t &digit1, const uint8_t &digit2, const uint8_t &digit3, const uint8_t &digit4) const
ros::Subscriber check_led_sub_
float getBatteryCapacity() const
std_msgs::Float32 float32_msg_
diagnostic_updater::Updater diagnostics_
CreateDriver(ros::NodeHandle &nh)
std_msgs::UInt16 uint16_msg_
ros::Publisher temperature_pub_
ros::Subscriber debris_led_sub_
void dockCallback(const std_msgs::EmptyConstPtr &msg)
bool isCleanButtonPressed() const
bool isLightBumperCenterRight() const
ros::Subscriber side_brush_motor_sub_
ros::Publisher clean_btn_pub_
void playSongCallback(const create_msgs::PlaySongConstPtr &msg)
bool isLeftBumper() const
ros::Subscriber play_song_sub_
ros::Subscriber main_brush_motor_sub_
bool enableDockLED(const bool &enable)
bool setPowerLED(const uint8_t &power, const uint8_t &intensity=255)
unsigned int getBaud() const
ros::Publisher day_btn_pub_
void cmdVelCallback(const geometry_msgs::TwistConstPtr &msg)
ros::Publisher charge_ratio_pub_
nav_msgs::Odometry odom_msg_
void setASCIICallback(const std_msgs::UInt8MultiArrayConstPtr &msg)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
uint16_t getLightSignalFrontRight() const
void publish(const boost::shared_ptr< M > &message) const
void updateSerialDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
ros::Subscriber vacuum_motor_sub_
ros::Publisher dock_btn_pub_
std::vector< float > covariance
#define ROS_FATAL_STREAM(args)
std_msgs::Int16 int16_msg_
ros::Subscriber cmd_vel_sub_
void spotLEDCallback(const std_msgs::BoolConstPtr &msg)
float getRequestedRightWheelVel() const
uint16_t getLightSignalCenterLeft() const
float getLeftWheelDistance() const
void updateModeDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
bool enableCheckRobotLED(const bool &enable)
bool enableSpotLED(const bool &enable)
void powerLEDCallback(const std_msgs::UInt8MultiArrayConstPtr &msg)
void publishBatteryInfo()
bool setMainMotor(const float &power)
uint64_t getNumCorruptPackets() const
static const double COVARIANCE[36]
bool drive(const float &xVel, const float &angularVel)
int main(int argc, char **argv)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ros::Publisher hour_btn_pub_
create_msgs::ChargingState charging_state_msg_
uint8_t getIROmni() const
bool isLightBumperFrontRight() const
bool enableDebrisLED(const bool &enable)
ros::Subscriber dock_sub_
void sideBrushMotor(const create_msgs::MotorSetpointConstPtr &msg)
uint64_t getTotalPackets() const
ros::Publisher capacity_pub_
ros::Publisher wheeldrop_pub_
create::ChargingState getChargingState() const
bool isRightBumper() const
float getRightWheelDistance() const
ros::Publisher charge_pub_
bool isLightBumperRight() const
#define ROS_INFO_STREAM(args)
tf2_ros::TransformBroadcaster tf_broadcaster_
std_msgs::Empty empty_msg_
bool isMinButtonPressed() const
int8_t getTemperature() const
bool defineSong(const uint8_t &songNumber, const uint8_t &songLength, const uint8_t *notes, const float *durations) const
void undockCallback(const std_msgs::EmptyConstPtr &msg)
bool playSong(const uint8_t &songNumber) const
void dockLEDCallback(const std_msgs::BoolConstPtr &msg)
ROSCPP_DECL void shutdown()
static RobotModel CREATE_2
ros::Subscriber undock_sub_
void add(const std::string &key, const T &val)
bool isLightBumperFrontLeft() const
create::RobotModel model_
#define ROS_ERROR_STREAM(args)
ros::Publisher current_pub_
void defineSongCallback(const create_msgs::DefineSongConstPtr &msg)
bool isLightBumperCenterLeft() const
ROSCPP_DECL void spinOnce()
ros::Publisher spot_btn_pub_
static RobotModel ROOMBA_400
geometry_msgs::TransformStamped tf_odom_
void vacuumBrushMotor(const create_msgs::MotorSetpointConstPtr &msg)
uint16_t getLightSignalFrontLeft() const
create::Vel getVel() const
create::Pose getPose() const
bool setMode(const create::CreateMode &mode)
create::CreateMode getMode()
float getBatteryCharge() const
float getRequestedLeftWheelVel() const
sensor_msgs::JointState joint_state_msg_
bool isDayButtonPressed() const