8 #include <urdf_parser/urdf_parser.h> 9 #include <boost/assign.hpp> 23 , steering_angle_instead_of_angular_speed_(true)
25 , cmd_vel_timeout_(0.5)
26 , velocity_rolling_window_size_(10)
27 , odom_frame_id_(
"odom")
28 , base_frame_id_(
"base_link")
29 , base_link_(
"base_link")
30 , enable_odom_tf_(true)
43 const std::string complete_ns = controller_nh.
getNamespace();
44 std::size_t
id = complete_ns.find_last_of(
"/");
45 name_ = complete_ns.substr(
id + 1);
56 std::vector<std::string>::const_iterator it;
57 std::vector<std::string> spinning_joint_names =
getJointNames(controller_nh,
"spinning_joints");
58 std::vector<std::string> odometry_joint_names =
getJointNames(controller_nh,
"odometry_joints");
59 std::vector<std::string> steering_joint_names =
getJointNames(controller_nh,
"steering_joints");
61 for (it = spinning_joint_names.begin(); it != spinning_joint_names.end(); ++it)
65 "Found spinning joint " << wheel.name_
66 <<
" with lateral deviation " << wheel.lateral_deviation_
67 <<
" and radius " << wheel.radius_);
71 for (it = odometry_joint_names.begin(); it != odometry_joint_names.end(); ++it)
75 "Found odometry joint " << wheel.name_
76 <<
" with lateral deviation " << wheel.lateral_deviation_
77 <<
" and radius " << wheel.radius_);
81 for (it = steering_joint_names.begin(); it != steering_joint_names.end(); ++it)
85 "Found steering joint " << steering_joint.name_
86 <<
" with lateral deviation " << steering_joint.lateral_deviation_);
90 catch(
const std::runtime_error& e)
127 const geometry_msgs::Quaternion orientation(
135 odom_pub_->msg_.pose.pose.orientation = orientation;
143 geometry_msgs::TransformStamped& odom_frame =
tf_odom_pub_->msg_.transforms[0];
144 odom_frame.header.stamp = time;
147 odom_frame.transform.rotation = orientation;
157 const double dt = (time - curr_cmd.
stamp).toSec();
167 const double cmd_dt(period.
toSec());
178 angle = curr_cmd.
ang;
188 double steering_angle = std::atan(
wheelbase_ * std::tan(angle)/std::abs(
wheelbase_ + it->lateral_deviation_ * std::tan(angle)));
189 it->setCommand(steering_angle);
195 double velocity = (curr_cmd.
lin * (1.0 + 2.0 * it->lateral_deviation_ * std::tan(curr_cmd.
ang) / (2.0 *
wheelbase_))) / it->radius_;
196 it->setCommand(velocity);
217 const double velocity = 0.0;
219 std::vector<ActuatedWheel>::iterator it;
222 it->setCommand(velocity);
237 "Added values to command. " 252 controller_nh.
param(
"publish_rate", publish_rate, 50.0);
254 << publish_rate <<
"Hz.");
306 const std::string model_param_name =
"robot_description";
307 std::string robot_model_str =
"";
309 if (!nh.
hasParam(model_param_name) || !nh.
getParam(model_param_name, robot_model_str))
311 throw std::runtime_error(
"Robot description couldn't be retrieved from param server.");
321 const std::string& param)
323 std::vector<std::string> names;
326 if (!controller_nh.
getParam(param, wheel_list))
328 throw std::runtime_error(std::string(
"Couldn't retrieve param '") + param +
"'.");
333 if (wheel_list.
size() == 0)
335 throw std::runtime_error(param +
" is an empty list");
338 for (
int i = 0; i < wheel_list.
size(); ++i)
342 throw std::runtime_error(param +
" child isn't a string.");
346 names.resize(wheel_list.
size());
347 for (
int i = 0; i < wheel_list.
size(); ++i)
349 names[i] =
static_cast<std::string
>(wheel_list[i]);
354 names.push_back(wheel_list);
358 throw std::runtime_error(param +
" is neither a list of strings nor a string.");
368 controller_nh.
getParam(
"pose_covariance_diagonal", pose_cov_list);
371 for (
int i = 0; i < pose_cov_list.
size(); ++i)
375 controller_nh.
getParam(
"twist_covariance_diagonal", twist_cov_list);
378 for (
int i = 0; i < twist_cov_list.
size(); ++i)
385 odom_pub_->msg_.pose.pose.position.z = 0;
386 odom_pub_->msg_.pose.covariance = boost::assign::list_of
387 (static_cast<double>(pose_cov_list[0])) (0) (0) (0) (0) (0)
388 (0) (
static_cast<double>(pose_cov_list[1])) (0) (0) (0) (0)
389 (0) (0) (
static_cast<double>(pose_cov_list[2])) (0) (0) (0)
390 (0) (0) (0) (
static_cast<double>(pose_cov_list[3])) (0) (0)
391 (0) (0) (0) (0) (
static_cast<double>(pose_cov_list[4])) (0)
392 (0) (0) (0) (0) (0) (
static_cast<double>(pose_cov_list[5]));
393 odom_pub_->msg_.twist.twist.linear.y = 0;
394 odom_pub_->msg_.twist.twist.linear.z = 0;
395 odom_pub_->msg_.twist.twist.angular.x = 0;
396 odom_pub_->msg_.twist.twist.angular.y = 0;
397 odom_pub_->msg_.twist.covariance = boost::assign::list_of
398 (static_cast<double>(twist_cov_list[0])) (0) (0) (0) (0) (0)
399 (0) (
static_cast<double>(twist_cov_list[1])) (0) (0) (0) (0)
400 (0) (0) (
static_cast<double>(twist_cov_list[2])) (0) (0) (0)
401 (0) (0) (0) (
static_cast<double>(twist_cov_list[3])) (0) (0)
402 (0) (0) (0) (0) (
static_cast<double>(twist_cov_list[4])) (0)
403 (0) (0) (0) (0) (0) (
static_cast<double>(twist_cov_list[5]));
406 tf_odom_pub_->msg_.transforms[0].transform.translation.z = 0.0;
double getY() const
y position getter
std::vector< Wheel > odometry_joints_
void stopping(const ros::Time &)
Stops controller.
bool update(const std::vector< ActuatedJoint > &steering_joints, const std::vector< Wheel > &odometry_joints, const ros::Time &time)
Updates the odometry class with latest wheels position.
#define ROS_DEBUG_STREAM_NAMED(name, args)
void updateOdometry(const ros::Time &time, const ros::Duration &period)
#define ROS_ERROR_STREAM_NAMED(name, args)
void setWheelbase(double wheelbase)
std::vector< ActuatedJoint > steering_joints_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ros::Subscriber sub_command_
std::vector< ActuatedWheel > spinning_joints_
boost::shared_ptr< realtime_tools::RealtimePublisher< nav_msgs::Odometry > > odom_pub_
boost::shared_ptr< realtime_tools::RealtimePublisher< tf::tfMessage > > tf_odom_pub_
bool steering_angle_instead_of_angular_speed_
void cmdVelCallback(const geometry_msgs::Twist &command)
ros::Duration publish_period_
#define ROS_INFO_STREAM_NAMED(name, args)
ros::Time last_state_publish_time_
bool initParams(ros::NodeHandle &controller_nh)
void setOdomPubFields(ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
Type const & getType() const
void starting(const ros::Time &time)
Starts controller.
void update(const ros::Time &time, const ros::Duration &period)
Updates controller, i.e. computes the odometry and sets the new velocity commands.
ackermann_controller::SpeedLimiter limiter_
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
bool has_deceleration_limits
void setVelocityRollingWindowSize(size_t velocity_rolling_window_size)
Velocity rolling window size setter.
double limit(double &v, double v0, double v1, double dt)
Limit the velocity and acceleration.
boost::shared_ptr< urdf::ModelInterface > getURDFModel(const ros::NodeHandle &nh)
bool init(hardware_interface::RobotHW *hw, ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
Initialize controller.
double getHeading() const
heading getter
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
const std::string & getNamespace() const
void updateOpenLoop(double linear, double angular, const ros::Time &time)
Updates the odometry class with latest velocity command.
realtime_tools::RealtimeBuffer< Commands > command_
void moveRobot(const ros::Time &time, const ros::Duration &period)
double getLinear() const
linear velocity getter
JointHandle getHandle(const std::string &name)
std::string base_frame_id_
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
ackermann_controller::Odometry odometry_
std::string odom_frame_id_
bool getParam(const std::string &key, std::string &s) const
int velocity_rolling_window_size_
double getX() const
x position getter
bool has_acceleration_limits
#define ROS_ERROR_NAMED(name,...)
void init(const ros::Time &time)
Initialize the odometry.
bool hasParam(const std::string &key) const
std::vector< std::string > getJointNames(ros::NodeHandle &controller_nh, const std::string ¶m)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
double getAngular() const
angular velocity getter