00001 #include <range_sensor_layer/range_sensor_layer.h>
00002 #include <boost/algorithm/string.hpp>
00003 #include <pluginlib/class_list_macros.h>
00004 #include <angles/angles.h>
00005
00006 PLUGINLIB_EXPORT_CLASS(range_sensor_layer::RangeSensorLayer, costmap_2d::Layer)
00007
00008 using costmap_2d::NO_INFORMATION;
00009
00010 namespace range_sensor_layer
00011 {
00012
00013 RangeSensorLayer::RangeSensorLayer() {}
00014
00015 void RangeSensorLayer::onInitialize()
00016 {
00017 ros::NodeHandle nh("~/" + name_);
00018 current_ = true;
00019 buffered_readings_ = 0;
00020 last_reading_time_ = ros::Time::now();
00021 default_value_ = to_cost(0.5);
00022
00023 matchSize();
00024 min_x_ = min_y_ = -std::numeric_limits<double>::max();
00025 max_x_ = max_y_ = std::numeric_limits<double>::max();
00026
00027
00028
00029 const char* xml = "<value><array><data><value>/sonar</value></data></array></value>";
00030 int zero_offset = 0;
00031 std::string topics_ns;
00032 XmlRpc::XmlRpcValue topic_names(xml, &zero_offset);
00033
00034 nh.param("ns", topics_ns, std::string());
00035 nh.param("topics", topic_names, topic_names);
00036
00037 InputSensorType input_sensor_type = ALL;
00038 std::string sensor_type_name;
00039 nh.param("input_sensor_type", sensor_type_name, std::string("ALL"));
00040
00041 boost::to_upper(sensor_type_name);
00042 ROS_INFO("%s: %s as input_sensor_type given", name_.c_str(), sensor_type_name.c_str());
00043
00044 if (sensor_type_name == "VARIABLE")
00045 input_sensor_type = VARIABLE;
00046 else if (sensor_type_name == "FIXED")
00047 input_sensor_type = FIXED;
00048 else if (sensor_type_name == "ALL")
00049 input_sensor_type = ALL;
00050 else
00051 {
00052 ROS_ERROR("%s: Invalid input sensor type: %s", name_.c_str(), sensor_type_name.c_str());
00053 }
00054
00055
00056 if ((topic_names.valid() == false) || (topic_names.getType() != XmlRpc::XmlRpcValue::TypeArray))
00057 {
00058 ROS_ERROR("Invalid topic names list: it must be a non-empty list of strings");
00059 return;
00060 }
00061
00062 if (topic_names.size() < 1)
00063 {
00064
00065 ROS_WARN("Empty topic names list: range sensor layer will have no effect on costmap");
00066 }
00067
00068
00069 for (unsigned int i = 0; i < topic_names.size(); i++)
00070 {
00071 if (topic_names[i].getType() != XmlRpc::XmlRpcValue::TypeString)
00072 {
00073 ROS_WARN("Invalid topic names list: element %d is not a string, so it will be ignored", i);
00074 }
00075 else
00076 {
00077 std::string topic_name(topics_ns);
00078 if ((topic_name.size() > 0) && (topic_name.at(topic_name.size() - 1) != '/'))
00079 topic_name += "/";
00080 topic_name += static_cast<std::string>(topic_names[i]);
00081
00082 if (input_sensor_type == VARIABLE)
00083 processRangeMessageFunc_ = boost::bind(&RangeSensorLayer::processVariableRangeMsg, this, _1);
00084 else if (input_sensor_type == FIXED)
00085 processRangeMessageFunc_ = boost::bind(&RangeSensorLayer::processFixedRangeMsg, this, _1);
00086 else if (input_sensor_type == ALL)
00087 processRangeMessageFunc_ = boost::bind(&RangeSensorLayer::processRangeMsg, this, _1);
00088 else
00089 {
00090 ROS_ERROR(
00091 "%s: Invalid input sensor type: %s. Did you make a new type and forgot to choose the subscriber for it?",
00092 name_.c_str(), sensor_type_name.c_str());
00093 }
00094
00095 range_subs_.push_back(nh.subscribe(topic_name, 100, &RangeSensorLayer::bufferIncomingRangeMsg, this));
00096
00097 ROS_INFO("RangeSensorLayer: subscribed to topic %s", range_subs_.back().getTopic().c_str());
00098 }
00099 }
00100
00101 dsrv_ = new dynamic_reconfigure::Server<range_sensor_layer::RangeSensorLayerConfig>(nh);
00102 dynamic_reconfigure::Server<range_sensor_layer::RangeSensorLayerConfig>::CallbackType cb =
00103 boost::bind(&RangeSensorLayer::reconfigureCB, this, _1, _2);
00104 dsrv_->setCallback(cb);
00105 global_frame_ = layered_costmap_->getGlobalFrameID();
00106 }
00107
00108
00109 double RangeSensorLayer::gamma(double theta)
00110 {
00111 if (fabs(theta) > max_angle_)
00112 return 0.0;
00113 else
00114 return 1 - pow(theta / max_angle_, 2);
00115 }
00116
00117 double RangeSensorLayer::delta(double phi)
00118 {
00119 return 1 - (1 + tanh(2 * (phi - phi_v_))) / 2;
00120 }
00121
00122 void RangeSensorLayer::get_deltas(double angle, double *dx, double *dy)
00123 {
00124 double ta = tan(angle);
00125 if (ta == 0)
00126 *dx = 0;
00127 else
00128 *dx = resolution_ / ta;
00129
00130 *dx = copysign(*dx, cos(angle));
00131 *dy = copysign(resolution_, sin(angle));
00132 }
00133
00134 double RangeSensorLayer::sensor_model(double r, double phi, double theta)
00135 {
00136 double lbda = delta(phi)*gamma(theta);
00137
00138 double delta = resolution_;
00139
00140 if(phi >= 0.0 and phi < r - 2 * delta * r)
00141 return (1- lbda) * (0.5);
00142 else if(phi < r - delta * r)
00143 return lbda* 0.5 * pow((phi - (r - 2*delta*r))/(delta*r), 2)+(1-lbda)*.5;
00144 else if(phi < r + delta * r){
00145 double J = (r-phi)/(delta*r);
00146 return lbda * ((1-(0.5)*pow(J,2)) -0.5) + 0.5;
00147 }
00148 else
00149 return 0.5;
00150 }
00151
00152
00153 void RangeSensorLayer::reconfigureCB(range_sensor_layer::RangeSensorLayerConfig &config, uint32_t level)
00154 {
00155 phi_v_ = config.phi;
00156 inflate_cone_ = config.inflate_cone;
00157 no_readings_timeout_ = config.no_readings_timeout;
00158 clear_threshold_ = config.clear_threshold;
00159 mark_threshold_ = config.mark_threshold;
00160 clear_on_max_reading_ = config.clear_on_max_reading;
00161
00162 if(enabled_ != config.enabled)
00163 {
00164 enabled_ = config.enabled;
00165 current_ = false;
00166 }
00167 }
00168
00169 void RangeSensorLayer::bufferIncomingRangeMsg(const sensor_msgs::RangeConstPtr& range_message)
00170 {
00171 boost::mutex::scoped_lock lock(range_message_mutex_);
00172 range_msgs_buffer_.push_back(*range_message);
00173 }
00174
00175 void RangeSensorLayer::updateCostmap()
00176 {
00177 std::list<sensor_msgs::Range> range_msgs_buffer_copy;
00178
00179 range_message_mutex_.lock();
00180 range_msgs_buffer_copy = std::list<sensor_msgs::Range>(range_msgs_buffer_);
00181 range_msgs_buffer_.clear();
00182 range_message_mutex_.unlock();
00183
00184 for (std::list<sensor_msgs::Range>::iterator range_msgs_it = range_msgs_buffer_copy.begin();
00185 range_msgs_it != range_msgs_buffer_copy.end(); range_msgs_it++)
00186 {
00187 processRangeMessageFunc_(*range_msgs_it);
00188 }
00189 }
00190
00191 void RangeSensorLayer::processRangeMsg(sensor_msgs::Range& range_message)
00192 {
00193 if (range_message.min_range == range_message.max_range)
00194 processFixedRangeMsg(range_message);
00195 else
00196 processVariableRangeMsg(range_message);
00197 }
00198
00199 void RangeSensorLayer::processFixedRangeMsg(sensor_msgs::Range& range_message)
00200 {
00201 if (!isinf(range_message.range))
00202 {
00203 ROS_ERROR_THROTTLE(1.0,
00204 "Fixed distance ranger (min_range == max_range) in frame %s sent invalid value. Only -Inf (== object detected) and Inf (== no object detected) are valid.",
00205 range_message.header.frame_id.c_str());
00206 return;
00207 }
00208
00209 bool clear_sensor_cone = false;
00210
00211 if (range_message.range > 0)
00212 {
00213 if (!clear_on_max_reading_)
00214 return;
00215
00216 clear_sensor_cone = true;
00217 }
00218
00219 range_message.range = range_message.min_range;
00220
00221 updateCostmap(range_message, clear_sensor_cone);
00222 }
00223
00224 void RangeSensorLayer::processVariableRangeMsg(sensor_msgs::Range& range_message)
00225 {
00226 if (range_message.range < range_message.min_range || range_message.range > range_message.max_range)
00227 return;
00228
00229 bool clear_sensor_cone = false;
00230
00231 if (range_message.range == range_message.max_range && clear_on_max_reading_)
00232 clear_sensor_cone = true;
00233
00234 updateCostmap(range_message, clear_sensor_cone);
00235 }
00236
00237 void RangeSensorLayer::updateCostmap(sensor_msgs::Range& range_message, bool clear_sensor_cone)
00238 {
00239 max_angle_ = range_message.field_of_view/2;
00240
00241 geometry_msgs::PointStamped in, out;
00242 in.header.stamp = range_message.header.stamp;
00243 in.header.frame_id = range_message.header.frame_id;
00244
00245 if(!tf_->waitForTransform(global_frame_, in.header.frame_id, in.header.stamp, ros::Duration(0.1)) )
00246 {
00247 ROS_ERROR_THROTTLE(1.0, "Range sensor layer can't transform from %s to %s at %f",
00248 global_frame_.c_str(), in.header.frame_id.c_str(),
00249 in.header.stamp.toSec());
00250 return;
00251 }
00252
00253 tf_->transformPoint (global_frame_, in, out);
00254
00255 double ox = out.point.x, oy = out.point.y;
00256
00257 in.point.x = range_message.range;
00258
00259 tf_->transformPoint(global_frame_, in, out);
00260
00261 double tx = out.point.x, ty = out.point.y;
00262
00263
00264 double dx = tx-ox, dy = ty-oy, theta = atan2(dy,dx), d = sqrt(dx*dx+dy*dy);
00265
00266
00267 int bx0, by0, bx1, by1;
00268
00269
00270
00271 int Ox, Oy, Ax, Ay, Bx, By;
00272
00273
00274 worldToMapNoBounds(ox, oy, Ox, Oy);
00275 bx1 = bx0 = Ox;
00276 by1 = by0 = Oy;
00277 touch(ox, oy, &min_x_, &min_y_, &max_x_, &max_y_);
00278
00279
00280 unsigned int aa, ab;
00281 if(worldToMap(tx, ty, aa, ab)){
00282 setCost(aa, ab, 233);
00283 touch(tx, ty, &min_x_, &min_y_, &max_x_, &max_y_);
00284 }
00285
00286 double mx, my;
00287
00288
00289 mx = ox + cos(theta-max_angle_) * d * 1.2;
00290 my = oy + sin(theta-max_angle_) * d * 1.2;
00291 worldToMapNoBounds(mx, my, Ax, Ay);
00292 bx0 = std::min(bx0, Ax);
00293 bx1 = std::max(bx1, Ax);
00294 by0 = std::min(by0, Ay);
00295 by1 = std::max(by1, Ay);
00296 touch(mx, my, &min_x_, &min_y_, &max_x_, &max_y_);
00297
00298
00299 mx = ox + cos(theta+max_angle_) * d * 1.2;
00300 my = oy + sin(theta+max_angle_) * d * 1.2;
00301
00302 worldToMapNoBounds(mx, my, Bx, By);
00303 bx0 = std::min(bx0, Bx);
00304 bx1 = std::max(bx1, Bx);
00305 by0 = std::min(by0, By);
00306 by1 = std::max(by1, By);
00307 touch(mx, my, &min_x_, &min_y_, &max_x_, &max_y_);
00308
00309
00310 bx0 = std::max(0, bx0);
00311 by0 = std::max(0, by0);
00312 bx1 = std::min((int)size_x_, bx1);
00313 by1 = std::min((int)size_y_, by1);
00314
00315 for(unsigned int x=bx0; x<=(unsigned int)bx1; x++){
00316 for(unsigned int y=by0; y<=(unsigned int)by1; y++){
00317 bool update_xy_cell = true;
00318
00319
00320
00321
00322
00323 if (inflate_cone_ < 1.0){
00324
00325 int w0 = orient2d(Ax, Ay, Bx, By, x, y);
00326 int w1 = orient2d(Bx, By, Ox, Oy, x, y);
00327 int w2 = orient2d(Ox, Oy, Ax, Ay, x, y);
00328
00329
00330 float bcciath = -inflate_cone_*area(Ax, Ay, Bx, By, Ox, Oy);
00331 update_xy_cell = w0 >= bcciath && w1 >= bcciath && w2 >= bcciath;
00332 }
00333
00334 if (update_xy_cell){
00335 double wx, wy;
00336 mapToWorld(x,y,wx,wy);
00337 update_cell(ox, oy, theta, range_message.range, wx, wy, clear_sensor_cone);
00338 }
00339 }
00340 }
00341
00342 buffered_readings_++;
00343 last_reading_time_ = ros::Time::now();
00344 }
00345
00346 void RangeSensorLayer::update_cell(double ox, double oy, double ot, double r, double nx, double ny, bool clear)
00347 {
00348 unsigned int x, y;
00349 if(worldToMap(nx, ny, x, y)){
00350 double dx = nx-ox, dy = ny-oy;
00351 double theta = atan2(dy, dx) - ot;
00352 theta = angles::normalize_angle(theta);
00353 double phi = sqrt(dx*dx+dy*dy);
00354 double sensor = 0.0;
00355 if(!clear)
00356 sensor = sensor_model(r,phi,theta);
00357 double prior = to_prob(getCost(x,y));
00358 double prob_occ = sensor * prior;
00359 double prob_not = (1 - sensor) * (1 - prior);
00360 double new_prob = prob_occ/(prob_occ+prob_not);
00361
00362
00363
00364 unsigned char c = to_cost(new_prob);
00365 setCost(x,y,c);
00366 }
00367 }
00368
00369 void RangeSensorLayer::updateBounds(double robot_x, double robot_y, double robot_yaw,
00370 double* min_x, double* min_y, double* max_x, double* max_y)
00371 {
00372 if (layered_costmap_->isRolling())
00373 updateOrigin(robot_x - getSizeInMetersX() / 2, robot_y - getSizeInMetersY() / 2);
00374
00375 updateCostmap();
00376
00377 *min_x = std::min(*min_x, min_x_);
00378 *min_y = std::min(*min_y, min_y_);
00379 *max_x = std::max(*max_x, max_x_);
00380 *max_y = std::max(*max_y, max_y_);
00381
00382 min_x_ = min_y_ = std::numeric_limits<double>::max();
00383 max_x_ = max_y_ = std::numeric_limits<double>::min();
00384
00385 if (!enabled_)
00386 {
00387 current_ = true;
00388 return;
00389 }
00390
00391 if (buffered_readings_ == 0)
00392 {
00393 if (no_readings_timeout_ > 0.0 &&
00394 (ros::Time::now() - last_reading_time_).toSec() > no_readings_timeout_)
00395 {
00396 ROS_WARN_THROTTLE(2.0, "No range readings received for %.2f seconds, " \
00397 "while expected at least every %.2f seconds.",
00398 (ros::Time::now() - last_reading_time_).toSec(), no_readings_timeout_);
00399 current_ = false;
00400 }
00401 }
00402
00403 }
00404
00405 void RangeSensorLayer::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
00406 {
00407 if (!enabled_)
00408 return;
00409
00410 unsigned char* master_array = master_grid.getCharMap();
00411 unsigned int span = master_grid.getSizeInCellsX();
00412 unsigned char clear = to_cost(clear_threshold_), mark = to_cost(mark_threshold_);
00413
00414 for (int j = min_j; j < max_j; j++)
00415 {
00416 unsigned int it = j * span + min_i;
00417 for (int i = min_i; i < max_i; i++)
00418 {
00419 unsigned char prob = costmap_[it];
00420 unsigned char current;
00421 if(prob==costmap_2d::NO_INFORMATION){
00422 it++;
00423 continue;
00424 }
00425 else if(prob>mark)
00426 current = costmap_2d::LETHAL_OBSTACLE;
00427 else if(prob<clear)
00428 current = costmap_2d::FREE_SPACE;
00429 else{
00430 it++;
00431 continue;
00432 }
00433
00434 unsigned char old_cost = master_array[it];
00435
00436 if (old_cost == NO_INFORMATION || old_cost < current)
00437 master_array[it] = current;
00438 it++;
00439 }
00440 }
00441
00442 buffered_readings_ = 0;
00443 current_ = true;
00444 }
00445
00446 void RangeSensorLayer::reset()
00447 {
00448 ROS_DEBUG("Reseting range sensor layer...");
00449 deactivate();
00450 resetMaps();
00451 current_ = true;
00452 activate();
00453 }
00454
00455 void RangeSensorLayer::deactivate()
00456 {
00457 range_msgs_buffer_.clear();
00458 }
00459
00460 void RangeSensorLayer::activate()
00461 {
00462 range_msgs_buffer_.clear();
00463 }
00464
00465 }