cmd_vel_smoother.cpp
Go to the documentation of this file.
00001 #include <cmath>
00002 #include <boost/shared_ptr.hpp>
00003 #include <ros/ros.h>
00004 #include <dynamic_reconfigure/server.h>
00005 #include <cmd_vel_smoother/CmdVelSmootherConfig.h>
00006 #include <geometry_msgs/Twist.h>
00007 
00008 template<class T> inline T sgn(T val) { return val > 0 ? 1.0 : -1.0; }
00009 
00010 namespace dyn = dynamic_reconfigure;
00011 
00012 class VelocitySmootherNode
00013 {
00014   ros::NodeHandle nh_, pnh_;
00015   ros::Publisher  pub_;
00016   ros::Subscriber sub_;
00017   ros::Timer timer_;
00018 
00019   boost::mutex cfg_mutex_;
00020   typedef cmd_vel_smoother::CmdVelSmootherConfig Config;
00021   boost::shared_ptr<dyn::Server<Config> > dyn_srv_;
00022   
00023   int interpolate_max_frame_, count_;
00024   double desired_rate_;
00025   double x_acc_lim_, y_acc_lim_, yaw_acc_lim_;
00026   ros::Time latest_time_;
00027   geometry_msgs::Twist::ConstPtr latest_vel_;
00028   geometry_msgs::Twist::Ptr pub_vel_;
00029 
00030 public:
00031   ros::Duration timerDuration() {
00032     return ros::Duration(1./(desired_rate_ * 2.2));
00033   }
00034 
00035   void dynConfigCallback(Config &cfg, uint32_t level) {
00036     boost::mutex::scoped_lock lock(cfg_mutex_);
00037     x_acc_lim_ = cfg.x_acc_lim;
00038     y_acc_lim_ = cfg.y_acc_lim;
00039     yaw_acc_lim_ = cfg.yaw_acc_lim;
00040     interpolate_max_frame_ = cfg.interpolate_max_frame;
00041 
00042     if(desired_rate_ != cfg.desired_rate) {
00043       desired_rate_ = cfg.desired_rate;
00044       if (timer_.isValid()) {
00045         ros::Duration d = timerDuration();
00046         timer_.setPeriod(d);
00047         ROS_INFO_STREAM("timer loop rate is changed to " << 1.0 / d.toSec() << "[Hz]");
00048       }
00049     }
00050   }
00051 
00052   void velCallback(const geometry_msgs::Twist::ConstPtr &msg){
00053     latest_time_ = ros::Time::now();
00054     latest_vel_ = msg;
00055     count_ = 0;
00056     pub_.publish(msg);
00057   }
00058 
00059   void timerCallback(const ros::TimerEvent& event){
00060     if (count_ > interpolate_max_frame_) return;
00061     if (latest_vel_ == NULL) return;
00062 
00063     double past_sec = (event.current_real - latest_time_).toSec();
00064     if (past_sec < 1.0 / desired_rate_) return;
00065 
00066     double g_x   = std::abs(latest_vel_->linear.x  / past_sec);
00067     double g_y   = std::abs(latest_vel_->linear.y  / past_sec);
00068     double g_yaw = std::abs(latest_vel_->angular.z / past_sec);
00069 
00070     ROS_DEBUG_STREAM("G: (" << g_x << ", " << g_y << ", " << g_yaw << ") detected");
00071 
00072     bool need_publish = false;
00073     if (g_x > x_acc_lim_) {
00074       pub_vel_->linear.x = (g_x - x_acc_lim_) * past_sec * sgn(latest_vel_->linear.x);
00075       need_publish = true;
00076     }
00077 
00078     if (g_y > y_acc_lim_) {
00079       pub_vel_->linear.y = (g_y - y_acc_lim_) * past_sec * sgn(latest_vel_->linear.y);
00080       need_publish = true;
00081     }
00082 
00083     if (g_yaw > yaw_acc_lim_) {
00084       pub_vel_->angular.z = (g_yaw - yaw_acc_lim_) * past_sec * sgn(latest_vel_->angular.z);
00085       need_publish = true;
00086     }
00087 
00088     if (need_publish)
00089       pub_.publish(*pub_vel_);
00090     count_++;
00091   }
00092 
00093   VelocitySmootherNode(): nh_(), pnh_("~") {
00094     latest_time_ = ros::Time::now();
00095 
00096     dyn_srv_ = boost::make_shared<dyn::Server<Config> >(pnh_);
00097     dyn::Server<Config>::CallbackType f = boost::bind(&VelocitySmootherNode::dynConfigCallback, this, _1, _2);
00098     dyn_srv_->setCallback(f);
00099     
00100     pub_vel_ = boost::shared_ptr<geometry_msgs::Twist>(new geometry_msgs::Twist());
00101     pub_ = nh_.advertise<geometry_msgs::Twist>("output", 100);
00102     sub_ = nh_.subscribe("input", 1, &VelocitySmootherNode::velCallback, this);
00103     timer_ = nh_.createTimer(timerDuration(), &VelocitySmootherNode::timerCallback, this);
00104   };
00105   ~VelocitySmootherNode() {};
00106 
00107 };
00108 
00109 int main(int argc, char** argv) {
00110   ros::init(argc, argv, "cmd_vel_smoother");
00111   VelocitySmootherNode n;
00112   ros::spin();
00113 
00114   return 0;
00115 }
00116 


cmd_vel_smoother
Author(s): Yuki Furuta
autogenerated on Fri Apr 19 2019 03:45:15