00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
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
00066 const double MARKER_WIDTH_ROT = 0.15;
00067
00068
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
00080 nh_ = ros::NodeHandle("~");
00081
00082
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
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
00097 createDirectionalMarkers();
00098 createRotationalMarkers();
00099 }
00100
00101
00102 VelocityLimitedMarker::~VelocityLimitedMarker()
00103 {
00104 }
00105
00106
00107 void VelocityLimitedMarker::createDirectionalMarkers()
00108 {
00109
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;
00132
00133
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
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
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;
00214
00215
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
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
00296 double epsilon = 0.05;
00297
00298
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
00308 double x_vel_diff = fabs(vel_x_desired - vel_x_actual);
00309 if( x_vel_diff >= epsilon )
00310 {
00311
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
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
00324 marker_pub_.publish(x_neg_marker_);
00325 }
00326 }
00327
00328
00329 double y_vel_diff = fabs(vel_y_desired - vel_y_actual);
00330 if( y_vel_diff >= epsilon )
00331 {
00332
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
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
00345 marker_pub_.publish(y_neg_marker_);
00346 }
00347 }
00348
00349
00350 double theta_vel_diff = fabs(vel_theta_desired - vel_theta_actual);
00351 if( theta_vel_diff >= epsilon )
00352 {
00353
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
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
00366 marker_pub_.publish(theta_neg_marker_);
00367 }
00368 }
00369 }
00370
00371
00372 }
00373