42 #include <urdf_parser/urdf_parser.h> 48 return std::sqrt(std::pow(vec1.x-vec2.x,2) +
49 std::pow(vec1.y-vec2.y,2) +
50 std::pow(vec1.z-vec2.z,2));
58 static bool isCylinder(
const urdf::LinkConstSharedPtr& link)
68 ROS_ERROR_STREAM(
"Link " << link->name <<
" does not have collision description. Add collision description for link to urdf.");
72 if (!link->collision->geometry)
74 ROS_ERROR_STREAM(
"Link " << link->name <<
" does not have collision geometry description. Add collision geometry description for link to urdf.");
78 if (link->collision->geometry->type != urdf::Geometry::CYLINDER)
80 ROS_ERROR_STREAM(
"Link " << link->name <<
" does not have cylinder geometry");
94 static bool getWheelRadius(
const urdf::LinkConstSharedPtr& wheel_link,
double& wheel_radius)
98 ROS_ERROR_STREAM(
"Wheel link " << wheel_link->name <<
" is NOT modeled as a cylinder!");
102 wheel_radius = (
static_cast<urdf::Cylinder*
>(wheel_link->collision->geometry.get()))->radius;
111 , wheel_separation_h_(0.0)
113 , wheel_separation_h_multiplier_(1.0)
114 , wheel_radius_multiplier_(1.0)
115 , steer_pos_multiplier_(1.0)
116 , cmd_vel_timeout_(0.5)
117 , allow_multiple_cmd_vel_publishers_(true)
118 , base_frame_id_(
"base_link")
119 , odom_frame_id_(
"odom")
120 , enable_odom_tf_(true)
121 , wheel_joints_size_(0)
134 VelIface *vel_joint_if = robot_hw->
get<VelIface>();
135 PosIface *pos_joint_if = robot_hw->
get<PosIface>();
137 const std::string complete_ns = controller_nh.
getNamespace();
139 std::size_t
id = complete_ns.find_last_of(
"/");
140 name_ = complete_ns.substr(
id + 1);
143 std::string rear_wheel_name =
"rear_wheel_joint";
144 controller_nh.
param(
"rear_wheel", rear_wheel_name, rear_wheel_name);
147 std::string front_steer_name =
"front_steer_joint";
148 controller_nh.
param(
"front_steer", front_steer_name, front_steer_name);
153 controller_nh.
param(
"publish_rate", publish_rate, 50.0);
155 << publish_rate <<
"Hz.");
172 int velocity_rolling_window_size = 10;
173 controller_nh.
param(
"velocity_rolling_window_size", velocity_rolling_window_size, velocity_rolling_window_size);
175 << velocity_rolling_window_size <<
".");
225 lookup_wheel_separation_h,
226 lookup_wheel_radius))
237 "Odometry params : wheel separation height " << ws_h
238 <<
", wheel radius " << wr);
245 "Adding the rear wheel with joint name: " << rear_wheel_name);
249 "Adding the front steer with joint name: " << front_steer_name);
252 "Adding the subscriber: cmd_vel");
271 if (std::isnan(wheel_pos) || std::isnan(steer_pos))
284 const geometry_msgs::Quaternion orientation(
293 odom_pub_->msg_.pose.pose.orientation = orientation;
302 geometry_msgs::TransformStamped& odom_frame =
tf_odom_pub_->msg_.transforms[0];
303 odom_frame.header.stamp = time;
306 odom_frame.transform.rotation = orientation;
314 const double dt = (time - curr_cmd.
stamp).toSec();
324 const double cmd_dt(period.
toSec());
356 const double steer_pos = 0.0;
357 const double wheel_vel = 0.0;
371 <<
" publishers. Only 1 publisher is allowed. Going to brake.");
381 "Added values to command. " 394 const std::string rear_wheel_name,
395 const std::string front_steer_name,
396 bool lookup_wheel_separation_h,
397 bool lookup_wheel_radius)
399 if (!(lookup_wheel_separation_h || lookup_wheel_radius))
406 const std::string model_param_name =
"robot_description";
407 bool res = root_nh.
hasParam(model_param_name);
408 std::string robot_model_str=
"";
409 if (!res || !root_nh.
getParam(model_param_name,robot_model_str))
415 urdf::ModelInterfaceSharedPtr model(urdf::parseURDF(robot_model_str));
417 urdf::JointConstSharedPtr rear_wheel_joint(model->getJoint(rear_wheel_name));
418 urdf::JointConstSharedPtr front_steer_joint(model->getJoint(front_steer_name));
420 if (lookup_wheel_separation_h)
423 if (!rear_wheel_joint)
426 <<
" couldn't be retrieved from model description");
430 if (!front_steer_joint)
433 <<
" couldn't be retrieved from model description");
438 << rear_wheel_joint->parent_to_joint_origin_transform.position.x <<
"," 439 << rear_wheel_joint->parent_to_joint_origin_transform.position.y <<
", " 440 << rear_wheel_joint->parent_to_joint_origin_transform.position.z);
443 << front_steer_joint->parent_to_joint_origin_transform.position.x <<
"," 444 << front_steer_joint->parent_to_joint_origin_transform.position.y <<
", " 445 << front_steer_joint->parent_to_joint_origin_transform.position.z);
448 rear_wheel_joint->parent_to_joint_origin_transform.position.x
449 - front_steer_joint->parent_to_joint_origin_transform.position.x);
454 if (lookup_wheel_radius)
472 controller_nh.
getParam(
"pose_covariance_diagonal", pose_cov_list);
475 for (
int i = 0; i < pose_cov_list.
size(); ++i)
479 controller_nh.
getParam(
"twist_covariance_diagonal", twist_cov_list);
482 for (
int i = 0; i < twist_cov_list.
size(); ++i)
489 odom_pub_->msg_.pose.pose.position.z = 0;
491 static_cast<double>(pose_cov_list[0]), 0., 0., 0., 0., 0.,
492 0., static_cast<double>(pose_cov_list[1]), 0., 0., 0., 0.,
493 0., 0.,
static_cast<double>(pose_cov_list[2]), 0., 0., 0.,
494 0., 0., 0., static_cast<double>(pose_cov_list[3]), 0., 0.,
495 0., 0., 0., 0.,
static_cast<double>(pose_cov_list[4]), 0.,
496 0., 0., 0., 0., 0., static_cast<double>(pose_cov_list[5]) };
497 odom_pub_->msg_.twist.twist.linear.y = 0;
498 odom_pub_->msg_.twist.twist.linear.z = 0;
499 odom_pub_->msg_.twist.twist.angular.x = 0;
500 odom_pub_->msg_.twist.twist.angular.y = 0;
502 static_cast<double>(twist_cov_list[0]), 0., 0., 0., 0., 0.,
503 0., static_cast<double>(twist_cov_list[1]), 0., 0., 0., 0.,
504 0., 0.,
static_cast<double>(twist_cov_list[2]), 0., 0., 0.,
505 0., 0., 0., static_cast<double>(twist_cov_list[3]), 0., 0.,
506 0., 0., 0., 0.,
static_cast<double>(twist_cov_list[4]), 0.,
507 0., 0., 0., 0., 0., static_cast<double>(twist_cov_list[5]) };
510 tf_odom_pub_->msg_.transforms[0].transform.translation.z = 0.0;
AckermannSteeringController()
void init(const ros::Time &time)
Initialize the odometry.
double getX() const
x position getter
diff_drive_controller::SpeedLimiter limiter_lin_
realtime_tools::RealtimeBuffer< Commands > command_
void starting(const ros::Time &time)
Starts controller.
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
void update(const ros::Time &time, const ros::Duration &period)
Updates controller, i.e. computes the odometry and sets the new velocity commands.
double wheel_radius_multiplier_
std::shared_ptr< realtime_tools::RealtimePublisher< tf::tfMessage > > tf_odom_pub_
bool enable_odom_tf_
Whether to publish odometry to tf or not:
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
bool has_acceleration_limits
void brake()
Brakes the wheels, i.e. sets the velocity to 0.
void stopping(const ros::Time &)
Stops controller.
uint32_t getNumPublishers() const
#define ROS_INFO_STREAM_NAMED(name, args)
hardware_interface::JointHandle front_steer_joint_
std::string base_frame_id_
Frame to use for the robot base:
#define ROS_ERROR_STREAM_THROTTLE_NAMED(period, name, args)
PLUGINLIB_EXPORT_CLASS(diff_drive_controller::DiffDriveController, controller_interface::ControllerBase)
void setWheelParams(double wheel_reparation_h, double wheel_radius)
Sets the wheel parameters: radius and separation.
double steer_pos_multiplier_
ros::Duration publish_period_
Odometry related:
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
Type const & getType() const
bool init(hardware_interface::RobotHW *robot_hw, ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
Initialize controller.
bool setOdomParamsFromUrdf(ros::NodeHandle &root_nh, const std::string rear_wheel_name, const std::string front_steer_name, bool lookup_wheel_separation_h, bool lookup_wheel_radius)
Sets odometry parameters from the URDF, i.e. the wheel radius and separation.
double wheel_separation_h_multiplier_
Wheel separation and radius calibration multipliers:
static double euclideanOfVectors(const urdf::Vector3 &vec1, const urdf::Vector3 &vec2)
bool getParam(const std::string &key, std::string &s) const
ros::Time last_state_publish_time_
std::string odom_frame_id_
Frame to use for odometry and odom tf:
void updateOpenLoop(double linear, double angular, const ros::Time &time)
Updates the odometry class with latest velocity command.
std::shared_ptr< realtime_tools::RealtimePublisher< nav_msgs::Odometry > > odom_pub_
Odometry related:
bool allow_multiple_cmd_vel_publishers_
Whether to allow multiple publishers on cmd_vel topic or not:
double getLinear() const
linear velocity getter
diff_drive_controller::SpeedLimiter limiter_ang_
ros::Subscriber sub_command_
double getY() const
y position getter
double cmd_vel_timeout_
Timeout to consider cmd_vel commands old:
bool hasParam(const std::string &key) const
double getHeading() const
heading getter
static bool isCylinder(const urdf::LinkConstSharedPtr &link)
double wheel_separation_h_
Wheel separation, wrt the midpoint of the wheel width:
hardware_interface::JointHandle rear_wheel_joint_
Hardware handles:
double getAngular() const
angular velocity getter
void setCommand(double command)
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
#define ROS_INFO_STREAM(args)
Commands last1_cmd_
Speed limiters:
const std::string & getNamespace() const
#define ROS_ERROR_NAMED(name,...)
void setOdomPubFields(ros::NodeHandle &root_nh, ros::NodeHandle &controller_nh)
Sets the odometry publishing fields.
Velocity command related:
#define ROS_ERROR_STREAM(args)
static bool getWheelRadius(const urdf::LinkConstSharedPtr &wheel_link, double &wheel_radius)
double limit(double &v, double v0, double v1, double dt)
double wheel_radius_
Wheel radius (assuming it's the same for the left and right wheels):
void cmdVelCallback(const geometry_msgs::Twist &command)
Velocity command callback.
void setVelocityRollingWindowSize(size_t velocity_rolling_window_size)
Velocity rolling window size setter.
bool update(double rear_wheel_pos, double front_steer_pos, const ros::Time &time)
Updates the odometry class with latest wheels position.
double getPosition() const