Description
I use ROS kinetic in order to be able to drive my differential drive robot and I also use range_sensor_layer package (Branch Indigo V0.4.0) in order to be able to use SRF sensors. Recently I noticed that range_sensor_layer, in function RangeSensorLayer::updateCosts() in lines 434-437, updates master grid cells for clearing, only if old_cost is NO_INFORMATION (if current=FREE_SPACE=0 then old_cost can never be smaller than current, because old_cost is an unsighned char and cannot be negative)
void RangeSensorLayer::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
{
if (!enabled_)
return;
unsigned char* master_array = master_grid.getCharMap();
unsigned int span = master_grid.getSizeInCellsX();
unsigned char clear = to_cost(clear_threshold_), mark = to_cost(mark_threshold_);
for (int j = min_j; j < max_j; j++)
{
unsigned int it = j * span + min_i;
for (int i = min_i; i < max_i; i++)
{
unsigned char prob = costmap_[it];
unsigned char current;
if(prob==costmap_2d::NO_INFORMATION){
it++;
continue;
}
else if(prob>mark)
current = costmap_2d::LETHAL_OBSTACLE;
else if(prob<clear)
current = costmap_2d::FREE_SPACE;
else{
it++;
continue;
}
unsigned char old_cost = master_array[it];
if (old_cost == NO_INFORMATION || old_cost < current)
master_array[it] = current;
it++;
}
}
buffered_readings_ = 0;
current_ = true;
}
But what happened if master grid old_cost is not NO_INFORMATION(255) and current=FREE_SPACE (0)?? Is that not possible?? Because if it’s possible, we ignore completely this case and that may cause errors. In this case maybe a possible solution is something like this (but it is not tested):
void RangeSensorLayer::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
{
if (!enabled_)
return;
unsigned char* master_array = master_grid.getCharMap();
unsigned int span = master_grid.getSizeInCellsX();
unsigned char clear = to_cost(clear_threshold_), mark = to_cost(mark_threshold_);
for (int j = min_j; j < max_j; j++)
{
unsigned int it = j * span + min_i;
for (int i = min_i; i < max_i; i++)
{
unsigned char prob = costmap_[it];
unsigned char old_cost = master_array[it];
unsigned char current;
if(prob==costmap_2d::NO_INFORMATION){
it++;
continue;
}
else if(prob>mark){
current = costmap_2d::LETHAL_OBSTACLE;
if (old_cost == NO_INFORMATION || old_cost < current){
master_array[it] = current;
}
it++;
}
else if(prob<clear){
current = costmap_2d::FREE_SPACE;
if (old_cost > current){
master_array[it] = current;
}
it++;
}
else{
it++;
continue;
}
}
}
buffered_readings_ = 0;
current_ = true;
}
In addition, I want to highlight another two points of range_sensor_layer source code.
First, in function RangeSensorLayer::processVariableRangeMsg() in line 231, it is critical programming to compare if two float values are equal.
if (range_message.range == range_message.max_range && clear_on_max_reading_)
clear_sensor_cone = true;
A better way to do that (considering float A and float B) is:
if ( fabs( A - B ) < limit_value )
where limit_value indicates the desired decimal position, in which we want if-statement to compare A and B equality .
And second, I want to ask if it is possible to define a parameter, in order to be able to configure how long we want to wait for transform in line 245 (now is used a fix value of 0.1(100msec))
if(!tf_->waitForTransform(global_frame_, in.header.frame_id, in.header.stamp, ros::Duration(0.1)) )
{
ROS_ERROR_THROTTLE(1.0, "Range sensor layer can't transform from %s to %s at %f",
global_frame_.c_str(), in.header.frame_id.c_str(),
in.header.stamp.toSec());
return;
}
Thanks in advance