Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <cob_base_velocity_smoother.h>
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 void cob_base_velocity_smoother::set_new_msg_received(bool received)
00032 {
00033 pthread_mutex_lock(&m_mutex);
00034 new_msg_received_ = received;
00035 pthread_mutex_unlock(&m_mutex);
00036 }
00037
00038 bool cob_base_velocity_smoother::get_new_msg_received()
00039 {
00040 pthread_mutex_lock(&m_mutex);
00041 bool ret_val = new_msg_received_;
00042 pthread_mutex_unlock(&m_mutex);
00043 return ret_val;
00044 }
00045
00046
00047 cob_base_velocity_smoother::cob_base_velocity_smoother()
00048 {
00049 m_mutex = PTHREAD_MUTEX_INITIALIZER;
00050 new_msg_received_ = false;
00051
00052
00053 nh_ = ros::NodeHandle();
00054 pnh_ = ros::NodeHandle("~");
00055
00056
00057 pub_ = nh_.advertise<geometry_msgs::Twist>("output", 1);
00058
00059
00060 geometry_msgs_sub_ = nh_.subscribe<geometry_msgs::Twist>("input", 1, boost::bind(&cob_base_velocity_smoother::geometryCallback, this, _1));
00061
00062
00063 if( !pnh_.hasParam("circular_buffer_capacity") )
00064 {
00065 ROS_WARN("No parameter circular_buffer_capacity on parameter server. Using default [12]");
00066 }
00067 pnh_.param("circular_buffer_capacity", buffer_capacity_, 12);
00068
00069 if( !pnh_.hasParam("maximal_time_delay") )
00070 {
00071 ROS_WARN("No parameter maximal_time_delay on parameter server. Using default [4 in s]");
00072 }
00073 pnh_.param("maximal_time_delay", store_delay_, 4.0);
00074
00075 if( !pnh_.hasParam("maximal_time_delay_to_stop") )
00076 {
00077 ROS_WARN("No parameter maximal_time_delay_to_stop on parameter server. Using default [0.1 in s]");
00078 }
00079 pnh_.param("maximal_time_delay_to_stop", stop_delay_after_no_sub_, 0.1);
00080
00081 if( !pnh_.hasParam("thresh_max_acc") )
00082 {
00083 ROS_WARN("No parameter thresh_max_acc on parameter server. Using default [0.3 in m/s]");
00084 }
00085 pnh_.param("thresh_max_acc", acc_limit_, 0.3);
00086
00087 if( !pnh_.hasParam("loop_rate") )
00088 {
00089 ROS_WARN("No parameter loop_rate on parameter server. Using default [30 in Hz]");
00090 }
00091 pnh_.param("loop_rate", loop_rate_, 30.0);
00092
00093 double min_input_rate;
00094 if( !pnh_.hasParam("min_input_rate") )
00095 {
00096 ROS_WARN("No parameter min_input_rate on parameter server. Using default [9 in Hz]");
00097 }
00098 pnh_.param("min_input_rate", min_input_rate, 9.0);
00099
00100 if( min_input_rate > loop_rate_)
00101 {
00102 ROS_WARN("min_input_rate > loop_rate: Setting min_input_rate to loop_rate = %f", loop_rate_);
00103 min_input_rate = loop_rate_;
00104 }
00105 max_delay_between_commands_ = 1/min_input_rate;
00106
00107
00108 zero_values_.linear.x = 0.0;
00109 zero_values_.linear.y = 0.0;
00110 zero_values_.linear.z = 0.0;
00111
00112 zero_values_.angular.x = 0.0;
00113 zero_values_.angular.y = 0.0;
00114 zero_values_.angular.z = 0.0;
00115
00116
00117 cb_.set_capacity(buffer_capacity_);
00118 cb_out_.set_capacity(buffer_capacity_);
00119 cb_time_.set_capacity(buffer_capacity_);
00120
00121
00122 ros::Time now = ros::Time::now();
00123
00124
00125 while(cb_.full() == false)
00126 {
00127 cb_.push_front(zero_values_);
00128 cb_time_.push_front(now);
00129 }
00130 };
00131
00132
00133 cob_base_velocity_smoother::~cob_base_velocity_smoother(){}
00134
00135
00136 void cob_base_velocity_smoother::geometryCallback(const geometry_msgs::Twist::ConstPtr &cmd_vel)
00137 {
00138 sub_msg_ = *cmd_vel;
00139 set_new_msg_received(true);
00140 }
00141
00142
00143 void cob_base_velocity_smoother::calculationStep()
00144 {
00145
00146 ros::Time now = ros::Time::now();
00147 static ros::Time last = now;
00148
00149 geometry_msgs::Twist result = geometry_msgs::Twist();
00150
00151
00152 if (get_new_msg_received())
00153 {
00154
00155 result = this->setOutput(now, sub_msg_);
00156 pub_.publish(result);
00157
00158 last = now;
00159 set_new_msg_received(false);
00160 }
00161
00162
00163 else if ( fabs((last - now).toSec()) > max_delay_between_commands_)
00164 {
00165 result = this->setOutput(now, geometry_msgs::Twist());
00166 }
00167
00168 else if (IsZeroMsg(sub_msg_))
00169 {
00170 result = this->setOutput(now, sub_msg_);
00171 pub_.publish(result);
00172 }
00173 }
00174
00175
00176
00177
00178 geometry_msgs::Twist cob_base_velocity_smoother::setOutput(ros::Time now, geometry_msgs::Twist cmd_vel)
00179 {
00180 geometry_msgs::Twist result = zero_values_;
00181
00182
00183 this->reviseCircBuff(now, cmd_vel);
00184
00185
00186 result.linear.x = meanValueX();
00187 result.linear.y = meanValueY();
00188 result.angular.z = meanValueZ();
00189
00190
00191 this->limitAcceleration(now, result);
00192
00193
00194 cb_out_.push_front(result);
00195
00196 return result;
00197 }
00198
00199
00200 void cob_base_velocity_smoother::reviseCircBuff(ros::Time now, geometry_msgs::Twist cmd_vel)
00201 {
00202 if(this->circBuffOutOfDate(now) == true)
00203 {
00204
00205
00206
00207 cb_.clear();
00208 cb_time_.clear();
00209
00210
00211 while(cb_.full() == false)
00212 {
00213 cb_.push_front(zero_values_);
00214 cb_time_.push_front(now);
00215 }
00216
00217
00218 cb_.push_front(cmd_vel);
00219
00220 cb_time_.push_front(now);
00221 }
00222 else
00223 {
00224
00225 double delay=(now.toSec() - cb_time_.back().toSec());
00226
00227 while( delay >= store_delay_ )
00228 {
00229
00230 cb_.pop_back();
00231 cb_time_.pop_back();
00232
00233 delay=(now.toSec() - cb_time_.back().toSec());
00234 }
00235
00236 if(cb_.empty() == true)
00237 {
00238 while(cb_.full() == false)
00239 {
00240 cb_.push_front(zero_values_);
00241 cb_time_.push_front(now);
00242 }
00243 }
00244 if(this->IsZeroMsg(cmd_vel))
00245 {
00246
00247 long unsigned int size = floor( cb_.size() / 3 );
00248
00249
00250 for(long unsigned int i=0; i< size; i++)
00251 {
00252
00253 cb_.push_front(cmd_vel);
00254
00255 cb_time_.push_front(now);
00256 }
00257 }
00258 else
00259 {
00260
00261 cb_.push_front(cmd_vel);
00262
00263 cb_time_.push_front(now);
00264 }
00265 }
00266 };
00267
00268
00269 bool cob_base_velocity_smoother::circBuffOutOfDate(ros::Time now)
00270 {
00271 bool result=true;
00272
00273 long unsigned int count=0;
00274
00275 while( (count < cb_.size()) && (result == true) )
00276 {
00277 double delay=(now.toSec() - cb_time_[count].toSec());
00278 if(delay < store_delay_)
00279 {
00280 result = false;
00281 }
00282 count++;
00283 }
00284
00285 return result;
00286 };
00287
00288
00289 bool cob_base_velocity_smoother::IsZeroMsg(geometry_msgs::Twist cmd_vel)
00290 {
00291 bool result = true;
00292 if( (cmd_vel.linear.x) != 0 || (cmd_vel.linear.y != 0) || (cmd_vel.angular.z != 0) )
00293 {
00294 result = false;
00295 }
00296
00297 return result;
00298 };
00299
00300 int cob_base_velocity_smoother::signum(double var)
00301 {
00302 if(var < 0)
00303 {
00304 return -1;
00305 }
00306 else
00307 {
00308 return 1;
00309 }
00310 };
00311
00312
00313 double cob_base_velocity_smoother::meanValueX()
00314 {
00315 double result = 0;
00316 long unsigned int size = cb_.size();
00317
00318
00319 for(long unsigned int i=0; i<size; i++)
00320 {
00321 result += cb_[i].linear.x;
00322 }
00323 result /= size;
00324
00325 if(size > 1)
00326 {
00327 double help_result = 0;
00328 double max = cb_[0].linear.x;
00329 long unsigned int max_ind = 0;
00330 for(long unsigned int i=0; i<size; i++)
00331 {
00332 if(abs(result-cb_[i].linear.x) > abs(result-max))
00333 {
00334 max = cb_[i].linear.x;
00335 max_ind = i;
00336 }
00337 }
00338
00339
00340 for(long unsigned int i=0; i<size; i++)
00341 {
00342 if(i != max_ind)
00343 {
00344 help_result += cb_[i].linear.x;
00345 }
00346 }
00347 result = help_result / (size - 1);
00348 }
00349
00350 return result;
00351 };
00352
00353
00354 double cob_base_velocity_smoother::meanValueY()
00355 {
00356 double result = 0;
00357 long unsigned int size = cb_.size();
00358
00359
00360 for(long unsigned int i=0; i<size; i++)
00361 {
00362 result += cb_[i].linear.y;
00363 }
00364 result /= size;
00365
00366 if(size > 1)
00367 {
00368 double help_result = 0;
00369 double max = cb_[0].linear.y;
00370 long unsigned int max_ind = 0;
00371 for(long unsigned int i=0; i<size; i++)
00372 {
00373 if(abs(result-cb_[i].linear.y) > abs(result-max))
00374 {
00375 max = cb_[i].linear.y;
00376 max_ind = i;
00377 }
00378 }
00379
00380
00381 for(long unsigned int i=0; i<size; i++)
00382 {
00383 if(i != max_ind)
00384 {
00385 help_result += cb_[i].linear.y;
00386 }
00387 }
00388 result = help_result / (size - 1);
00389 }
00390
00391 return result;
00392 };
00393
00394
00395 double cob_base_velocity_smoother::meanValueZ()
00396 {
00397 double result = 0;
00398 long unsigned int size = cb_.size();
00399
00400
00401 for(long unsigned int i=0; i<size; i++)
00402 {
00403 result += cb_[i].angular.z;
00404 }
00405 result /= size;
00406
00407 if(size > 1)
00408 {
00409 double help_result = 0;
00410 double max = cb_[0].angular.z;
00411 long unsigned int max_ind = 0;
00412 for(long unsigned int i = 0; i < size; i++)
00413 {
00414 if(abs(result-cb_[i].angular.z) > abs(result-max))
00415 {
00416 max = cb_[i].angular.z;
00417 max_ind = i;
00418 }
00419 }
00420
00421
00422 for(long unsigned int i = 0; i < size; i++)
00423 {
00424 if(i != max_ind)
00425 {
00426 help_result += cb_[i].angular.z;
00427 }
00428 }
00429 result = help_result / (size - 1);
00430 }
00431
00432 return result;
00433 };
00434
00435
00436 double cob_base_velocity_smoother::getLoopRate()
00437 {
00438 return loop_rate_;
00439 }
00440
00441
00442 bool cob_base_velocity_smoother::IsEqual(geometry_msgs::Twist msg1, geometry_msgs::Twist msg2)
00443 {
00444 if( (msg1.linear.x == msg2.linear.x) && (msg1.linear.y == msg2.linear.y) && (msg1.angular.z == msg2.angular.z))
00445 {
00446 return true;
00447 }
00448 else
00449 {
00450 return false;
00451 }
00452 }
00453
00454
00455 void cob_base_velocity_smoother::limitAcceleration(ros::Time now, geometry_msgs::Twist& result)
00456 {
00457
00458
00459
00460 double deltaTime = 0;
00461
00462 if(cb_time_.size() > 1)
00463 {
00464 deltaTime = now.toSec() - cb_time_[2].toSec();
00465 }
00466
00467 if( cb_out_.size() > 0)
00468 {
00469 if(deltaTime > 0)
00470 {
00471
00472 double deltaX = result.linear.x - cb_out_.front().linear.x;
00473
00474 double deltaY = result.linear.y - cb_out_.front().linear.y;
00475
00476 double deltaZ = result.angular.z - cb_out_.front().angular.z;
00477
00478 if( abs(deltaX) > acc_limit_)
00479 {
00480 result.linear.x = cb_out_.front().linear.x + this->signum(deltaX) * acc_limit_;
00481 }
00482 if( abs(deltaY) > acc_limit_ )
00483 {
00484 result.linear.y = cb_out_.front().linear.y + this->signum(deltaY) * acc_limit_;
00485 }
00486 if( abs(deltaZ) > acc_limit_ )
00487 {
00488 result.angular.z = cb_out_.front().angular.z + this->signum(deltaZ) * acc_limit_;
00489 }
00490 }
00491 }
00492 };
00493
00494
00495 int main(int argc, char **argv)
00496 {
00497
00498 ros::init(argc, argv, "cob_base_velocity_smoother");
00499
00500
00501 cob_base_velocity_smoother my_velocity_smoother;
00502
00503 ros::Rate rate(my_velocity_smoother.getLoopRate());
00504
00505 while(my_velocity_smoother.nh_.ok())
00506 {
00507 my_velocity_smoother.calculationStep();
00508
00509 ros::spinOnce();
00510 rate.sleep();
00511 }
00512
00513 return 0;
00514 }