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 #include <voxel_grid_model.h>
00038
00039 using namespace std;
00040 using namespace costmap_2d;
00041
00042 namespace iri_ackermann_local_planner {
00043 VoxelGridModel::VoxelGridModel(double size_x, double size_y, double size_z, double xy_resolution, double z_resolution,
00044 double origin_x, double origin_y, double origin_z, double max_z, double obstacle_range) :
00045 obstacle_grid_(size_x, size_y, size_z), xy_resolution_(xy_resolution), z_resolution_(z_resolution),
00046 origin_x_(origin_x), origin_y_(origin_y), origin_z_(origin_z),
00047 max_z_(max_z), sq_obstacle_range_(obstacle_range * obstacle_range) {}
00048
00049 double VoxelGridModel::footprintCost(const geometry_msgs::Point& position, const vector<geometry_msgs::Point>& footprint,
00050 double inscribed_radius, double circumscribed_radius){
00051 if(footprint.size() < 3)
00052 return -1.0;
00053
00054
00055 unsigned int x0, x1, y0, y1;
00056 double line_cost = 0.0;
00057
00058
00059 for(unsigned int i = 0; i < footprint.size() - 1; ++i){
00060
00061 if(!worldToMap2D(footprint[i].x, footprint[i].y, x0, y0))
00062 return -1.0;
00063
00064
00065 if(!worldToMap2D(footprint[i + 1].x, footprint[i + 1].y, x1, y1))
00066 return -1.0;
00067
00068 line_cost = lineCost(x0, x1, y0, y1);
00069
00070
00071 if(line_cost < 0)
00072 return -1.0;
00073 }
00074
00075
00076
00077 if(!worldToMap2D(footprint.back().x, footprint.back().y, x0, y0))
00078 return -1.0;
00079
00080
00081 if(!worldToMap2D(footprint.front().x, footprint.front().y, x1, y1))
00082 return -1.0;
00083
00084 line_cost = lineCost(x0, x1, y0, y1);
00085
00086 if(line_cost < 0)
00087 return -1.0;
00088
00089
00090 return 0.0;
00091 }
00092
00093
00094 double VoxelGridModel::lineCost(int x0, int x1,
00095 int y0, int y1){
00096
00097 int deltax = abs(x1 - x0);
00098 int deltay = abs(y1 - y0);
00099 int x = x0;
00100 int y = y0;
00101
00102 int xinc1, xinc2, yinc1, yinc2;
00103 int den, num, numadd, numpixels;
00104
00105 double line_cost = 0.0;
00106 double point_cost = -1.0;
00107
00108 if (x1 >= x0)
00109 {
00110 xinc1 = 1;
00111 xinc2 = 1;
00112 }
00113 else
00114 {
00115 xinc1 = -1;
00116 xinc2 = -1;
00117 }
00118
00119 if (y1 >= y0)
00120 {
00121 yinc1 = 1;
00122 yinc2 = 1;
00123 }
00124 else
00125 {
00126 yinc1 = -1;
00127 yinc2 = -1;
00128 }
00129
00130 if (deltax >= deltay)
00131 {
00132 xinc1 = 0;
00133 yinc2 = 0;
00134 den = deltax;
00135 num = deltax / 2;
00136 numadd = deltay;
00137 numpixels = deltax;
00138 }
00139 else
00140 {
00141 xinc2 = 0;
00142 yinc1 = 0;
00143 den = deltay;
00144 num = deltay / 2;
00145 numadd = deltax;
00146 numpixels = deltay;
00147 }
00148
00149 for (int curpixel = 0; curpixel <= numpixels; curpixel++)
00150 {
00151 point_cost = pointCost(x, y);
00152
00153 if(point_cost < 0)
00154 return -1;
00155
00156 if(line_cost < point_cost)
00157 line_cost = point_cost;
00158
00159 num += numadd;
00160 if (num >= den)
00161 {
00162 num -= den;
00163 x += xinc1;
00164 y += yinc1;
00165 }
00166 x += xinc2;
00167 y += yinc2;
00168 }
00169
00170 return line_cost;
00171 }
00172
00173 double VoxelGridModel::pointCost(int x, int y){
00174
00175 if(obstacle_grid_.getVoxelColumn(x, y)){
00176 return -1;
00177 }
00178
00179 return 1;
00180 }
00181
00182 void VoxelGridModel::updateWorld(const vector<geometry_msgs::Point>& footprint,
00183 const vector<Observation>& observations, const vector<PlanarLaserScan>& laser_scans){
00184
00185
00186 for(unsigned int i = 0; i < laser_scans.size(); ++i)
00187 removePointsInScanBoundry(laser_scans[i], 10.0);
00188
00189
00190 for(vector<Observation>::const_iterator it = observations.begin(); it != observations.end(); ++it){
00191 const Observation& obs = *it;
00192 const pcl::PointCloud<pcl::PointXYZ>& cloud = obs.cloud_;
00193 for(unsigned int i = 0; i < cloud.points.size(); ++i){
00194
00195 if(cloud.points[i].z > max_z_)
00196 continue;
00197
00198
00199 double sq_dist = (cloud.points[i].x - obs.origin_.x) * (cloud.points[i].x - obs.origin_.x)
00200 + (cloud.points[i].y - obs.origin_.y) * (cloud.points[i].y - obs.origin_.y)
00201 + (cloud.points[i].z - obs.origin_.z) * (cloud.points[i].z - obs.origin_.z);
00202
00203 if(sq_dist >= sq_obstacle_range_)
00204 continue;
00205
00206
00207 insert(cloud.points[i]);
00208 }
00209 }
00210
00211
00212
00213 }
00214
00215 void VoxelGridModel::removePointsInScanBoundry(const PlanarLaserScan& laser_scan, double raytrace_range){
00216 if(laser_scan.cloud.points.size() == 0)
00217 return;
00218
00219 unsigned int sensor_x, sensor_y, sensor_z;
00220 double ox = laser_scan.origin.x;
00221 double oy = laser_scan.origin.y;
00222 double oz = laser_scan.origin.z;
00223
00224 if(!worldToMap3D(ox, oy, oz, sensor_x, sensor_y, sensor_z))
00225 return;
00226
00227 for(unsigned int i = 0; i < laser_scan.cloud.points.size(); ++i){
00228 double wpx = laser_scan.cloud.points[i].x;
00229 double wpy = laser_scan.cloud.points[i].y;
00230 double wpz = laser_scan.cloud.points[i].z;
00231
00232 double distance = dist(ox, oy, oz, wpx, wpy, wpz);
00233 double scaling_fact = raytrace_range / distance;
00234 scaling_fact = scaling_fact > 1.0 ? 1.0 : scaling_fact;
00235 wpx = scaling_fact * (wpx - ox) + ox;
00236 wpy = scaling_fact * (wpy - oy) + oy;
00237 wpz = scaling_fact * (wpz - oz) + oz;
00238
00239
00240 if(wpz >= max_z_){
00241
00242 double a = wpx - ox;
00243 double b = wpy - oy;
00244 double c = wpz - oz;
00245 double t = (max_z_ - .01 - oz) / c;
00246 wpx = ox + a * t;
00247 wpy = oy + b * t;
00248 wpz = oz + c * t;
00249 }
00250
00251 else if(wpz < 0.0){
00252
00253 double a = wpx - ox;
00254 double b = wpy - oy;
00255 double c = wpz - oz;
00256 double t = (0.0 - oz) / c;
00257 wpx = ox + a * t;
00258 wpy = oy + b * t;
00259 wpz = oz + c * t;
00260 }
00261
00262 unsigned int point_x, point_y, point_z;
00263 if(worldToMap3D(wpx, wpy, wpz, point_x, point_y, point_z)){
00264 obstacle_grid_.clearVoxelLine(sensor_x, sensor_y, sensor_z, point_x, point_y, point_z);
00265 }
00266 }
00267 }
00268
00269 void VoxelGridModel::getPoints(pcl::PointCloud<pcl::PointXYZ>& cloud){
00270 for(unsigned int i = 0; i < obstacle_grid_.sizeX(); ++i){
00271 for(unsigned int j = 0; j < obstacle_grid_.sizeY(); ++j){
00272 for(unsigned int k = 0; k < obstacle_grid_.sizeZ(); ++k){
00273 if(obstacle_grid_.getVoxel(i, j, k)){
00274 double wx, wy, wz;
00275 mapToWorld3D(i, j, k, wx, wy, wz);
00276 pcl::PointXYZ pt;
00277 pt.x = wx;
00278 pt.y = wy;
00279 pt.z = wz;
00280 cloud.points.push_back(pt);
00281 }
00282 }
00283 }
00284 }
00285 }
00286
00287 };