39 #include <boost/assign.hpp> 47 : command_struct_twist_()
48 , command_struct_four_wheel_steering_()
50 , wheel_steering_y_offset_(0.0)
53 , cmd_vel_timeout_(0.5)
54 , base_frame_id_(
"base_link")
55 , enable_odom_tf_(true)
56 , enable_twist_cmd_(false)
64 const std::string complete_ns = controller_nh.
getNamespace();
65 std::size_t
id = complete_ns.find_last_of(
"/");
66 name_ = complete_ns.substr(
id + 1);
69 std::vector<std::string> front_wheel_names, rear_wheel_names;
70 if (!
getWheelNames(controller_nh,
"front_wheel", front_wheel_names) ||
71 !
getWheelNames(controller_nh,
"rear_wheel", rear_wheel_names))
76 if (front_wheel_names.size() != rear_wheel_names.size())
79 "#front wheels (" << front_wheel_names.size() <<
") != " <<
80 "#rear wheels (" << rear_wheel_names.size() <<
").");
83 else if (front_wheel_names.size() != 2)
86 "#two wheels by axle (left and right) is needed; now : "<<front_wheel_names.size()<<
" .");
96 std::vector<std::string> front_steering_names, rear_steering_names;
97 if (!
getWheelNames(controller_nh,
"front_steering", front_steering_names) ||
98 !
getWheelNames(controller_nh,
"rear_steering", rear_steering_names))
103 if (front_steering_names.size() != rear_steering_names.size())
106 "#left steerings (" << front_steering_names.size() <<
") != " <<
107 "#right steerings (" << rear_steering_names.size() <<
").");
110 else if (front_steering_names.size() != 2)
113 "#two steering by axle (left and right) is needed; now : "<<front_steering_names.size()<<
" .");
124 controller_nh.
param(
"publish_rate", publish_rate, 50.0);
126 << publish_rate <<
"Hz.");
131 int velocity_rolling_window_size = 10;
132 controller_nh.
param(
"velocity_rolling_window_size", velocity_rolling_window_size, velocity_rolling_window_size);
134 << velocity_rolling_window_size <<
".");
181 if(lookup_wheel_radius)
187 if(lookup_wheel_base)
197 "Odometry params : track " <<
track_ 212 "Adding left wheel with joint name: " << front_wheel_names[i]
213 <<
" and right wheel with joint name: " << rear_wheel_names[i]);
222 "Adding left steering with joint name: " << front_steering_names[i]
223 <<
" and right steering with joint name: " << rear_steering_names[i]);
262 if (std::isnan(fl_speed) || std::isnan(fr_speed)
263 || std::isnan(rl_speed) || std::isnan(rr_speed))
270 if (std::isnan(fl_steering) || std::isnan(fr_steering)
271 || std::isnan(rl_steering) || std::isnan(rr_steering))
273 double front_steering_pos = 0.0;
274 if(fabs(fl_steering) > 0.001 || fabs(fr_steering) > 0.001)
276 front_steering_pos = atan(2*tan(fl_steering)*tan(fr_steering)/
277 (tan(fl_steering) + tan(fr_steering)));
279 double rear_steering_pos = 0.0;
280 if(fabs(rl_steering) > 0.001 || fabs(rr_steering) > 0.001)
282 rear_steering_pos = atan(2*tan(rl_steering)*tan(rr_steering)/
283 (tan(rl_steering) + tan(rr_steering)));
286 ROS_DEBUG_STREAM_THROTTLE(1,
"rl_steering "<<rl_steering<<
" rr_steering "<<rr_steering<<
" rear_steering_pos "<<rear_steering_pos);
289 front_steering_pos, rear_steering_pos, time);
296 const geometry_msgs::Quaternion orientation(
305 odom_pub_->msg_.pose.pose.orientation = orientation;
317 odom_4ws_pub_->msg_.data.front_steering_angle = front_steering_pos;
319 odom_4ws_pub_->msg_.data.rear_steering_angle = rear_steering_pos;
327 geometry_msgs::TransformStamped& odom_frame =
tf_odom_pub_->msg_.transforms[0];
328 odom_frame.header.stamp = time;
331 odom_frame.transform.rotation = orientation;
344 if(curr_cmd_4ws.
stamp >= curr_cmd_twist.
stamp)
351 cmd = &curr_cmd_twist;
355 const double dt = (time - cmd->
stamp).toSec();
359 curr_cmd_twist.
lin_x = 0.0;
360 curr_cmd_twist.
lin_y = 0.0;
361 curr_cmd_twist.
ang = 0.0;
362 curr_cmd_4ws.
lin = 0.0;
367 const double cmd_dt(period.
toSec());
373 double vel_left_front = 0, vel_right_front = 0;
374 double vel_left_rear = 0, vel_right_rear = 0;
375 double front_left_steering = 0, front_right_steering = 0;
376 double rear_left_steering = 0, rear_right_steering = 0;
387 if(fabs(curr_cmd_twist.
lin_x) > 0.001)
390 vel_left_front = copysign(1.0, curr_cmd_twist.
lin_x) * sqrt((pow(curr_cmd_twist.
lin_x - curr_cmd_twist.
ang*steering_track/2,2)
392 - vel_steering_offset;
393 vel_right_front = copysign(1.0, curr_cmd_twist.
lin_x) * sqrt((pow(curr_cmd_twist.
lin_x + curr_cmd_twist.
ang*steering_track/2,2)
395 + vel_steering_offset;
396 vel_left_rear = copysign(1.0, curr_cmd_twist.
lin_x) * sqrt((pow(curr_cmd_twist.
lin_x - curr_cmd_twist.
ang*steering_track/2,2)
398 - vel_steering_offset;
399 vel_right_rear = copysign(1.0, curr_cmd_twist.
lin_x) * sqrt((pow(curr_cmd_twist.
lin_x + curr_cmd_twist.
ang*steering_track/2,2)
401 + vel_steering_offset;
405 if(fabs(2.0*curr_cmd_twist.
lin_x) > fabs(curr_cmd_twist.
ang*steering_track))
408 (2.0*curr_cmd_twist.
lin_x - curr_cmd_twist.
ang*steering_track));
410 (2.0*curr_cmd_twist.
lin_x + curr_cmd_twist.
ang*steering_track));
412 (2.0*curr_cmd_twist.
lin_x - curr_cmd_twist.
ang*steering_track));
414 (2.0*curr_cmd_twist.
lin_x + curr_cmd_twist.
ang*steering_track));
416 else if(fabs(curr_cmd_twist.
lin_x) > 0.001)
418 front_left_steering = copysign(M_PI_2, curr_cmd_twist.
ang);
419 front_right_steering = copysign(M_PI_2, curr_cmd_twist.
ang);
420 rear_left_steering = copysign(M_PI_2, -curr_cmd_twist.
ang);
421 rear_right_steering = copysign(M_PI_2, -curr_cmd_twist.
ang);
435 if(fabs(
wheel_base_ - fabs(steering_diff)) > 0.001)
444 if(fabs(curr_cmd_4ws.
lin) > 0.001)
449 if(fabs(tan(front_left_steering) - tan(front_right_steering)) > 0.01)
451 l_front = tan(front_right_steering) * tan(front_left_steering) * steering_track
452 / (tan(front_left_steering) - tan(front_right_steering));
456 if(fabs(tan(rear_left_steering) - tan(rear_right_steering)) > 0.01)
458 l_rear = tan(rear_right_steering) * tan(rear_left_steering) * steering_track
459 / (tan(rear_left_steering) - tan(rear_right_steering));
465 vel_left_front = copysign(1.0, curr_cmd_4ws.
lin) * sqrt((pow(curr_cmd_4ws.
lin - angular_speed_cmd*steering_track/2,2)
467 - vel_steering_offset;
468 vel_right_front = copysign(1.0, curr_cmd_4ws.
lin) * sqrt((pow(curr_cmd_4ws.
lin + angular_speed_cmd*steering_track/2,2)
470 + vel_steering_offset;
471 vel_left_rear = copysign(1.0, curr_cmd_4ws.
lin) * sqrt((pow(curr_cmd_4ws.
lin - angular_speed_cmd*steering_track/2,2)
473 - vel_steering_offset;
474 vel_right_rear = copysign(1.0, curr_cmd_4ws.
lin) * sqrt((pow(curr_cmd_4ws.
lin + angular_speed_cmd*steering_track/2,2)
476 + vel_steering_offset;
502 const double vel = 0.0;
509 const double pos = 0.0;
521 if(std::isnan(command.angular.z) || std::isnan(command.linear.x))
523 ROS_WARN(
"Received NaN in geometry_msgs::Twist. Ignoring command.");
532 "Added values to command. " 548 if(std::isnan(command.front_steering_angle) || std::isnan(command.rear_steering_angle)
549 || std::isnan(command.speed))
551 ROS_WARN(
"Received NaN in four_wheel_steering_msgs::FourWheelSteering. Ignoring command.");
560 "Added values to command. " 573 const std::string& wheel_param,
574 std::vector<std::string>& wheel_names)
577 if (!controller_nh.
getParam(wheel_param, wheel_list))
580 "Couldn't retrieve wheel param '" << wheel_param <<
"'.");
586 if (wheel_list.
size() == 0)
589 "Wheel param '" << wheel_param <<
"' is an empty list");
593 for (
int i = 0; i < wheel_list.
size(); ++i)
598 "Wheel param '" << wheel_param <<
"' #" << i <<
604 wheel_names.resize(wheel_list.
size());
605 for (
int i = 0; i < wheel_list.
size(); ++i)
607 wheel_names[i] =
static_cast<std::string
>(wheel_list[i]);
613 wheel_names.push_back(wheel_list);
618 "Wheel param '" << wheel_param <<
619 "' is neither a list of strings nor a string.");
629 controller_nh.
getParam(
"pose_covariance_diagonal", pose_cov_list);
632 for (
int i = 0; i < pose_cov_list.
size(); ++i)
636 controller_nh.
getParam(
"twist_covariance_diagonal", twist_cov_list);
639 for (
int i = 0; i < twist_cov_list.
size(); ++i)
644 odom_pub_->msg_.header.frame_id =
"odom";
646 odom_pub_->msg_.pose.pose.position.z = 0;
647 odom_pub_->msg_.pose.covariance = boost::assign::list_of
648 (static_cast<double>(pose_cov_list[0])) (0) (0) (0) (0) (0)
649 (0) (
static_cast<double>(pose_cov_list[1])) (0) (0) (0) (0)
650 (0) (0) (
static_cast<double>(pose_cov_list[2])) (0) (0) (0)
651 (0) (0) (0) (
static_cast<double>(pose_cov_list[3])) (0) (0)
652 (0) (0) (0) (0) (
static_cast<double>(pose_cov_list[4])) (0)
653 (0) (0) (0) (0) (0) (
static_cast<double>(pose_cov_list[5]));
654 odom_pub_->msg_.twist.twist.linear.y = 0;
655 odom_pub_->msg_.twist.twist.linear.z = 0;
656 odom_pub_->msg_.twist.twist.angular.x = 0;
657 odom_pub_->msg_.twist.twist.angular.y = 0;
658 odom_pub_->msg_.twist.covariance = boost::assign::list_of
659 (static_cast<double>(twist_cov_list[0])) (0) (0) (0) (0) (0)
660 (0) (
static_cast<double>(twist_cov_list[1])) (0) (0) (0) (0)
661 (0) (0) (
static_cast<double>(twist_cov_list[2])) (0) (0) (0)
662 (0) (0) (0) (
static_cast<double>(twist_cov_list[3])) (0) (0)
663 (0) (0) (0) (0) (
static_cast<double>(twist_cov_list[4])) (0)
664 (0) (0) (0) (0) (0) (
static_cast<double>(twist_cov_list[5]));
671 tf_odom_pub_->msg_.transforms[0].transform.translation.z = 0.0;
673 tf_odom_pub_->msg_.transforms[0].header.frame_id =
"odom";
void setVelocityRollingWindowSize(size_t velocity_rolling_window_size)
Velocity rolling window size setter.
#define ROS_DEBUG_STREAM_THROTTLE(rate, args)
void stopping(const ros::Time &)
Stops controller.
ros::Subscriber sub_command_four_wheel_steering_
double cmd_vel_timeout_
Timeout to consider cmd_vel commands old:
double getX() const
x position getter
void cmdVelCallback(const geometry_msgs::Twist &command)
Velocity command callback.
std::string base_frame_id_
Frame to use for the robot base:
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
void updateCommand(const ros::Time &time, const ros::Duration &period)
Compute and publish command.
double getLinearY() const
linear velocity getter along Y on the robot base link frame
std::vector< hardware_interface::JointHandle > front_steering_joints_
std::vector< hardware_interface::JointHandle > rear_wheel_joints_
double getLinearAcceleration() const
linear acceleration getter
void update(const ros::Time &time, const ros::Duration &period)
Updates controller, i.e. computes the odometry and sets the new velocity commands.
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
CommandTwist command_struct_twist_
double getLinear() const
linear velocity getter norm
void updateOdometry(const ros::Time &time)
Update and publish odometry.
bool init(hardware_interface::RobotHW *robot_hw, ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
Initialize controller.
std::vector< hardware_interface::JointHandle > rear_steering_joints_
void cmdFourWheelSteeringCallback(const four_wheel_steering_msgs::FourWheelSteering &command)
Velocity and steering command callback.
#define ROS_INFO_STREAM_NAMED(name, args)
bool enable_twist_cmd_
Whether the control is make with four_wheel_steering msg or twist msg:
double getY() const
y position getter
Type const & getType() const
double wheel_steering_y_offset_
double limit(double &v, double v0, double v1, double dt)
Limit the velocity and acceleration.
double wheel_radius_
Wheel radius (assuming it's the same for the left and right wheels):
bool update(const double &fl_speed, const double &fr_speed, const double &rl_speed, const double &rr_speed, double front_steering, double rear_steering, const ros::Time &time)
Updates the odometry class with latest wheels and steerings position.
std::vector< hardware_interface::JointHandle > front_wheel_joints_
Hardware handles:
bool getWheelNames(ros::NodeHandle &controller_nh, const std::string &wheel_param, std::vector< std::string > &wheel_names)
Get the wheel names from a wheel param.
bool has_acceleration_limits
ros::Subscriber sub_command_
boost::shared_ptr< realtime_tools::RealtimePublisher< tf::tfMessage > > tf_odom_pub_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
ros::Time last_state_publish_time_
void setWheelParams(double steering_track, double wheel_steering_y_offset, double wheel_radius, double wheel_base)
Sets the wheel parameters: radius and separation.
const std::string & getNamespace() const
double getLinearJerk() const
linear jerk getter
void setOdomPubFields(ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
Sets the odometry publishing fields.
bool enable_odom_tf_
Whether to publish odometry to tf or not:
#define ROS_DEBUG_STREAM(args)
void brake()
Brakes the wheels, i.e. sets the velocity to 0.
ros::Duration publish_period_
Odometry related:
bool getJointRadius(const std::string &joint_name, double &radius)
boost::shared_ptr< realtime_tools::RealtimePublisher< nav_msgs::Odometry > > odom_pub_
Odometry related:
JointHandle getHandle(const std::string &name)
Velocity command related:
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
bool getParam(const std::string &key, std::string &s) const
FourWheelSteeringController()
void starting(const ros::Time &time)
Starts controller.
realtime_tools::RealtimeBuffer< CommandTwist > command_twist_
#define ROS_ERROR_NAMED(name,...)
Command4ws command_struct_four_wheel_steering_
bool getDistanceBetweenJoints(const std::string &first_joint_name, const std::string &second_joint_name, double &distance)
double getFrontSteerVel() const
front steering velocity getter
boost::shared_ptr< realtime_tools::RealtimePublisher< four_wheel_steering_msgs::FourWheelSteeringStamped > > odom_4ws_pub_
SpeedLimiter limiter_ang_
double getHeading() const
heading getter
double getRearSteerVel() const
rear steering velocity getter
CommandTwist last1_cmd_
Speed limiters:
void init(const ros::Time &time)
Initialize the odometry.
double getAngular() const
angular velocity getter
double track_
Wheel separation (or track), distance between left and right wheels (from the midpoint of the wheel w...
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const
double getLinearX() const
linear velocity getter along X on the robot base link frame
double wheel_base_
Wheel base (distance between front and rear wheel):
T clamp(T x, T min, T max)
realtime_tools::RealtimeBuffer< Command4ws > command_four_wheel_steering_
FourWheelSteering command related:
SpeedLimiter limiter_lin_