11 #include <sys/ioctl.h> 14 #include "std_msgs/Int32.h" 15 #include "std_msgs/Int32MultiArray.h" 16 #include "std_msgs/Float32MultiArray.h" 17 #include "geometry_msgs/TwistStamped.h" 18 #include <std_msgs/Bool.h> 19 #include "nav_msgs/Odometry.h" 20 #include "rr_openrover_basic/RawRrOpenroverBasicFastRateData.h" 21 #include "rr_openrover_basic/RawRrOpenroverBasicMedRateData.h" 22 #include "rr_openrover_basic/RawRrOpenroverBasicSlowRateData.h" 23 #include "rr_openrover_basic/SmartBatteryStatus.h" 33 , port_(
"/dev/ttyUSB0")
34 , serial_baud_rate_(57600)
36 , medium_rate_hz_(2.0)
57 ROS_INFO(
"Initializing openrover driver.");
68 ROS_WARN(
"Failed to setup Robot parameters.");
80 ROS_INFO(
"Creating Publishers and Subscribers");
110 ROS_WARN(
"Failed to retrieve port from parameter server.Defaulting to %s",
port_.c_str());
116 ROS_ERROR(
"Failed to start serial communication.");
122 ROS_WARN(
"Failed to retrieve fast_data_rate from parameter. Defaulting to 10");
127 ROS_WARN(
"Failed to retrieve medium_data_rate from parameter. Defaulting to 2");
132 ROS_WARN(
"Failed to retrieve slow_data_rate from parameter. Defaulting to 1");
138 ROS_WARN(
"Failed to retrieve closed_loop_control_on from parameter server. Defaulting to off.");
143 ROS_WARN(
"Failed to retrieve timeout from parameter server. Defaulting to %f s",
timeout_);
148 ROS_WARN(
"Failed to retrieve total_weight from parameter server. Defaulting to %f lbs",
total_weight_);
153 ROS_WARN(
"Failed to retrieve drive_type from parameter.Defaulting to %s",
drive_type_.c_str());
182 ROS_INFO(
"flipper parameters loaded.");
194 ROS_WARN(
"Unclear ROS param drive_type. Defaulting to flippers params.");
213 ROS_WARN(
"Failed to retrieve odom_covariance_0 from parameter. Defaulting to 0.01");
219 ROS_WARN(
"Failed to retrieve odom_covariance_35 from parameter. Defaulting to 0.03");
223 ROS_INFO(
"Openrover parameters loaded:");
305 float left_motor_speed, right_motor_speed;
306 int flipper_motor_speed;
307 int motor_speed_deadband_scaled;
308 double turn_rate = msg->twist.angular.z;
309 double linear_rate = msg->twist.linear.x;
310 double flipper_rate = msg->twist.angular.y;
311 std::string frame_id = msg->header.frame_id;
320 if (frame_id == (std::string)
"soft e-stopped")
325 ROS_WARN(
"Openrover driver - Soft e-stop on.");
334 ROS_INFO(
"Openrover driver - Soft e-stop off.");
348 static double left_dist = 0;
349 static double right_dist = 0;
350 static double pos_x = 0;
351 static double pos_y = 0;
352 static double theta = 0;
353 static double past_time = 0;
361 double now_time = ros_now_time.
toSec();
363 nav_msgs::Odometry odom_msg;
365 dt = now_time - past_time;
366 past_time = now_time;
370 left_dist += left_vel * dt;
371 right_dist += right_vel * dt;
373 net_vel = 0.5 * (left_vel + right_vel);
374 diff_vel = right_vel - left_vel;
378 pos_x = pos_x + net_vel * cos(theta) * dt;
379 pos_y = pos_y + net_vel * sin(theta) * dt;
380 theta = (theta + alpha * dt);
383 quaternionTFToMsg(q_new, odom_msg.pose.pose.orientation);
386 odom_msg.header.stamp = ros_now_time;
387 odom_msg.header.frame_id =
"odom";
388 odom_msg.child_frame_id =
"base_link";
390 odom_msg.twist.twist.linear.x = net_vel;
391 odom_msg.twist.twist.angular.z = alpha;
395 if (net_vel == 0 && alpha == 0)
408 odom_msg.pose.pose.position.x = pos_x;
409 odom_msg.pose.pose.position.y = pos_y;
419 double run_time = (ros_now_time - ros_start_time).toSec();
420 std_msgs::Float32MultiArray vel_vec;
439 rr_openrover_basic::RawRrOpenroverBasicFastRateData
msg;
442 msg.header.frame_id =
"";
454 rr_openrover_basic::RawRrOpenroverBasicMedRateData med_msg;
455 std_msgs::Bool is_charging_msg;
458 med_msg.header.frame_id =
"";
477 is_charging_msg.data =
true;
483 is_charging_msg.data =
false;
494 rr_openrover_basic::SmartBatteryStatus status_msg;
495 status_msg.over_charged_alarm = bool(bits & 0x8000);
496 status_msg.terminate_charge_alarm = bool(bits & 0x4000);
497 status_msg.over_temp_alarm = bool(bits & 0x1000);
498 status_msg.terminate_discharge_alarm = bool(bits & 0x0800);
499 status_msg.remaining_capacity_alarm = bool(bits & 0x0200);
500 status_msg.remaining_time_alarm = bool(bits & 0x0100);
501 status_msg.initialized = bool(bits & 0x0080);
502 status_msg.discharging = bool(bits & 0x0040);
503 status_msg.fully_charged = bool(bits & 0x0020);
504 status_msg.fully_discharged = bool(bits & 0x0010);
510 rr_openrover_basic::RawRrOpenroverBasicSlowRateData slow_msg;
511 rr_openrover_basic::SmartBatteryStatus batteryStatusA;
514 slow_msg.header.frame_id =
"";
541 std_msgs::Int32MultiArray motor_speeds_msg;
542 motor_speeds_msg.data.clear();
553 unsigned char param1;
554 unsigned char param2;
555 static double past_time = 0;
569 ROS_DEBUG(
"Its fast data's turn to be sent: %i", param2);
576 ROS_DEBUG(
"Its fan speed's turn to be sent: %i", param2);
583 ROS_DEBUG(
"Its medium data's turn to be sent: %i", param2);
590 ROS_DEBUG(
"Its slow data's turn to be sent: %i", param2);
605 else if (param1 == 20)
609 else if (param1 == 250)
613 else if (param1 == 0)
618 throw std::string(
"Unknown param1. Removing parameter from buffer");
621 catch (std::string
s)
634 double now_time = ros_now_time.
toSec();
636 double dt = now_time - past_time;
637 past_time = now_time;
724 catch (std::string
s)
727 sprintf(str_ex,
"Failed to update param %i. ", param);
728 throw std::string(str_ex) + s;
741 write_buffer[4] = (
unsigned char)param1;
742 write_buffer[5] = (
unsigned char)param2;
745 (char)255 - (write_buffer[1] + write_buffer[2] + write_buffer[3] + write_buffer[4] + write_buffer[5]) % 255;
749 ROS_INFO(
"Serial communication failed. Attempting to restart.");
752 ROS_WARN(
"Failed to restart serial communication.");
759 sprintf(str_ex,
"Failed to send command: %02x,%02x,%02x,%02x,%02x,%02x,%02x", write_buffer[0], write_buffer[1],
760 write_buffer[2], write_buffer[3], write_buffer[4], write_buffer[5], write_buffer[6]);
761 throw std::string(str_ex);
769 unsigned char read_buffer[1];
770 unsigned char start_byte_read, checksum, read_checksum, data1, data2, dataNO;
774 ROS_INFO(
"Serial communication failed. Attempting to restart.");
777 ROS_WARN(
"Failed to restart serial communication.");
782 start_byte_read = read_buffer[0];
785 dataNO = read_buffer[0];
788 data1 = read_buffer[0];
791 data2 = read_buffer[0];
794 read_checksum = read_buffer[0];
796 checksum = 255 - (dataNO + data1 + data2) % 255;
801 sprintf(str_ex,
"Received bad start byte. Received: %02x", start_byte_read);
803 throw std::string(str_ex);
805 else if (checksum != read_checksum)
808 sprintf(str_ex,
"Received bad CRC. Received: %02x,%02x,%02x,%02x,%02x", start_byte_read, dataNO, data1, data2,
811 throw std::string(str_ex);
813 data = (data1 << 8) + data2;
828 catch (std::string
s)
830 std::string s2(
"setParameterData() failed. ");
854 catch (std::string
s)
856 std::string s2(
"getParameterData() failed. ");
864 struct termios serial_port_fd__options;
867 if (serial_port_fd_ < 0)
869 ROS_ERROR(
"Failed to open port: %s", strerror(errno));
872 if (0 > fcntl(serial_port_fd_, F_SETFL, 0))
874 ROS_ERROR(
"Failed to set port descriptor: %s", strerror(errno));
877 if (0 > tcgetattr(serial_port_fd_, &serial_port_fd__options))
879 ROS_ERROR(
"Failed to fetch port attributes: %s", strerror(errno));
882 if (0 > cfsetispeed(&serial_port_fd__options, B57600))
884 ROS_ERROR(
"Failed to set input baud: %s", strerror(errno));
887 if (0 > cfsetospeed(&serial_port_fd__options, B57600))
889 ROS_ERROR(
"Failed to set output baud: %s", strerror(errno));
893 serial_port_fd__options.c_cflag |= (CREAD | CLOCAL | CS8);
894 serial_port_fd__options.c_cflag &= ~(PARODD | CRTSCTS | CSTOPB | PARENB);
895 serial_port_fd__options.c_iflag &= ~(IUCLC | IXANY | IMAXBEL | IXON | IXOFF | IUTF8 | ICRNL | INPCK);
896 serial_port_fd__options.c_oflag |= (NL0 | CR0 | TAB0 | BS0 | VT0 | FF0);
897 serial_port_fd__options.c_oflag &=
898 ~(OPOST | ONLCR | OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL | NL1 | CR1 | CR2 | TAB3 | BS1 | VT1 | FF1);
899 serial_port_fd__options.c_lflag |= (NOFLSH);
900 serial_port_fd__options.c_lflag &= ~(ICANON | IEXTEN | TOSTOP | ISIG | ECHOPRT | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE);
901 serial_port_fd__options.c_cc[VINTR] = 0x03;
902 serial_port_fd__options.c_cc[VQUIT] = 0x1C;
903 serial_port_fd__options.c_cc[VERASE] = 0x7F;
904 serial_port_fd__options.c_cc[VKILL] = 0x15;
905 serial_port_fd__options.c_cc[VEOF] = 0x04;
906 serial_port_fd__options.c_cc[VTIME] = 0x01;
907 serial_port_fd__options.c_cc[VMIN] = 0;
908 serial_port_fd__options.c_cc[VSWTC] = 0x00;
910 serial_port_fd__options.c_cc[VSTOP] = 0x13;
911 serial_port_fd__options.c_cc[VSUSP] = 0x1A;
912 serial_port_fd__options.c_cc[VEOL] = 0x00;
913 serial_port_fd__options.c_cc[VREPRINT] = 0x12;
914 serial_port_fd__options.c_cc[VDISCARD] = 0x0F;
915 serial_port_fd__options.c_cc[VWERASE] = 0x17;
916 serial_port_fd__options.c_cc[VLNEXT] = 0x16;
917 serial_port_fd__options.c_cc[VEOL2] = 0x00;
919 if (0 > tcsetattr(serial_port_fd_, TCSANOW, &serial_port_fd__options))
921 ROS_ERROR(
"Failed to set port attributes: %s", strerror(errno));
924 ::ioctl(serial_port_fd_, TIOCEXCL);
928 tcflush(serial_port_fd_, TCIOFLUSH);
935 int main(
int argc,
char* argv[])
938 ros::init(argc, argv,
"rr_openrover_basic_node");
965 if (!openrover.
start())
967 ROS_FATAL(
"Failed to start the openrover driver");
982 catch (std::string
s)
void robotDataMediumCB(const ros::WallTimerEvent &e)
void robotDataSlowCB(const ros::WallTimerEvent &e)
const int i_REG_MOTOR_FB_CURRENT_LEFT
const int i_BATTERY_VOLTAGE_B
const int i_REG_MOTOR_FLIPPER_ANGLE
bool is_serial_coms_open_
std::vector< unsigned char > serial_fast_buffer_
static tf::Quaternion createQuaternionFromRPY(double roll, double pitch, double yaw)
void robotDataFastCB(const ros::WallTimerEvent &e)
const int MOTOR_SPEED_ANGULAR_COEF_4WD_HS
const int MOTOR_SPEED_LINEAR_COEF_F_HS
std::vector< unsigned char > serial_slow_buffer_
const float ODOM_AXLE_TRACK_F
const int i_REG_MOTOR_TEMP_RIGHT
void publish(const boost::shared_ptr< M > &message) const
const int i_REG_POWER_BAT_VOLTAGE_A
void publishFastRateData()
ros::NodeHandle & nh_priv_
const int i_ENCODER_INTERVAL_MOTOR_RIGHT
OdomControl left_controller_
const int i_REG_ROBOT_REL_SOC_A
const float ODOM_AXLE_TRACK_2WD
void publishMotorSpeeds()
const int LEFT_MOTOR_INDEX_
rr_openrover_basic::SmartBatteryStatus interpret_battery_status(uint16_t bits)
ros::Publisher is_charging_pub
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
const int i_REG_MOTOR_CHARGER_STATE
const int i_BATTERY_VOLTAGE_A
const float ODOM_ENCODER_COEF_2WD
ros::Publisher battery_status_a_pub
const int i_BATTERY_MODE_A
int motor_speeds_commanded_[3]
const float ODOM_ENCODER_COEF_F
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void updateMeasuredVelocities()
ros::WallTimer medium_timer
int motor_speed_flipper_coef_
const int i_ENCODER_INTERVAL_MOTOR_FLIPPER
#define ROS_WARN_DELAYED_THROTTLE(rate,...)
ros::Publisher slow_rate_pub
double right_vel_commanded_
void updateRobotData(int parameter)
bool publish_fast_rate_values_
int main(int argc, char *argv[])
const int MOTOR_SPEED_ANGULAR_COEF_F_HS
const float ODOM_TRACTION_FACTOR_2WD
const int i_REG_FLIPPER_FB_POSITION_POT2
const int ROBOT_DATA_INDEX_FAST[]
bool publish_slow_rate_values_
const float ODOM_ANGULAR_COEF_4WD
const int i_REG_MOTOR_FAULT_FLAG_LEFT
const int RIGHT_MOTOR_INDEX_
double left_vel_commanded_
double right_vel_filtered_
OdomControl right_controller_
ros::Publisher battery_status_b_pub
void timeoutCB(const ros::WallTimerEvent &e)
void cmdVelCB(const geometry_msgs::TwistStamped::ConstPtr &msg)
int motor_speed_angular_coef_
const int i_BATTERY_CURRENT_B
int motor_speed_linear_coef_
const int i_REG_FLIPPER_FB_POSITION_POT1
const int MOTOR_SPEED_MAX
const int SERIAL_OUT_PACKAGE_LENGTH
const float ODOM_AXLE_TRACK_4WD
ros::Subscriber fan_speed_sub
void publishSlowRateData()
int motor_speed_deadband_
ros::Publisher fast_rate_pub
const int i_BATTERY_MODE_B
void fanSpeedCB(const std_msgs::Int32::ConstPtr &msg)
std::vector< unsigned char > serial_fan_buffer_
const int i_REG_POWER_B_CURRENT
const int i_BATTERY_TEMP_A
const int i_REG_ROBOT_REL_SOC_B
double velocity_filtered_
void start(bool use_control, PidGains pid_gains, int max, int min)
const int i_BATTERY_TEMP_B
float odom_traction_factor_
const int i_ENCODER_INTERVAL_MOTOR_LEFT
const int MOTOR_SPEED_ANGULAR_COEF_2WD_HS
WallTimer createWallTimer(WallDuration period, void(T::*callback)(const WallTimerEvent &), T *obj, bool oneshot=false, bool autostart=true) const
ros::Publisher vel_calc_pub
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
const int i_REG_POWER_BAT_VOLTAGE_B
const int i_REG_MOTOR_FB_RPM_RIGHT
const float ODOM_TRACTION_FACTOR_F
const int i_BATTERY_STATUS_A
const int i_REG_MOTOR_TEMP_LEFT
unsigned char run(bool e_stop_on, bool control_on, double commanded_vel, double measured_vel, double dt)
bool closed_loop_control_on_
ros::WallTimer slow_timer
const float ODOM_ENCODER_COEF_4WD
ros::Subscriber cmd_vel_sub
const int MOTOR_SPEED_LINEAR_COEF_4WD_HS
ros::Publisher medium_rate_pub
ROSCPP_DECL void requestShutdown()
std::vector< unsigned char > serial_medium_buffer_
const int ROBOT_DATA_INDEX_SLOW[]
const int ROBOT_DATA_INDEX_MEDIUM[]
const int i_REG_PWR_TOTAL_CURRENT
const float ODOM_ANGULAR_COEF_2WD
double right_vel_measured_
bool getParam(const std::string &key, std::string &s) const
ros::WallTimer timeout_timer
float odom_covariance_35_
double left_vel_measured_
const int i_REG_POWER_A_CURRENT
ros::WallTimer fast_timer
bool sendCommand(int param1, int param2)
ros::Publisher odom_enc_pub
double left_vel_filtered_
const float ODOM_TRACTION_FACTOR_4WD
OpenRover(ros::NodeHandle &nh, ros::NodeHandle &nh_priv)
int getParameterData(int parameter)
void publishMedRateData()
const int i_REG_MOTOR_FB_CURRENT_RIGHT
bool publish_med_rate_values_
bool setParameterData(int param1, int param2)
const int MOTOR_SPEED_MIN
ros::Publisher motor_speeds_pub
const float ODOM_ANGULAR_COEF_F
const int i_REG_MOTOR_FB_RPM_LEFT
ROSCPP_DECL void spinOnce()
const int MOTOR_SPEED_LINEAR_COEF_2WD_HS
const int i_BATTERY_STATUS_B
void publishOdometry(float left_vel, float right_vel)
const int FLIPPER_MOTOR_INDEX_
geometry_msgs::Twist cmd_vel_commanded_
const unsigned char SERIAL_START_BYTE
const int i_BATTERY_CURRENT_A