velocity_limited_marker.cpp
Go to the documentation of this file.
00001 /****************************************************************
00002  *
00003  * Copyright (c) 2012 Brno University of Technology (BUT)
00004  *
00005  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00006  *
00007  * Project name: care-o-bot
00008  * ROS stack name: cob_navigation
00009  * ROS package name: cob_collision_velocity_filter
00010  *                                                      
00011  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00012  *              
00013  * Author: Michal Spanel, email:spanel@fit.vutbr.cz
00014  *
00015  * Date of creation: November 2012
00016  *
00017  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00018  *
00019  * Redistribution and use in source and binary forms, with or without
00020  * modification, are permitted provided that the following conditions are met:
00021  *
00022  *   * Redistributions of source code must retain the above copyright
00023  *       notice, this list of conditions and the following disclaimer.
00024  *   * Redistributions in binary form must reproduce the above copyright
00025  *       notice, this list of conditions and the following disclaimer in the
00026  *       documentation and/or other materials provided with the distribution.
00027  *   * Neither the name of the Fraunhofer Institute for Manufacturing 
00028  *       Engineering and Automation (IPA) nor the names of its
00029  *       contributors may be used to endorse or promote products derived from
00030  *       this software without specific prior written permission.
00031  *
00032  * This program is free software: you can redistribute it and/or modify
00033  * it under the terms of the GNU Lesser General Public License LGPL as 
00034  * published by the Free Software Foundation, either version 3 of the 
00035  * License, or (at your option) any later version.
00036  * 
00037  * This program is distributed in the hope that it will be useful,
00038  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00039  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00040  * GNU Lesser General Public License LGPL for more details.
00041  * 
00042  * You should have received a copy of the GNU Lesser General Public 
00043  * License LGPL along with this program. 
00044  * If not, see <http://www.gnu.org/licenses/>.
00045  *
00046  ****************************************************************/
00047 
00048 #include <velocity_limited_marker.h>
00049 
00050 #include <tf/tf.h>
00051 
00052 
00053 namespace cob_collision_velocity_filter
00054 {
00055 
00056 const double DEFAULT_LIFETIME   = 1.0;
00057 const double DEFAULT_Z_POSITION = 0.25;
00058 
00059 const double MARKER_SCALE_DIR   = 1.0;
00060 const double MARKER_RADIUS_DIR  = 0.5;
00061 const double MARKER_WIDTH_DIR   = 0.2;
00062 
00063 const double MARKER_SCALE_ROT   = 1.0;
00064 const double MARKER_RADIUS_ROT  = 0.6;
00065 //const double MARKER_WIDTH_ROT   = 0.065;
00066 const double MARKER_WIDTH_ROT   = 0.15;
00067 
00068 //const double MAX_VELOCITY       = 0.2;
00069 const double MAX_VELOCITY       = 0.25;
00070 const double MIN_VELOCITY       = 0.01;
00071 const double VELOCITY_COEFF     = 1.0 / (MAX_VELOCITY - MIN_VELOCITY);
00072 
00073 const float MAX_COLOR[4]        = { 1.0f, 0.0f, 0.0f, 1.0f };
00074 const float MIN_COLOR[4]        = { 1.0f, 0.8f, 0.0f, 0.2f };
00075 
00076 
00077 VelocityLimitedMarker::VelocityLimitedMarker()
00078 {
00079     // a handle for this node, initialize node
00080     nh_ = ros::NodeHandle("~");
00081 
00082     // read parameters from parameter server
00083     nh_.param("marker_frame", base_frame_, std::string("/base_link"));
00084     nh_.param("marker_topic_name", topic_name_, std::string("velocity_limited_marker"));
00085     nh_.param("marker_lifetime", lifetime_, DEFAULT_LIFETIME);
00086     nh_.param("z_pos", z_pos_, DEFAULT_Z_POSITION);
00087     nh_.param("marker_disabled", disabled_, false);
00088 
00089     // Create the publisher
00090     marker_pub_ = nh_.advertise<visualization_msgs::Marker>(topic_name_, 1);
00091 
00092     vx_last_ = 0.0;
00093     vy_last_ = 0.0;
00094     vtheta_last_ = 0.0;
00095 
00096     // Create the markers
00097     createDirectionalMarkers();
00098     createRotationalMarkers();
00099 }
00100 
00101 
00102 VelocityLimitedMarker::~VelocityLimitedMarker()
00103 {
00104 }
00105 
00106 
00107 void VelocityLimitedMarker::createDirectionalMarkers()
00108 {
00109     // Message template
00110     visualization_msgs::Marker marker;
00111     marker.header.frame_id = base_frame_;
00112     marker.header.stamp = ros::Time::now();
00113     marker.ns = "cob_velocity_limited_marker";
00114     marker.id = 0;
00115     marker.type = visualization_msgs::Marker::TRIANGLE_LIST;
00116     marker.action = visualization_msgs::Marker::ADD;
00117     marker.lifetime = ros::Duration(lifetime_);
00118     marker.pose.orientation.x = 0;
00119     marker.pose.orientation.y = 0;
00120     marker.pose.orientation.z = 0;
00121     marker.pose.orientation.w = 1;
00122     marker.pose.position.x = 0;
00123     marker.pose.position.y = 0;
00124     marker.pose.position.z = z_pos_;
00125     marker.scale.x = MARKER_SCALE_DIR;
00126     marker.scale.y = MARKER_SCALE_DIR;
00127     marker.scale.z = 1.0;
00128     marker.color.r = 1.0;
00129     marker.color.g = 0.0;
00130     marker.color.b = 0.0;
00131     marker.color.a = 0.5; // adjust according to the velocity?
00132 
00133     // Create the disc like geometry for the markers
00134     std::vector<geometry_msgs::Point> circle1, circle2;
00135     geometry_msgs::Point v1, v2;
00136 
00137     static const int STEPS = 36;
00138     static const int FIRST = -4;
00139     static const int LAST = 4;
00140     for( int i = FIRST; i <= LAST; ++i )
00141     {
00142         float a = float(i) / float(STEPS) * M_PI * 2.0;
00143         float cosa = cos(a);
00144         float sina = sin(a);
00145 
00146         v1.x = MARKER_RADIUS_DIR * cosa;
00147         v1.y = MARKER_RADIUS_DIR * sina;
00148         v2.x = (MARKER_RADIUS_DIR + MARKER_WIDTH_DIR) * cosa;
00149         v2.y = (MARKER_RADIUS_DIR + MARKER_WIDTH_DIR) * sina;
00150 
00151         circle1.push_back(v1);
00152         circle2.push_back(v2);
00153     }
00154 
00155     marker.points.clear();
00156     for( std::size_t i = 0; i < (circle1.size() - 1); ++i )
00157     {
00158         std::size_t i1 = i;
00159         std::size_t i2 = (i + 1) % circle1.size();
00160 
00161         marker.points.push_back(circle1[i1]);
00162         marker.points.push_back(circle2[i1]);
00163         marker.points.push_back(circle1[i2]);
00164 
00165         marker.points.push_back(circle1[i2]);
00166         marker.points.push_back(circle2[i2]);
00167         marker.points.push_back(circle2[i1]);
00168     }
00169 
00170     // Particular messages for each axis
00171     x_pos_marker_ = marker;
00172     x_pos_marker_.id = 0;
00173     x_pos_marker_.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, 0);
00174 
00175     x_neg_marker_ = marker;
00176     x_neg_marker_.id = 1;
00177     x_neg_marker_.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, M_PI);
00178 
00179     y_pos_marker_ = marker;
00180     y_pos_marker_.id = 2;
00181     y_pos_marker_.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, 0.5 * M_PI);
00182 
00183     y_neg_marker_ = marker;
00184     y_neg_marker_.id = 3;
00185     y_neg_marker_.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, -0.5 * M_PI);
00186 }
00187 
00188 
00189 void VelocityLimitedMarker::createRotationalMarkers()
00190 {
00191     // Message template
00192     visualization_msgs::Marker marker;
00193     marker.header.frame_id = base_frame_;
00194     marker.header.stamp = ros::Time::now();
00195     marker.ns = "cob_velocity_limited_marker";
00196     marker.id = 0;
00197     marker.type = visualization_msgs::Marker::TRIANGLE_LIST;
00198     marker.action = visualization_msgs::Marker::ADD;
00199     marker.lifetime = ros::Duration(lifetime_);
00200     marker.pose.orientation.x = 0;
00201     marker.pose.orientation.y = 0;
00202     marker.pose.orientation.z = 0;
00203     marker.pose.orientation.w = 1;
00204     marker.pose.position.x = 0;
00205     marker.pose.position.y = 0;
00206     marker.pose.position.z = z_pos_;
00207     marker.scale.x = MARKER_SCALE_ROT;
00208     marker.scale.y = MARKER_SCALE_ROT;
00209     marker.scale.z = 1.0;
00210     marker.color.r = 1.0;
00211     marker.color.g = 0.0;
00212     marker.color.b = 0.0;
00213     marker.color.a = 0.5; // adjust according to the velocity?
00214 
00215     // Create the disc like geometry for the markers
00216     std::vector<geometry_msgs::Point> circle1, circle2, circle3;
00217     geometry_msgs::Point v1, v2, v3;
00218 
00219     static const int STEPS = 48;
00220     static const int FIRST = 0;
00221     static const int LAST = 23;
00222     for( int i = FIRST; i <= LAST; ++i )
00223     {
00224         float a = float(2*i) / float(STEPS) * M_PI * 2.0;
00225         float cosa = cos(a);
00226         float sina = sin(a);
00227 
00228         v1.x = MARKER_RADIUS_ROT * cosa;
00229         v1.y = MARKER_RADIUS_ROT * sina;
00230         v2.x = (MARKER_RADIUS_ROT + MARKER_WIDTH_ROT) * cosa;
00231         v2.y = (MARKER_RADIUS_ROT + MARKER_WIDTH_ROT) * sina;
00232 
00233         circle1.push_back(v1);
00234         circle2.push_back(v2);
00235 
00236         a = float(2*i+1) / float(STEPS) * M_PI * 2.0;
00237         cosa = cos(a);
00238         sina = sin(a);
00239 
00240         v3.x = (MARKER_RADIUS_ROT + 0.5 * MARKER_WIDTH_ROT) * cosa;
00241         v3.y = (MARKER_RADIUS_ROT + 0.5 * MARKER_WIDTH_ROT) * sina;
00242 
00243         circle3.push_back(v3);
00244     }
00245 
00246     marker.points.clear();
00247     for( std::size_t i = 0; i < circle1.size(); ++i )
00248     {
00249         marker.points.push_back(circle1[i]);
00250         marker.points.push_back(circle2[i]);
00251         marker.points.push_back(circle3[i]);
00252     }
00253 
00254     // Particular messages for each axis
00255     theta_pos_marker_ = marker;
00256     theta_pos_marker_.id = 4;
00257     theta_pos_marker_.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, 0);
00258 
00259     theta_neg_marker_ = marker;
00260     theta_neg_marker_.id = 5;
00261     theta_neg_marker_.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(M_PI, 0, 0);
00262 }
00263 
00264 
00265 void VelocityLimitedMarker::interpolateColor(double velocity, std_msgs::ColorRGBA& color)
00266 {
00267         if( velocity < MIN_VELOCITY )
00268         {
00269                 color.r = color.g = color.b = color.a = 0.0f;
00270                 return;
00271         }
00272 
00273     float alpha = float((velocity - MIN_VELOCITY) * VELOCITY_COEFF);
00274     alpha = (alpha > 1.0f) ? 1.0f : alpha;
00275 
00276     color.r = (1.0f - alpha) * MIN_COLOR[0] + alpha * MAX_COLOR[0];
00277     color.g = (1.0f - alpha) * MIN_COLOR[1] + alpha * MAX_COLOR[1];
00278     color.b = (1.0f - alpha) * MIN_COLOR[2] + alpha * MAX_COLOR[2];
00279     color.a = (1.0f - alpha) * MIN_COLOR[3] + alpha * MAX_COLOR[3];
00280 }
00281 
00282 
00283 void VelocityLimitedMarker::publishMarkers( double vel_x_desired, 
00284                                             double vel_x_actual, 
00285                                             double vel_y_desired, 
00286                                             double vel_y_actual, 
00287                                             double vel_theta_desired,
00288                                             double vel_theta_actual)
00289 {
00290     if( disabled_ )
00291     {
00292         return;
00293     }
00294 
00295     // Publish the markers
00296     double epsilon = 0.05;
00297 
00298     // acceleration
00299     double ax,ay,atheta;
00300     ax = vel_x_actual - vx_last_;
00301     ay = vel_y_actual - vy_last_;
00302     atheta = vel_theta_actual - vtheta_last_;
00303     vx_last_ = vel_x_actual;
00304     vy_last_ = vel_y_actual;
00305     vtheta_last_ = vel_theta_actual;
00306 
00307     // for x-axis
00308     double x_vel_diff = fabs(vel_x_desired - vel_x_actual);
00309     if( x_vel_diff >= epsilon )
00310     {
00311 //        double alpha = x_vel_diff * VELOCITY_COEFF;
00312         if (vel_x_desired >= 0.0 && ax <= 0.0)
00313         {
00314             x_pos_marker_.header.stamp = ros::Time::now();
00315             interpolateColor(x_vel_diff, x_pos_marker_.color);
00316 //            x_pos_marker_.color.a = (alpha > 1.0) ? 1.0 : alpha;
00317                 marker_pub_.publish(x_pos_marker_);            
00318         }
00319         else if (vel_x_desired <= 0.0 && ax >= 0.0)
00320         {
00321             x_neg_marker_.header.stamp = ros::Time::now();
00322             interpolateColor(x_vel_diff, x_neg_marker_.color);
00323 //            x_neg_marker_.color.a = (alpha > 1.0) ? 1.0 : alpha;
00324             marker_pub_.publish(x_neg_marker_);
00325         }
00326     }
00327 
00328     // for y-axis
00329     double y_vel_diff = fabs(vel_y_desired - vel_y_actual);
00330     if( y_vel_diff >= epsilon )
00331     {
00332 //        double alpha = y_vel_diff * VELOCITY_COEFF;
00333         if (vel_y_desired >= 0.0 && ay <= 0.0)
00334         {
00335             y_pos_marker_.header.stamp = ros::Time::now();
00336             interpolateColor(y_vel_diff, y_pos_marker_.color);
00337 //            y_pos_marker_.color.a = (alpha > 1.0) ? 1.0 : alpha;
00338                 marker_pub_.publish(y_pos_marker_);            
00339         }
00340         else if (vel_y_desired <= 0.0 && ay >= 0.0)
00341         {
00342             y_neg_marker_.header.stamp = ros::Time::now();
00343             interpolateColor(y_vel_diff, y_neg_marker_.color);
00344 //            y_neg_marker_.color.a = (alpha > 1.0) ? 1.0 : alpha;
00345             marker_pub_.publish(y_neg_marker_);
00346         }
00347     }
00348 
00349     // for theta-axis
00350     double theta_vel_diff = fabs(vel_theta_desired - vel_theta_actual);
00351     if( theta_vel_diff >= epsilon )
00352     {
00353 //        double alpha = theta_vel_diff * VELOCITY_COEFF;
00354         if (vel_theta_desired >= 0.0  && atheta <= 0.0)
00355         {
00356             theta_pos_marker_.header.stamp = ros::Time::now();
00357             interpolateColor(theta_vel_diff, theta_pos_marker_.color);
00358 //            theta_pos_marker_.color.a = (alpha > 1.0) ? 1.0 : alpha;
00359                 marker_pub_.publish(theta_pos_marker_);            
00360         }
00361         else if (vel_theta_desired <= 0.0  && atheta >= 0.0)
00362         {
00363             theta_neg_marker_.header.stamp = ros::Time::now();
00364             interpolateColor(theta_vel_diff, theta_neg_marker_.color);
00365 //            theta_neg_marker_.color.a = (alpha > 1.0) ? 1.0 : alpha;
00366             marker_pub_.publish(theta_neg_marker_);
00367         }
00368     }
00369 }
00370 
00371 
00372 }
00373 


cob_collision_velocity_filter
Author(s): Matthias Gruhler, Michal Spanel (spanel@fit.vutbr.cz, vel. limited marker)
autogenerated on Tue Mar 3 2015 15:11:57