$search
00001 /* 00002 * Copyright (c) 2008, Willow Garage, Inc. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of the Willow Garage, Inc. nor the names of its 00014 * contributors may be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 * 00029 */ 00030 00039 #include "shortest_path_result.h" 00040 #include <occupancy_grid_utils/coordinate_conversions.h> 00041 #include <occupancy_grid_utils/ray_tracer.h> 00042 #include <occupancy_grid_utils/file.h> 00043 #include <occupancy_grid_utils/geometry.h> 00044 #include <occupancy_grid_utils/shortest_path.h> 00045 #include <boost/python.hpp> 00046 #include <boost/python/suite/indexing/vector_indexing_suite.hpp> 00047 00048 // Macro for boost python's convoluted syntax for exposing vector<T> to python 00049 #define BOOST_PYTHON_VECTOR(t, name) boost::python::class_<std::vector<t> >(name) \ 00050 .def(boost::python::vector_indexing_suite<std::vector<t> >()) 00051 00052 // Macro due to boost python requiring operator== for any T for which you want vector<T> 00053 #define DEFINE_DUMMY_EQUALITY(ns, t) namespace ns { \ 00054 bool operator== (const t& x1, const t& x2) { return false; } \ 00055 } // namespace 00056 00057 DEFINE_DUMMY_EQUALITY(geometry_msgs, Point32) 00058 00059 namespace occupancy_grid_utils 00060 { 00061 00062 namespace nm=nav_msgs; 00063 namespace gm=geometry_msgs; 00064 namespace sm=sensor_msgs; 00065 using std::string; 00066 using std::vector; 00067 using std::set; 00068 00069 // STL exports 00070 void exportSTL () 00071 { 00072 using namespace boost::python; 00073 BOOST_PYTHON_VECTOR(int8_t, "Int8Vec"); 00074 } 00075 00076 // Ros message exports 00077 // Should eventually be done via standard genmsg mechanisms 00078 void exportRosMessages() 00079 { 00080 using namespace boost::python; 00081 class_<std_msgs::Header>("Header") 00082 .def_readwrite("stamp", &std_msgs::Header::stamp) 00083 .def_readwrite("frame_id", &std_msgs::Header::frame_id); 00084 00085 class_<ros::Time>("Time") 00086 .def_readwrite("sec", &ros::Time::sec) 00087 .def_readwrite("nsec", &ros::Time::nsec); 00088 00089 class_<gm::Point>("Point") 00090 .def_readwrite("x", &gm::Point::x) 00091 .def_readwrite("y", &gm::Point::y) 00092 .def_readwrite("z", &gm::Point::z); 00093 00094 class_<gm::Point32>("Point32") 00095 .def_readwrite("x", &gm::Point32::x) 00096 .def_readwrite("y", &gm::Point32::y) 00097 .def_readwrite("z", &gm::Point32::z); 00098 00099 class_<gm::Quaternion>("Quaternion") 00100 .def_readwrite("x", &gm::Quaternion::x) 00101 .def_readwrite("y", &gm::Quaternion::y) 00102 .def_readwrite("z", &gm::Quaternion::z) 00103 .def_readwrite("w", &gm::Quaternion::w); 00104 00105 class_<gm::Pose>("Pose") 00106 .def_readwrite("position", &gm::Pose::position) 00107 .def_readwrite("orientation", &gm::Pose::orientation); 00108 00109 class_<nm::MapMetaData>("MapMetaData") 00110 .def_readwrite("resolution", &nm::MapMetaData::resolution) 00111 .def_readwrite("width", &nm::MapMetaData::width) 00112 .def_readwrite("height", &nm::MapMetaData::height) 00113 .def_readwrite("origin", &nm::MapMetaData::origin); 00114 00115 BOOST_PYTHON_VECTOR(gm::Point32, "Point32Vec"); 00116 00117 class_<gm::Polygon>("Polygon") 00118 .def_readwrite("points", &gm::Polygon::points); 00119 00120 class_<nm::OccupancyGrid, nm::OccupancyGrid::Ptr>("OccupancyGrid") 00121 .def_readwrite("header", &nm::OccupancyGrid::header) 00122 .def_readwrite("info", &nm::OccupancyGrid::info) 00123 .def_readwrite("data", &nm::OccupancyGrid::data); 00124 } 00125 00126 /************************************************************ 00127 * Helpers 00128 ************************************************************/ 00129 00130 void allocateGrid (nav_msgs::OccupancyGrid& grid) 00131 { 00132 grid.data.resize(grid.info.height*grid.info.width); 00133 } 00134 00135 void setCell (nav_msgs::OccupancyGrid& grid, const Cell& c, const int x) 00136 { 00137 grid.data[cellIndex(grid.info, c)] = x; 00138 } 00139 00140 int getCell (const nav_msgs::OccupancyGrid& grid, const Cell& c) 00141 { 00142 return grid.data[cellIndex(grid.info, c)]; 00143 } 00144 00145 nm::OccupancyGrid::Ptr loadGrid1 (const string& fname) 00146 { 00147 return loadGrid(fname, 1.0, identityPose()); 00148 } 00149 00150 nm::OccupancyGrid::Ptr loadGrid2 (const string& fname, const double resolution) 00151 { 00152 return loadGrid(fname, resolution, identityPose()); 00153 } 00154 00155 nm::OccupancyGrid::Ptr loadGrid3 (const string& fname, const double res, 00156 const gm::Pose& p) 00157 { 00158 return loadGrid(fname, res, p); 00159 } 00160 00161 sm::LaserScan::Ptr 00162 simulateRangeScan3 (const nm::OccupancyGrid& grid, const gm::Pose& sensor_pose, 00163 const sm::LaserScan& scanner_info) 00164 { 00165 return simulateRangeScan(grid, sensor_pose, scanner_info); 00166 } 00167 00168 sm::LaserScan::Ptr 00169 simulateRangeScan4 (const nm::OccupancyGrid& grid, const gm::Pose& sensor_pose, 00170 const sm::LaserScan& scanner_info, const bool unknown_obstacles) 00171 { 00172 return simulateRangeScan(grid, sensor_pose, scanner_info, unknown_obstacles); 00173 } 00174 00175 bool 00176 withinBoundsCell (const nm::MapMetaData& info, const Cell& c) 00177 { 00178 return withinBounds(info, c); 00179 } 00180 00181 bool 00182 withinBoundsPoint (const nm::MapMetaData& info, const gm::Point& p) 00183 { 00184 return withinBounds(info, p); 00185 } 00186 00187 ResultPtr sssp1 (const nav_msgs::OccupancyGrid& g, const Cell& start, 00188 const double max_dist) 00189 { 00190 TerminationCondition term(max_dist); 00191 return singleSourceShortestPaths(g, start, term, false); 00192 } 00193 00194 double ssspDistance (ResultPtr res, const Cell& dest) 00195 { 00196 boost::optional<double> dist = distanceTo(res, dest); 00197 if (dist) 00198 return *dist; 00199 else 00200 return -1; 00201 } 00202 00203 // Wrap the library function with one that returns a vector, so we 00204 // can export to python 00205 vector<Cell> cellVectorInConvexPolygon (const nm::MapMetaData& info, 00206 const gm::Polygon& p) 00207 { 00208 set<Cell> cells = cellsInConvexPolygon(info, p); 00209 vector<Cell> cell_vec(cells.begin(), cells.end()); 00210 return cell_vec; 00211 } 00212 00213 BOOST_PYTHON_MODULE(occupancy_grid_utils) 00214 { 00215 using namespace boost::python; 00216 00217 exportSTL(); 00218 exportRosMessages(); 00219 00220 /**************************************** 00221 * Constants 00222 ****************************************/ 00223 00224 scope().attr("OCCUPIED") = OCCUPIED; 00225 scope().attr("UNOCCUPIED") = UNOCCUPIED; 00226 00227 /**************************************** 00228 * Types 00229 ****************************************/ 00230 00231 class_<Cell>("Cell", init<>()) 00232 .def(init<int, int>()) 00233 .def_readwrite("x", &Cell::x) 00234 .def_readwrite("y", &Cell::y) 00235 ; 00236 00237 BOOST_PYTHON_VECTOR(Cell, "CellVec"); 00238 00239 class_<ShortestPathResult, ResultPtr > 00240 ("ShortestPathResult") 00241 ; 00242 00243 /**************************************** 00244 * Operations 00245 ****************************************/ 00246 00247 def("cell_index", cellIndex); 00248 def("index_cell", indexCell); 00249 def("point_cell", pointCell); 00250 def("cell_center", cellCenter); 00251 def("point_index", pointIndex); 00252 def("within_bounds", withinBoundsCell); 00253 def("within_bounds", withinBoundsPoint); 00254 def("get_cell", getCell); 00255 def("set_cell", &setCell); 00256 def("allocate_grid", &allocateGrid); 00257 def("simulate_range_scan", &simulateRangeScan3); 00258 def("simulate_range_scan", &simulateRangeScan4); 00259 def("load_grid", loadGrid3); 00260 def("load_grid", loadGrid1); 00261 def("load_grid", loadGrid2); 00262 def("inflate_obstacles", inflateObstacles); 00263 def("nav_fn", sssp1); 00264 def("sssp_distance_internal", ssspDistance); 00265 def("cells_in_convex_polygon", cellVectorInConvexPolygon); 00266 } 00267 00268 00269 00270 00271 } // namespace