37 #include <sensor_msgs/JointState.h> 38 #include <sensor_msgs/Imu.h> 39 #include <std_msgs/Float64.h> 41 #include <nav_msgs/Odometry.h> 42 #include <robotnik_msgs/set_mode.h> 43 #include <robotnik_msgs/get_mode.h> 44 #include <robotnik_msgs/set_odometry.h> 45 #include <robotnik_msgs/ptz.h> 47 #include "ackermann_msgs/AckermannDriveStamped.h" 50 #include "diagnostic_msgs/DiagnosticStatus.h" 57 #define PI 3.1415926535 58 #define RBCAR_MIN_COMMAND_REC_FREQ 5.0 59 #define RBCAR_MAX_COMMAND_REC_FREQ 150.0 61 #define RBCAR_D_WHEELS_M 2.5 // distance from front to back axis, car-like kinematics 62 #define RBCAR_WHEEL_DIAMETER 0.470 // wheel avg diameter - may need calibration according to tyre pressure 63 #define RBCAR_JOINT_STATES_TIME_WINDOW 1.0 // accepted time deviation to process joint_sttate 189 node_handle_(h), private_node_handle_(
"~"),
191 freq_diag_(
diagnostic_updater::FrequencyStatusParam(&desired_freq_, &desired_freq_, 0.05) ),
195 ROS_INFO(
"rbcar_robot_control_node - Init ");
197 ros::NodeHandle rbcar_robot_control_node_handle(node_handle_,
"rbcar_robot_control");
200 if (!private_node_handle_.
getParam(
"model", robot_model_)) {
204 else ROS_INFO(
"Robot Model : %s", robot_model_.c_str());
209 private_node_handle_.
param<std::string>(
"frw_vel_topic", frw_vel_topic_,
"rbcar/right_front_axle_controller/command");
210 private_node_handle_.
param<std::string>(
"flw_vel_topic", flw_vel_topic_,
"rbcar/left_front_axle_controller/command");
211 private_node_handle_.
param<std::string>(
"blw_vel_topic", blw_vel_topic_,
"rbcar/left_rear_axle_controller/command");
212 private_node_handle_.
param<std::string>(
"brw_vel_topic", brw_vel_topic_,
"rbcar/right_rear_axle_controller/command");
215 private_node_handle_.
param<std::string>(
"joint_front_right_wheel", joint_front_right_wheel,
"right_front_axle");
216 private_node_handle_.
param<std::string>(
"joint_front_left_wheel", joint_front_left_wheel,
"left_front_axle");
217 private_node_handle_.
param<std::string>(
"joint_back_left_wheel", joint_back_left_wheel,
"left_rear_axle");
218 private_node_handle_.
param<std::string>(
"joint_back_right_wheel", joint_back_right_wheel,
"right_rear_axle");
221 private_node_handle_.
param<std::string>(
"frw_pos_topic", frw_pos_topic_,
"rbcar/right_steering_joint_controller/command");
222 private_node_handle_.
param<std::string>(
"flw_pos_topic", flw_pos_topic_,
"rbcar/left_steering_joint_controller/command");
224 private_node_handle_.
param<std::string>(
"joint_front_right_steer", joint_front_right_steer,
"right_steering_joint");
225 private_node_handle_.
param<std::string>(
"joint_front_left_steer", joint_front_left_steer,
"left_steering_joint");
228 if (!private_node_handle_.
getParam(
"rbcar_d_wheels", rbcar_d_wheels_))
230 if (!private_node_handle_.
getParam(
"rbcar_wheel_diameter", rbcar_wheel_diameter_))
232 ROS_INFO(
"rbcar_d_wheels_ = %5.2f", rbcar_d_wheels_);
233 ROS_INFO(
"rbcar_wheel_diameter_ = %5.2f", rbcar_wheel_diameter_);
235 private_node_handle_.
param(
"publish_odom_tf", publish_odom_tf_,
true);
236 if (publish_odom_tf_)
ROS_INFO(
"PUBLISHING odom->base_footprint tf");
237 else ROS_INFO(
"NOT PUBLISHING odom->base_footprint tf");
240 linearSpeedXMps_ = 0.0;
241 linearSpeedYMps_ = 0.0;
242 angularSpeedRads_ = 0.0;
245 robot_pose_px_ = 0.0;
246 robot_pose_py_ = 0.0;
247 robot_pose_pa_ = 0.0;
248 robot_pose_vx_ = 0.0;
249 robot_pose_vy_ = 0.0;
257 ang_vel_x_ = 0.0; ang_vel_y_ = 0.0; ang_vel_z_ = 0.0;
258 lin_acc_x_ = 0.0; lin_acc_y_ = 0.0; lin_acc_z_ = 0.0;
259 orientation_x_ = 0.0; orientation_y_ = 0.0; orientation_z_ = 0.0; orientation_w_ = 1.0;
271 ref_vel_frw_ = node_handle_.
advertise<std_msgs::Float64>( frw_vel_topic_, 50);
272 ref_vel_flw_ = node_handle_.
advertise<std_msgs::Float64>( flw_vel_topic_, 50);
273 ref_vel_blw_ = node_handle_.
advertise<std_msgs::Float64>( blw_vel_topic_, 50);
274 ref_vel_brw_ = node_handle_.
advertise<std_msgs::Float64>( brw_vel_topic_, 50);
275 ref_pos_frw_ = node_handle_.
advertise<std_msgs::Float64>( frw_pos_topic_, 50);
276 ref_pos_flw_ = node_handle_.
advertise<std_msgs::Float64>( flw_pos_topic_, 50);
282 odom_pub_ = private_node_handle_.
advertise<nav_msgs::Odometry>(
"odom", 1000);
285 diagnostic_.
setHardwareID(
"rbcar_robot_control - simulation");
286 diagnostic_.
add( freq_diag_ );
287 diagnostic_.
add( command_freq_ );
296 subs_command_freq->
addTask(&command_freq_);
307 vector<string> joint_names = joint_state_.name;
308 frw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_front_right_wheel)) - joint_names.begin();
309 flw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_front_left_wheel)) - joint_names.begin();
310 blw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_back_left_wheel)) - joint_names.begin();
311 brw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_back_right_wheel)) - joint_names.begin();
312 frw_pos_ = find (joint_names.begin(),joint_names.end(), string(joint_front_right_steer)) - joint_names.begin();
313 flw_pos_ = find (joint_names.begin(),joint_names.end(), string(joint_front_left_steer)) - joint_names.begin();
316 ROS_WARN(
"RbcarControllerClass::starting: joint_states are not being received");
329 double alfa_ref_left = 0.0;
330 double alfa_ref_right = 0.0;
331 if (alfa_ref_!=0.0) {
332 d1 = d / tan (alfa_ref_);
333 alfa_ref_left = atan2( d, d1 - 0.105);
334 alfa_ref_right = atan2( d, d1 + 0.105);
336 alfa_ref_left = alfa_ref_left -
PI;
337 alfa_ref_right = alfa_ref_right -
PI;
342 alfa_ref_right = 0.0;
346 std_msgs::Float64 frw_ref_pos_msg;
347 std_msgs::Float64 flw_ref_pos_msg;
348 std_msgs::Float64 brw_ref_pos_msg;
349 std_msgs::Float64 blw_ref_pos_msg;
351 flw_ref_pos_msg.data = alfa_ref_left;
352 frw_ref_pos_msg.data = alfa_ref_right;
358 std_msgs::Float64 frw_ref_vel_msg;
359 std_msgs::Float64 flw_ref_vel_msg;
360 std_msgs::Float64 brw_ref_vel_msg;
361 std_msgs::Float64 blw_ref_vel_msg;
362 frw_ref_vel_msg.data = -ref_speed_joint;
363 flw_ref_vel_msg.data = -ref_speed_joint;
364 brw_ref_vel_msg.data = -ref_speed_joint;
365 blw_ref_vel_msg.data = -ref_speed_joint;
368 ref_vel_frw_.
publish( frw_ref_vel_msg );
369 ref_vel_flw_.
publish( flw_ref_vel_msg );
370 ref_vel_blw_.
publish( blw_ref_vel_msg );
371 ref_vel_brw_.
publish( brw_ref_vel_msg );
372 ref_pos_frw_.
publish( frw_ref_pos_msg );
373 ref_pos_flw_.
publish( flw_ref_pos_msg );
383 ROS_WARN_THROTTLE(2,
"RbcarControllerClass::UpdateOdometry: joint_states are not being received");
388 a1 = radnorm2( joint_state_.position[frw_pos_] );
389 a2 = radnorm2( joint_state_.position[flw_pos_] );
398 v3 = joint_state_.velocity[blw_vel_] * (rbcar_wheel_diameter_ / 2.0);
399 v4 = joint_state_.velocity[brw_vel_] * (rbcar_wheel_diameter_ / 2.0);
402 double fBetaRads = (a1 + a2) / 2.0;
405 double fSamplePeriod = 1.0 / desired_freq_;
406 double v_mps = -(v3 + v4) / 2.0;
412 tf::Quaternion q(orientation_x_, orientation_y_, orientation_z_, orientation_w_);
415 double roll, pitch, yaw;
416 m.
getRPY(roll, pitch, yaw);
417 robot_pose_pa_ = yaw;
420 while (robot_pose_pa_ >=
PI)
421 robot_pose_pa_ -= 2.0 *
PI;
422 while (robot_pose_pa_ <= (-
PI))
423 robot_pose_pa_ += 2.0 *
PI;
425 double vx = v_mps * cos(fBetaRads) * cos(robot_pose_pa_);
426 double vy = v_mps * cos(fBetaRads) * sin(robot_pose_pa_);
429 robot_pose_px_ += vx * fSamplePeriod;
430 robot_pose_py_ += vy * fSamplePeriod;
446 geometry_msgs::TransformStamped odom_trans;
447 odom_trans.header.stamp = current_time;
448 odom_trans.header.frame_id =
"odom";
449 odom_trans.child_frame_id =
"base_footprint";
451 odom_trans.transform.translation.x = robot_pose_px_;
452 odom_trans.transform.translation.y = robot_pose_py_;
453 odom_trans.transform.translation.z = 0.0;
454 odom_trans.transform.rotation.x = orientation_x_;
455 odom_trans.transform.rotation.y = orientation_y_;
456 odom_trans.transform.rotation.z = orientation_z_;
457 odom_trans.transform.rotation.w = orientation_w_;
462 if (publish_odom_tf_) odom_broadcaster.
sendTransform(odom_trans);
465 nav_msgs::Odometry odom;
466 odom.header.stamp = current_time;
467 odom.header.frame_id =
"odom";
471 odom.pose.pose.position.x = robot_pose_px_;
472 odom.pose.pose.position.y = robot_pose_py_;
473 odom.pose.pose.position.z = 0.0;
475 odom.pose.pose.orientation.x = orientation_x_;
476 odom.pose.pose.orientation.y = orientation_y_;
477 odom.pose.pose.orientation.z = orientation_z_;
478 odom.pose.pose.orientation.w = orientation_w_;
480 for(
int i = 0; i < 6; i++)
481 odom.pose.covariance[i*6+i] = 0.1;
484 odom.child_frame_id =
"base_footprint";
486 odom.twist.twist.linear.x = robot_pose_vx_;
487 odom.twist.twist.linear.y = robot_pose_vy_;
488 odom.twist.twist.linear.z = 0.0;
490 odom.twist.twist.angular.x = ang_vel_x_;
491 odom.twist.twist.angular.y = ang_vel_y_;
492 odom.twist.twist.angular.z = ang_vel_z_;
494 for(
int i = 0; i < 6; i++)
495 odom.twist.covariance[6*i+i] = 0.1;
514 double diff = (current_time - last_command_time_).toSec();
517 stat.
summary(diagnostic_msgs::DiagnosticStatus::WARN,
"Topic is not receiving commands");
523 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Topic receiving commands");
530 void setCommand(
const ackermann_msgs::AckermannDriveStamped &msg)
533 double speed_limit = 10.0;
534 double angle_limit =
PI/4.0;
535 v_ref_ = saturation(msg.drive.speed, -speed_limit, speed_limit);
536 alfa_ref_ = saturation(msg.drive.steering_angle, -angle_limit, angle_limit);
543 robot_pose_px_ = request.x;
544 robot_pose_py_ = request.y;
545 robot_pose_pa_ = request.orientation;
565 subs_command_freq->
tick();
567 base_vel_msg_ = *msg;
568 this->setCommand(base_vel_msg_);
574 orientation_x_ = imu_msg.orientation.x;
575 orientation_y_ = imu_msg.orientation.y;
576 orientation_z_ = imu_msg.orientation.z;
577 orientation_w_ = imu_msg.orientation.w;
579 ang_vel_x_ = imu_msg.angular_velocity.x;
580 ang_vel_y_ = imu_msg.angular_velocity.y;
581 ang_vel_z_ = imu_msg.angular_velocity.z;
583 lin_acc_x_ = imu_msg.linear_acceleration.x;
584 lin_acc_y_ = imu_msg.linear_acceleration.y;
585 lin_acc_z_ = imu_msg.linear_acceleration.z;
597 while (value >
PI) value -=
PI;
598 while (value < -
PI) value +=
PI;
604 while (value > 2.0*
PI) value -= 2.0*
PI;
605 while (value < -2.0*
PI) value += 2.0*
PI;
611 ROS_INFO(
"rbcar_robot_control::spin()");
640 int main(
int argc,
char** argv)
642 ros::init(argc, argv,
"rbcar_robot_control");
std::string flw_pos_topic_
void imuCallback(const sensor_msgs::Imu &imu_msg)
double rbcar_wheel_diameter_
ros::NodeHandle node_handle_
std::string joint_front_right_steer
#define RBCAR_JOINT_STATES_TIME_WINDOW
double radnorm(double value)
diagnostic_updater::HeaderlessTopicDiagnostic * subs_command_freq
ros::Publisher ref_vel_blw_
#define ROS_WARN_THROTTLE(rate,...)
std::string frw_pos_topic_
void publish(const boost::shared_ptr< M > &message) const
ros::Publisher ref_pos_frw_
std::string joint_back_right_wheel
void summary(unsigned char lvl, const std::string s)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
sensor_msgs::JointState joint_state_
ros::Subscriber joint_state_sub_
void setHardwareID(const std::string &hwid)
std::string frw_vel_topic_
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void add(const std::string &name, TaskFunction f)
ros::Time last_command_time_
void setCommand(const ackermann_msgs::AckermannDriveStamped &msg)
std::string joint_front_left_steer
#define RBCAR_MIN_COMMAND_REC_FREQ
std::string brw_vel_topic_
void check_command_subscriber(diagnostic_updater::DiagnosticStatusWrapper &stat)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
tf::TransformBroadcaster odom_broadcaster
std::string joint_back_left_wheel
ros::ServiceServer srv_SetOdometry_
std::string joint_front_left_wheel
void stopping()
Controller stopping.
ackermann_msgs::AckermannDriveStamped base_vel_msg_
std::string joint_front_right_wheel
bool srvCallback_SetOdometry(robotnik_msgs::set_odometry::Request &request, robotnik_msgs::set_odometry::Response &response)
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
std::string blw_vel_topic_
ROSCPP_DECL bool isShuttingDown()
diagnostic_updater::FrequencyStatus freq_diag_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define RBCAR_WHEEL_DIAMETER
diagnostic_updater::Updater diagnostic_
int starting()
Controller startup in realtime.
RbcarControllerClass(ros::NodeHandle h)
Public constructor.
void UpdateControl()
Controller update loop.
double radnorm2(double value)
bool getParam(const std::string &key, std::string &s) const
void jointStateCallback(const sensor_msgs::JointStateConstPtr &msg)
ros::Publisher ref_pos_flw_
diagnostic_updater::FunctionDiagnosticTask command_freq_
void commandCallback(const ackermann_msgs::AckermannDriveStamped::ConstPtr &msg)
ros::NodeHandle private_node_handle_
ros::Publisher ref_vel_frw_
std::string flw_vel_topic_
ROSCPP_DECL void spinOnce()
int main(int argc, char **argv)
ros::Publisher ref_vel_brw_
ros::Publisher ref_vel_flw_
double saturation(double u, double min, double max)
#define RBCAR_MAX_COMMAND_REC_FREQ
void addTask(DiagnosticTask *t)