├── rviz_plugins ├── Makefile ├── lib │ └── librviz_plugins.so ├── src │ ├── goal_tool.h │ ├── pose_tool.h │ ├── goal_tool.cpp │ ├── multi_probmap_display.h │ ├── probmap_display.h │ ├── aerialmap_display.h │ ├── pose_tool.cpp │ ├── multi_probmap_display.cpp │ ├── aerialmap_display.cpp │ └── probmap_display.cpp ├── package.xml ├── plugin_description.xml └── CMakeLists.txt ├── waypoint_generator ├── package.xml ├── CMakeLists.txt └── src │ ├── sample_waypoints.h │ └── waypoint_generator.cpp ├── README.md ├── grid_path_searcher ├── package.xml ├── include │ ├── node.h │ ├── JPS_searcher.h │ ├── JPS_utils.h │ └── Astar_searcher.h ├── CMakeLists.txt ├── launch │ ├── demo.launch │ └── rviz_config │ │ └── demo.rviz └── src │ ├── random_complex_generator.cpp │ ├── demo_node.cpp │ ├── JPS_searcher.cpp │ ├── Astar_searcher.cpp │ └── JPS_utils.cpp └── LICENSE /rviz_plugins/Makefile: -------------------------------------------------------------------------------- 1 | include $(shell rospack find mk)/cmake.mk -------------------------------------------------------------------------------- /rviz_plugins/lib/librviz_plugins.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Grizi-ju/Astar_JPS_Pathplanning_in_ROS/HEAD/rviz_plugins/lib/librviz_plugins.so -------------------------------------------------------------------------------- /waypoint_generator/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 0.0.0 3 | waypoint_generator 4 | 5 | 6 | waypoint_generator 7 | 8 | 9 | Shaojie Shen 10 | BSD 11 | http://ros.org/wiki/waypoint_generator 12 | 13 | catkin 14 | 15 | roscpp 16 | tf 17 | nav_msgs 18 | 19 | roscpp 20 | tf 21 | nav_msgs 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Astar_JPS_Pathplanning_in_ROS 2 | 智能车航天物流线上赛--在ROS中实现A星三维路径规划 3 | 4 | **使用:** 5 | 6 | 点个Star 谢谢~ 7 | 8 | Ubuntu18.04 9 | melodic 10 | 11 | `````` 12 | 1.git clone git@github.com:Grizi-ju/Astar_JPS_Pathplanning_in_ROS.git 13 | 14 | 2.cd catkin_ws 15 | 16 | 3.catkin_make 17 | 18 | 4.source devel/setup.bash 19 | 20 | 5.roslaunch grid_path_searcher demo.launch 21 | `````` 22 | 23 | 24 | 实际还有很多改进的地方,时间原因暂时是这样,后续会继续提交 25 | 26 | **结果:** 27 | 28 | ![image](https://user-images.githubusercontent.com/80267952/162573084-6a798240-ffc8-4776-87f5-a922429c6637.png) 29 | 30 | 31 | Reference: 32 | 33 | https://blog.csdn.net/weixin_48628189/article/details/119545751?spm=1001.2014.3001.5502 34 | 35 | https://github.com/Mesywang/Astar-JPS-Algorithm 36 | 37 | https://mesywang.github.io/2020/01/26/Jump-Point-Search/ 38 | 39 | 《Improving Jump Point Search》 40 | -------------------------------------------------------------------------------- /grid_path_searcher/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | grid_path_searcher 4 | 0.0.1 5 | Path searching methods on 3d grid map 6 | fgaoaa 7 | BSD 8 | 9 | catkin 10 | 11 | roscpp 12 | rospy 13 | sensor_msgs 14 | std_msgs 15 | visualization_msgs 16 | 17 | roscpp 18 | rospy 19 | sensor_msgs 20 | std_msgs 21 | visualization_msgs 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /rviz_plugins/src/goal_tool.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef RVIZ_GOAL_TOOL_H 3 | #define RVIZ_GOAL_TOOL_H 4 | 5 | #ifndef Q_MOC_RUN // See: https://bugreports.qt-project.org/browse/QTBUG-22829 6 | # include 7 | 8 | # include 9 | 10 | # include "pose_tool.h" 11 | #endif 12 | 13 | namespace rviz 14 | { 15 | class Arrow; 16 | class DisplayContext; 17 | class StringProperty; 18 | 19 | class Goal3DTool: public Pose3DTool 20 | { 21 | Q_OBJECT 22 | public: 23 | Goal3DTool(); 24 | virtual ~Goal3DTool() {} 25 | virtual void onInitialize(); 26 | 27 | protected: 28 | virtual void onPoseSet(double x, double y, double z, double theta); 29 | 30 | private Q_SLOTS: 31 | void updateTopic(); 32 | 33 | private: 34 | ros::NodeHandle nh_; 35 | ros::Publisher pub_; 36 | 37 | StringProperty* topic_property_; 38 | }; 39 | 40 | } 41 | 42 | #endif 43 | 44 | 45 | -------------------------------------------------------------------------------- /rviz_plugins/src/pose_tool.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef RVIZ_POSE_TOOL_H 3 | #define RVIZ_POSE_TOOL_H 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "rviz/tool.h" 12 | 13 | namespace rviz 14 | { 15 | class Arrow; 16 | class DisplayContext; 17 | 18 | class Pose3DTool: public Tool 19 | { 20 | public: 21 | Pose3DTool(); 22 | virtual ~Pose3DTool(); 23 | 24 | virtual void onInitialize(); 25 | 26 | virtual void activate(); 27 | virtual void deactivate(); 28 | 29 | virtual int processMouseEvent( ViewportMouseEvent& event ); 30 | 31 | protected: 32 | virtual void onPoseSet(double x, double y, double z, double theta) = 0; 33 | 34 | Arrow* arrow_; 35 | std::vector arrow_array; 36 | 37 | enum State 38 | { 39 | Position, 40 | Orientation, 41 | Height 42 | }; 43 | State state_; 44 | 45 | Ogre::Vector3 pos_; 46 | }; 47 | 48 | } 49 | 50 | #endif 51 | 52 | 53 | -------------------------------------------------------------------------------- /grid_path_searcher/include/node.h: -------------------------------------------------------------------------------- 1 | #ifndef _NODE_H_ 2 | #define _NODE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "backward.hpp" 9 | 10 | #define inf 1>>20 11 | struct GridNode; 12 | 13 | typedef GridNode* GridNodePtr; 14 | 15 | 16 | struct GridNode 17 | { 18 | int id; 19 | 20 | Eigen::Vector3d coord; 21 | 22 | Eigen::Vector3i dir; 23 | 24 | Eigen::Vector3i index; 25 | 26 | double gScore, fScore; 27 | 28 | GridNodePtr cameFrom; 29 | std::multimap::iterator nodeMapIt; 30 | 31 | GridNode(Eigen::Vector3i _index, Eigen::Vector3d _coord){ 32 | id = 0; 33 | index = _index; 34 | coord = _coord; 35 | dir = Eigen::Vector3i::Zero(); 36 | 37 | gScore = inf; 38 | fScore = inf; 39 | 40 | cameFrom = NULL; 41 | } 42 | 43 | GridNode(){}; 44 | ~GridNode(){}; 45 | }; 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /rviz_plugins/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 0.0.0 3 | rviz_plugins 4 | 5 | 6 | Additional plugins for RViz 7 | 8 | 9 | Shaojie Shen 10 | BSD 11 | http://ros.org/wiki/rviz_plugins 12 | 13 | catkin 14 | 15 | rviz 16 | roscpp 17 | 18 | qtbase5-dev 19 | 20 | rviz 21 | 22 | roscpp 23 | libqt5-core 24 | libqt5-gui 25 | libqt5-widgets 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /rviz_plugins/plugin_description.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Tool for setting 3D goal 7 | 8 | 9 | 12 | 13 | Display of -inf +inf probabilistic occupancy grid map 14 | 15 | 16 | 19 | 20 | Display of aerial map 21 | 22 | 23 | 26 | 27 | Display of multiple -inf +inf probabilistic occupancy grid map 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /grid_path_searcher/include/JPS_searcher.h: -------------------------------------------------------------------------------- 1 | #ifndef _JPS_SEARCHER_H_ 2 | #define _JPS_SEARCHER_H_ 3 | 4 | #include "Astar_searcher.h" 5 | #include "JPS_utils.h" 6 | 7 | class JPSPathFinder : public AstarPathFinder 8 | { 9 | private: 10 | bool isOccupied(const int &idx_x, const int &idx_y, const int &idx_z) const; 11 | bool isOccupied(const Eigen::Vector3i &index) const; 12 | bool isFree(const int &idx_x, const int &idx_y, const int &idx_z) const; 13 | bool isFree(const Eigen::Vector3i &index) const; 14 | 15 | public: 16 | JPS3DNeib *jn3d; 17 | 18 | JPSPathFinder() 19 | { 20 | jn3d = new JPS3DNeib(); 21 | }; 22 | 23 | ~JPSPathFinder() 24 | { 25 | delete jn3d; 26 | }; 27 | void JPSGetSucc(GridNodePtr currentPtr, std::vector &neighborPtrSets, std::vector &edgeCostSets); 28 | bool hasForced(const Eigen::Vector3i &idx, const Eigen::Vector3i &dir); 29 | bool jump(const Eigen::Vector3i &curIdx, const Eigen::Vector3i &expDir, Eigen::Vector3i &neiIdx); 30 | 31 | void JPSGraphSearch(Eigen::Vector3d start_pt, Eigen::Vector3d end_pt); 32 | }; 33 | 34 | #endif -------------------------------------------------------------------------------- /waypoint_generator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(waypoint_generator) 3 | 4 | set(CMAKE_VERBOSE_MAKEFILE "true") 5 | include(CheckCXXCompilerFlag) 6 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) 7 | CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) 8 | if(COMPILER_SUPPORTS_CXX11) 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 10 | elseif(COMPILER_SUPPORTS_CXX0X) 11 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 12 | else() 13 | message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") 14 | endif() 15 | 16 | set(ADDITIONAL_CXX_FLAG "-Wall -O3 -march=native") 17 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ADDITIONAL_CXX_FLAG}") 18 | 19 | find_package(catkin REQUIRED COMPONENTS 20 | roscpp 21 | tf 22 | nav_msgs 23 | ) 24 | catkin_package() 25 | 26 | include_directories(include) 27 | include_directories( 28 | ${catkin_INCLUDE_DIRS} 29 | ) 30 | 31 | add_executable(waypoint_generator src/waypoint_generator.cpp) 32 | 33 | target_link_libraries(waypoint_generator 34 | ${catkin_LIBRARIES} 35 | ) 36 | -------------------------------------------------------------------------------- /grid_path_searcher/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(grid_path_searcher) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | std_msgs 7 | nav_msgs 8 | visualization_msgs 9 | ) 10 | 11 | find_package(Eigen3 REQUIRED) 12 | find_package(PCL REQUIRED) 13 | 14 | set(Eigen3_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR}) 15 | 16 | catkin_package( 17 | INCLUDE_DIRS include 18 | ) 19 | 20 | include_directories( 21 | include 22 | SYSTEM 23 | third_party 24 | ${catkin_INCLUDE_DIRS} 25 | ${Eigen3_INCLUDE_DIRS} 26 | ${PCL_INCLUDE_DIRS} 27 | ) 28 | 29 | set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS} -O3 -Wall") # -Wextra -Werror 30 | 31 | add_executable( demo_node 32 | src/demo_node.cpp 33 | src/Astar_searcher.cpp 34 | src/JPS_utils.cpp 35 | src/JPS_searcher.cpp 36 | ) 37 | 38 | target_link_libraries(demo_node 39 | ${catkin_LIBRARIES} 40 | ${PCL_LIBRARIES} 41 | ) 42 | 43 | add_executable ( random_complex 44 | src/random_complex_generator.cpp ) 45 | 46 | target_link_libraries( random_complex 47 | ${catkin_LIBRARIES} 48 | ${PCL_LIBRARIES} ) 49 | -------------------------------------------------------------------------------- /grid_path_searcher/include/JPS_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _JPS_UTILS_H_ 2 | #define _JPS_UTILS_H_ 3 | 4 | #include 5 | ///Search and prune neighbors for JPS 3D 6 | struct JPS3DNeib 7 | { 8 | // for each (dx,dy,dz) these contain: 9 | // ns: neighbors that are always added 10 | // f1: forced neighbors to check 11 | // f2: neighbors to add if f1 is forced 12 | int ns[27][3][26]; 13 | int f1[27][3][12]; 14 | int f2[27][3][12]; 15 | // nsz contains the number of neighbors for the four different types of moves: 16 | // no move (norm 0): 26 neighbors always added 17 | // 0 forced neighbors to check (never happens) 18 | // 0 neighbors to add if forced (never happens) 19 | // straight (norm 1): 1 neighbor always added 20 | // 8 forced neighbors to check 21 | // 8 neighbors to add if forced 22 | // diagonal (norm sqrt(2)): 3 neighbors always added 23 | // 8 forced neighbors to check 24 | // 12 neighbors to add if forced 25 | // diagonal (norm sqrt(3)): 7 neighbors always added 26 | // 6 forced neighbors to check 27 | // 12 neighbors to add if forced 28 | static constexpr int nsz[4][2] = {{26, 0}, {1, 8}, {3, 12}, {7, 12}}; 29 | JPS3DNeib(); 30 | 31 | private: 32 | void Neib(int dx, int dy, int dz, int norm1, int dev, int &tx, int &ty, int &tz); 33 | void FNeib(int dx, int dy, int dz, int norm1, int dev, 34 | int &fx, int &fy, int &fz, 35 | int &nx, int &ny, int &nz); 36 | }; 37 | 38 | #endif -------------------------------------------------------------------------------- /rviz_plugins/src/goal_tool.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "rviz/display_context.h" 8 | #include "rviz/properties/string_property.h" 9 | 10 | #include "goal_tool.h" 11 | 12 | namespace rviz 13 | { 14 | 15 | Goal3DTool::Goal3DTool() 16 | { 17 | shortcut_key_ = 'g'; 18 | 19 | topic_property_ = new StringProperty( "Topic", "goal", 20 | "The topic on which to publish navigation goals.", 21 | getPropertyContainer(), SLOT( updateTopic() ), this ); 22 | } 23 | 24 | void Goal3DTool::onInitialize() 25 | { 26 | Pose3DTool::onInitialize(); 27 | setName( "3D Nav Goal" ); 28 | updateTopic(); 29 | } 30 | 31 | void Goal3DTool::updateTopic() 32 | { 33 | pub_ = nh_.advertise( topic_property_->getStdString(), 1 ); 34 | } 35 | 36 | void Goal3DTool::onPoseSet(double x, double y, double z, double theta) 37 | { 38 | ROS_WARN("3D Goal Set"); 39 | std::string fixed_frame = context_->getFixedFrame().toStdString(); 40 | tf::Quaternion quat; 41 | quat.setRPY(0.0, 0.0, theta); 42 | tf::Stamped p = tf::Stamped(tf::Pose(quat, tf::Point(x, y, z)), ros::Time::now(), fixed_frame); 43 | geometry_msgs::PoseStamped goal; 44 | tf::poseStampedTFToMsg(p, goal); 45 | ROS_INFO("Setting goal: Frame:%s, Position(%.3f, %.3f, %.3f), Orientation(%.3f, %.3f, %.3f, %.3f) = Angle: %.3f\n", fixed_frame.c_str(), 46 | goal.pose.position.x, goal.pose.position.y, goal.pose.position.z, 47 | goal.pose.orientation.x, goal.pose.orientation.y, goal.pose.orientation.z, goal.pose.orientation.w, theta); 48 | pub_.publish(goal); 49 | } 50 | 51 | } 52 | 53 | #include 54 | PLUGINLIB_EXPORT_CLASS( rviz::Goal3DTool, rviz::Tool ) 55 | -------------------------------------------------------------------------------- /rviz_plugins/src/multi_probmap_display.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MULTI_PROB_MAP_DISPLAY_H 3 | #define MULTI_PROB_MAP_DISPLAY_H 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include "rviz/display.h" 16 | 17 | namespace Ogre 18 | { 19 | class ManualObject; 20 | } 21 | 22 | namespace rviz 23 | { 24 | 25 | class FloatProperty; 26 | class IntProperty; 27 | class Property; 28 | class QuaternionProperty; 29 | class RosTopicProperty; 30 | class VectorProperty; 31 | 32 | class MultiProbMapDisplay: public Display 33 | { 34 | Q_OBJECT 35 | public: 36 | MultiProbMapDisplay(); 37 | virtual ~MultiProbMapDisplay(); 38 | 39 | virtual void onInitialize(); 40 | virtual void reset(); 41 | virtual void update( float wall_dt, float ros_dt ); 42 | 43 | protected Q_SLOTS: 44 | void updateTopic(); 45 | void updateDrawUnder(); 46 | 47 | 48 | protected: 49 | 50 | virtual void onEnable(); 51 | virtual void onDisable(); 52 | 53 | virtual void subscribe(); 54 | virtual void unsubscribe(); 55 | 56 | void incomingMap(const multi_map_server::MultiOccupancyGrid::ConstPtr& msg); 57 | 58 | void clear(); 59 | 60 | std::vector manual_object_; 61 | std::vector texture_; 62 | std::vector material_; 63 | 64 | bool loaded_; 65 | 66 | std::string topic_; 67 | 68 | ros::Subscriber map_sub_; 69 | 70 | RosTopicProperty* topic_property_; 71 | Property* draw_under_property_; 72 | 73 | multi_map_server::MultiOccupancyGrid::ConstPtr updated_map_; 74 | multi_map_server::MultiOccupancyGrid::ConstPtr current_map_; 75 | boost::mutex mutex_; 76 | bool new_map_; 77 | }; 78 | 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /grid_path_searcher/include/Astar_searcher.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASTART_SEARCHER_H 2 | #define _ASTART_SEARCHER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "backward.hpp" 9 | #include "node.h" 10 | 11 | class AstarPathFinder 12 | { 13 | private: 14 | 15 | protected: 16 | uint8_t * data; 17 | 18 | GridNodePtr *** GridNodeMap; 19 | 20 | Eigen::Vector3i goalIdx; 21 | 22 | int GLX_SIZE, GLY_SIZE, GLZ_SIZE; 23 | int GLXYZ_SIZE, GLYZ_SIZE; 24 | 25 | double resolution, inv_resolution; 26 | 27 | double gl_xl, gl_yl, gl_zl; 28 | double gl_xu, gl_yu, gl_zu; 29 | 30 | GridNodePtr terminatePtr; 31 | 32 | std::multimap openSet; 33 | 34 | double getHeu(GridNodePtr node1, GridNodePtr node2); 35 | double getHeu2(GridNodePtr node1, GridNodePtr node2); 36 | 37 | double calEuclideanDistance(GridNodePtr node1, GridNodePtr node2); 38 | 39 | void AstarGetSucc(GridNodePtr currentPtr, std::vector & neighborPtrSets, std::vector & edgeCostSets); 40 | 41 | bool isOccupied(const int & idx_x, const int & idx_y, const int & idx_z) const; 42 | bool isOccupied(const Eigen::Vector3i & index) const; 43 | 44 | bool isFree(const int & idx_x, const int & idx_y, const int & idx_z) const; 45 | bool isFree(const Eigen::Vector3i & index) const; 46 | 47 | Eigen::Vector3d gridIndex2coord(const Eigen::Vector3i & index); 48 | Eigen::Vector3i coord2gridIndex(const Eigen::Vector3d & pt); 49 | 50 | public: 51 | AstarPathFinder(){}; 52 | ~AstarPathFinder(){}; 53 | 54 | void AstarGraphSearch(Eigen::Vector3d start_pt, Eigen::Vector3d end_pt); 55 | 56 | void resetGrid(GridNodePtr ptr); 57 | 58 | void resetUsedGrids(); 59 | 60 | void initGridMap(double _resolution, Eigen::Vector3d global_xyz_l, Eigen::Vector3d global_xyz_u, int max_x_id, int max_y_id, int max_z_id); 61 | 62 | void setObs(const double coord_x, const double coord_y, const double coord_z); 63 | 64 | Eigen::Vector3d coordRounding(const Eigen::Vector3d & coord); 65 | 66 | std::vector getPath(); 67 | 68 | std::vector getVisitedNodes(); 69 | }; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /rviz_plugins/src/probmap_display.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef PROB_MAP_DISPLAY_H 3 | #define PROB_MAP_DISPLAY_H 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "rviz/display.h" 15 | 16 | namespace Ogre 17 | { 18 | class ManualObject; 19 | } 20 | 21 | namespace rviz 22 | { 23 | 24 | class FloatProperty; 25 | class IntProperty; 26 | class Property; 27 | class QuaternionProperty; 28 | class RosTopicProperty; 29 | class VectorProperty; 30 | 31 | class ProbMapDisplay: public Display 32 | { 33 | Q_OBJECT 34 | public: 35 | ProbMapDisplay(); 36 | virtual ~ProbMapDisplay(); 37 | 38 | virtual void onInitialize(); 39 | virtual void fixedFrameChanged(); 40 | virtual void reset(); 41 | virtual void update( float wall_dt, float ros_dt ); 42 | 43 | float getResolution() { return resolution_; } 44 | int getWidth() { return width_; } 45 | int getHeight() { return height_; } 46 | Ogre::Vector3 getPosition() { return position_; } 47 | Ogre::Quaternion getOrientation() { return orientation_; } 48 | 49 | protected Q_SLOTS: 50 | void updateAlpha(); 51 | void updateTopic(); 52 | void updateDrawUnder(); 53 | 54 | 55 | protected: 56 | 57 | virtual void onEnable(); 58 | virtual void onDisable(); 59 | 60 | virtual void subscribe(); 61 | virtual void unsubscribe(); 62 | 63 | void incomingMap(const nav_msgs::OccupancyGrid::ConstPtr& msg); 64 | 65 | void clear(); 66 | 67 | void transformMap(); 68 | 69 | Ogre::ManualObject* manual_object_; 70 | Ogre::TexturePtr texture_; 71 | Ogre::MaterialPtr material_; 72 | bool loaded_; 73 | 74 | std::string topic_; 75 | float resolution_; 76 | int width_; 77 | int height_; 78 | Ogre::Vector3 position_; 79 | Ogre::Quaternion orientation_; 80 | std::string frame_; 81 | 82 | ros::Subscriber map_sub_; 83 | 84 | RosTopicProperty* topic_property_; 85 | FloatProperty* resolution_property_; 86 | IntProperty* width_property_; 87 | IntProperty* height_property_; 88 | VectorProperty* position_property_; 89 | QuaternionProperty* orientation_property_; 90 | FloatProperty* alpha_property_; 91 | Property* draw_under_property_; 92 | 93 | nav_msgs::OccupancyGrid::ConstPtr updated_map_; 94 | nav_msgs::OccupancyGrid::ConstPtr current_map_; 95 | boost::mutex mutex_; 96 | bool new_map_; 97 | }; 98 | 99 | } 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /rviz_plugins/src/aerialmap_display.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef AERIAL_MAP_DISPLAY_H 3 | #define AERIAL_MAP_DISPLAY_H 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "rviz/display.h" 15 | 16 | namespace Ogre 17 | { 18 | class ManualObject; 19 | } 20 | 21 | namespace rviz 22 | { 23 | 24 | class FloatProperty; 25 | class IntProperty; 26 | class Property; 27 | class QuaternionProperty; 28 | class RosTopicProperty; 29 | class VectorProperty; 30 | 31 | class AerialMapDisplay: public Display 32 | { 33 | Q_OBJECT 34 | public: 35 | AerialMapDisplay(); 36 | virtual ~AerialMapDisplay(); 37 | 38 | virtual void onInitialize(); 39 | virtual void fixedFrameChanged(); 40 | virtual void reset(); 41 | virtual void update( float wall_dt, float ros_dt ); 42 | 43 | float getResolution() { return resolution_; } 44 | int getWidth() { return width_; } 45 | int getHeight() { return height_; } 46 | Ogre::Vector3 getPosition() { return position_; } 47 | Ogre::Quaternion getOrientation() { return orientation_; } 48 | 49 | protected Q_SLOTS: 50 | void updateAlpha(); 51 | void updateTopic(); 52 | void updateDrawUnder(); 53 | 54 | 55 | protected: 56 | 57 | virtual void onEnable(); 58 | virtual void onDisable(); 59 | 60 | virtual void subscribe(); 61 | virtual void unsubscribe(); 62 | 63 | void incomingAerialMap(const nav_msgs::OccupancyGrid::ConstPtr& msg); 64 | 65 | void clear(); 66 | 67 | void transformAerialMap(); 68 | 69 | Ogre::ManualObject* manual_object_; 70 | Ogre::TexturePtr texture_; 71 | Ogre::MaterialPtr material_; 72 | bool loaded_; 73 | 74 | std::string topic_; 75 | float resolution_; 76 | int width_; 77 | int height_; 78 | Ogre::Vector3 position_; 79 | Ogre::Quaternion orientation_; 80 | std::string frame_; 81 | 82 | ros::Subscriber map_sub_; 83 | 84 | RosTopicProperty* topic_property_; 85 | FloatProperty* resolution_property_; 86 | IntProperty* width_property_; 87 | IntProperty* height_property_; 88 | VectorProperty* position_property_; 89 | QuaternionProperty* orientation_property_; 90 | FloatProperty* alpha_property_; 91 | Property* draw_under_property_; 92 | 93 | nav_msgs::OccupancyGrid::ConstPtr updated_map_; 94 | nav_msgs::OccupancyGrid::ConstPtr current_map_; 95 | boost::mutex mutex_; 96 | bool new_map_; 97 | }; 98 | 99 | } 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /grid_path_searcher/launch/demo.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /rviz_plugins/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(rviz_plugins) 3 | 4 | ## Find catkin macros and libraries 5 | ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) 6 | ## is used, also find other catkin packages 7 | find_package(catkin REQUIRED COMPONENTS 8 | rviz 9 | #multi_map_server 10 | roscpp 11 | ) 12 | 13 | ################################### 14 | ## catkin specific configuration ## 15 | ################################### 16 | ## The catkin_package macro generates cmake config files for your package 17 | ## Declare things to be passed to dependent projects 18 | ## INCLUDE_DIRS: uncomment this if you package contains header files 19 | ## LIBRARIES: libraries you create in this project that dependent projects also need 20 | ## CATKIN_DEPENDS: catkin_packages dependent projects also need 21 | ## DEPENDS: system dependencies of this project that dependent projects also need 22 | catkin_package( 23 | # INCLUDE_DIRS include 24 | # LIBRARIES irobot_msgs 25 | CATKIN_DEPENDS #multi_map_server 26 | # DEPENDS system_lib 27 | ) 28 | 29 | ########### 30 | ## Build ## 31 | ########### 32 | 33 | #find_package(Armadillo REQUIRED) 34 | #include_directories(${ARMADILLO_INCLUDE_DIRS}) 35 | 36 | ## This plugin includes Qt widgets, so we must include Qt like so: 37 | #find_package(Qt5 COMPONENTS QtCore QtGui REQUIRED) 38 | 39 | if(rviz_QT_VERSION VERSION_LESS "5") 40 | message(STATUS "Using Qt4 based on the rviz_QT_VERSION: ${rviz_QT_VERSION}") 41 | find_package(Qt4 ${rviz_QT_VERSION} EXACT REQUIRED QtCore QtGui) 42 | ## pull in all required include dirs, define QT_LIBRARIES, etc. 43 | include(${QT_USE_FILE}) 44 | else() 45 | message(STATUS "Using Qt5 based on the rviz_QT_VERSION: ${rviz_QT_VERSION}") 46 | find_package(Qt5 ${rviz_QT_VERSION} EXACT REQUIRED Core Widgets) 47 | ## make target_link_libraries(${QT_LIBRARIES}) pull in all required dependencies 48 | set(QT_LIBRARIES Qt5::Widgets) 49 | endif() 50 | 51 | ## I prefer the Qt signals and slots to avoid defining "emit", "slots", 52 | ## etc because they can conflict with boost signals, so define QT_NO_KEYWORDS here. 53 | add_definitions(-DQT_NO_KEYWORDS) 54 | 55 | ## Here we specify which header files need to be run through "moc", 56 | ## Qt's meta-object compiler. 57 | qt5_wrap_cpp(MOC_FILES 58 | src/goal_tool.h 59 | # src/probmap_display.h 60 | # src/aerialmap_display.h 61 | # src/multi_probmap_display.h 62 | ) 63 | 64 | ## Here we specify the list of source files, including the output of 65 | ## the previous command which is stored in ``${MOC_FILES}``. 66 | set(SOURCE_FILES 67 | src/pose_tool.cpp 68 | src/goal_tool.cpp 69 | # src/probmap_display.cpp 70 | # src/aerialmap_display.cpp 71 | # src/multi_probmap_display.cpp 72 | ${MOC_FILES} 73 | ) 74 | 75 | 76 | ## Specify additional locations of header files 77 | ## Your package locations should be listed before other locations 78 | include_directories(include) 79 | include_directories( 80 | ${catkin_INCLUDE_DIRS} 81 | ) 82 | 83 | add_library(${PROJECT_NAME} ${SOURCE_FILES}) 84 | 85 | target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES}) 86 | 87 | install(TARGETS 88 | ${PROJECT_NAME} 89 | ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 90 | LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} 91 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 92 | ) 93 | 94 | install(FILES 95 | plugin_description.xml 96 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) 97 | 98 | install(DIRECTORY media/ 99 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/media) 100 | 101 | install(DIRECTORY icons/ 102 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/icons) 103 | -------------------------------------------------------------------------------- /rviz_plugins/src/pose_tool.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "rviz/geometry.h" 8 | #include "rviz/ogre_helpers/arrow.h" 9 | #include "rviz/viewport_mouse_event.h" 10 | #include "rviz/load_resource.h" 11 | #include "rviz/render_panel.h" 12 | 13 | #include "pose_tool.h" 14 | 15 | namespace rviz 16 | { 17 | 18 | Pose3DTool::Pose3DTool() 19 | : Tool() 20 | , arrow_( NULL ) 21 | { 22 | } 23 | 24 | Pose3DTool::~Pose3DTool() 25 | { 26 | delete arrow_; 27 | } 28 | 29 | void Pose3DTool::onInitialize() 30 | { 31 | arrow_ = new Arrow( scene_manager_, NULL, 2.0f, 0.2f, 0.5f, 0.35f ); 32 | arrow_->setColor( 0.0f, 1.0f, 0.0f, 1.0f ); 33 | arrow_->getSceneNode()->setVisible( false ); 34 | } 35 | 36 | void Pose3DTool::activate() 37 | { 38 | setStatus( "Click and drag mouse to set position/orientation." ); 39 | state_ = Position; 40 | } 41 | 42 | void Pose3DTool::deactivate() 43 | { 44 | arrow_->getSceneNode()->setVisible( false ); 45 | } 46 | 47 | int Pose3DTool::processMouseEvent( ViewportMouseEvent& event ) 48 | { 49 | int flags = 0; 50 | static Ogre::Vector3 ang_pos; 51 | static double initz; 52 | static double prevz; 53 | static double prevangle; 54 | const double z_scale = 50; 55 | const double z_interval = 0.5; 56 | Ogre::Quaternion orient_x = Ogre::Quaternion( Ogre::Radian(-Ogre::Math::HALF_PI), Ogre::Vector3::UNIT_Y ); 57 | 58 | if( event.leftDown() ) 59 | { 60 | ROS_ASSERT( state_ == Position ); 61 | Ogre::Vector3 intersection; 62 | Ogre::Plane ground_plane( Ogre::Vector3::UNIT_Z, 0.0f ); 63 | if( getPointOnPlaneFromWindowXY( event.viewport, 64 | ground_plane, 65 | event.x, event.y, intersection )) 66 | { 67 | pos_ = intersection; 68 | arrow_->setPosition( pos_ ); 69 | state_ = Orientation; 70 | flags |= Render; 71 | } 72 | } 73 | else if( event.type == QEvent::MouseMove && event.left() ) 74 | { 75 | if( state_ == Orientation ) 76 | { 77 | 78 | Ogre::Vector3 cur_pos; 79 | Ogre::Plane ground_plane( Ogre::Vector3::UNIT_Z, 0.0f ); 80 | if( getPointOnPlaneFromWindowXY( event.viewport, 81 | ground_plane, 82 | event.x, event.y, cur_pos )) 83 | { 84 | double angle = atan2( cur_pos.y - pos_.y, cur_pos.x - pos_.x ); 85 | arrow_->getSceneNode()->setVisible( true ); 86 | arrow_->setOrientation( Ogre::Quaternion( Ogre::Radian(angle), Ogre::Vector3::UNIT_Z ) * orient_x ); 87 | if ( event.right() ) 88 | state_ = Height; 89 | initz = pos_.z; 90 | prevz = event.y; 91 | prevangle = angle; 92 | flags |= Render; 93 | } 94 | } 95 | if ( state_ == Height ) 96 | { 97 | double z = event.y; 98 | double dz = z - prevz; 99 | prevz = z; 100 | pos_.z -= dz / z_scale; 101 | arrow_->setPosition( pos_ ); 102 | 103 | for (int k = 0; k < arrow_array.size(); k++) 104 | delete arrow_array[k]; 105 | arrow_array.clear(); 106 | int cnt = ceil( fabs(initz - pos_.z) / z_interval ); 107 | for (int k = 0; k < cnt; k++) 108 | { 109 | Arrow* arrow__; 110 | arrow__ = new Arrow( scene_manager_, NULL, 0.5f, 0.1f, 0.0f, 0.1f ); 111 | arrow__->setColor( 0.0f, 1.0f, 0.0f, 1.0f ); 112 | arrow__->getSceneNode()->setVisible( true ); 113 | Ogre::Vector3 arr_pos = pos_; 114 | arr_pos.z = initz - ( (initz - pos_.z > 0)?1:-1 ) * k * z_interval; 115 | arrow__->setPosition( arr_pos ); 116 | arrow__->setOrientation( Ogre::Quaternion( Ogre::Radian(prevangle), Ogre::Vector3::UNIT_Z ) * orient_x ); 117 | arrow_array.push_back(arrow__); 118 | } 119 | flags |= Render; 120 | } 121 | } 122 | else if( event.leftUp() ) 123 | { 124 | if( state_ == Orientation || state_ == Height) 125 | { 126 | 127 | for (int k = 0; k < arrow_array.size(); k++) 128 | delete arrow_array[k]; 129 | arrow_array.clear(); 130 | onPoseSet(pos_.x, pos_.y, pos_.z, prevangle); 131 | flags |= (Finished|Render); 132 | } 133 | } 134 | 135 | return flags; 136 | } 137 | 138 | } 139 | 140 | -------------------------------------------------------------------------------- /waypoint_generator/src/sample_waypoints.h: -------------------------------------------------------------------------------- 1 | #ifndef SAMPLE_WAYPOINTS_H 2 | #define SAMPLE_WAYPOINTS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | nav_msgs::Path point() 9 | { 10 | 11 | nav_msgs::Path waypoints; 12 | geometry_msgs::PoseStamped pt; 13 | pt.pose.orientation = tf::createQuaternionMsgFromYaw(0.0); 14 | 15 | double h = 1.0; 16 | double scale = 7.0; 17 | 18 | pt.pose.position.y = scale * 0.0; 19 | pt.pose.position.x = scale * 2.0; 20 | pt.pose.position.z = h; 21 | waypoints.poses.push_back(pt); 22 | 23 | pt.pose.position.y = scale * 0.0; 24 | pt.pose.position.x = scale * 4.0; 25 | pt.pose.position.z = h; 26 | waypoints.poses.push_back(pt); 27 | 28 | pt.pose.position.y = scale * 0.25; 29 | pt.pose.position.x = scale * 5.0; 30 | pt.pose.position.z = h; 31 | waypoints.poses.push_back(pt); 32 | 33 | pt.pose.position.y = scale * 0.5; 34 | pt.pose.position.x = scale * 5.3; 35 | pt.pose.position.z = h; 36 | waypoints.poses.push_back(pt); 37 | 38 | pt.pose.position.y = scale * 0.75; 39 | pt.pose.position.x = scale * 5.0; 40 | pt.pose.position.z = h; 41 | waypoints.poses.push_back(pt); 42 | 43 | pt.pose.position.y = scale * 1.0; 44 | pt.pose.position.x = scale * 4.0; 45 | pt.pose.position.z = h; 46 | waypoints.poses.push_back(pt); 47 | 48 | pt.pose.position.y = scale * 1.0; 49 | pt.pose.position.x = scale * 2.0; 50 | pt.pose.position.z = h; 51 | waypoints.poses.push_back(pt); 52 | 53 | pt.pose.position.y = scale * 1.0; 54 | pt.pose.position.x = scale * 0.0; 55 | pt.pose.position.z = h; 56 | waypoints.poses.push_back(pt); 57 | 58 | return waypoints; 59 | } 60 | 61 | 62 | nav_msgs::Path circle() 63 | { 64 | double h = 1.0; 65 | double scale = 5.0; 66 | nav_msgs::Path waypoints; 67 | geometry_msgs::PoseStamped pt; 68 | pt.pose.orientation = tf::createQuaternionMsgFromYaw(0.0); 69 | 70 | pt.pose.position.y = -1.2 * scale; 71 | pt.pose.position.x = 2.5 * scale; 72 | pt.pose.position.z = h; 73 | waypoints.poses.push_back(pt); 74 | 75 | pt.pose.position.y = -2.4 * scale; 76 | pt.pose.position.x = 5.0 * scale; 77 | pt.pose.position.z = h; 78 | waypoints.poses.push_back(pt); 79 | pt.pose.position.y = 0.0 * scale; 80 | pt.pose.position.x = 5.0 * scale; 81 | pt.pose.position.z = h; 82 | waypoints.poses.push_back(pt); 83 | 84 | pt.pose.position.y = -1.2 * scale; 85 | pt.pose.position.x = 2.5 * scale; 86 | pt.pose.position.z = h; 87 | waypoints.poses.push_back(pt); 88 | 89 | pt.pose.position.y = -2.4 * scale; 90 | pt.pose.position.x = 0. * scale; 91 | pt.pose.position.z = h; 92 | waypoints.poses.push_back(pt); 93 | pt.pose.position.y = 0.0 * scale; 94 | pt.pose.position.x = 0.0 * scale; 95 | pt.pose.position.z = h; 96 | waypoints.poses.push_back(pt); 97 | 98 | pt.pose.position.y = -1.2 * scale; 99 | pt.pose.position.x = 2.5 * scale; 100 | pt.pose.position.z = h; 101 | waypoints.poses.push_back(pt); 102 | 103 | pt.pose.position.y = -2.4 * scale; 104 | pt.pose.position.x = 5.0 * scale; 105 | pt.pose.position.z = h; 106 | waypoints.poses.push_back(pt); 107 | pt.pose.position.y = 0.0 * scale; 108 | pt.pose.position.x = 5.0 * scale; 109 | pt.pose.position.z = h; 110 | waypoints.poses.push_back(pt); 111 | 112 | pt.pose.position.y = -1.2 * scale; 113 | pt.pose.position.x = 2.5 * scale; 114 | pt.pose.position.z = h; 115 | waypoints.poses.push_back(pt); 116 | 117 | pt.pose.position.y = -2.4 * scale; 118 | pt.pose.position.x = 0. * scale; 119 | pt.pose.position.z = h; 120 | waypoints.poses.push_back(pt); 121 | pt.pose.position.y = 0.0 * scale; 122 | pt.pose.position.x = 0.0 * scale; 123 | pt.pose.position.z = h; 124 | waypoints.poses.push_back(pt); 125 | 126 | 127 | return waypoints; 128 | } 129 | 130 | 131 | nav_msgs::Path eight() 132 | { 133 | 134 | double offset_x = 0.0; 135 | double offset_y = 0.0; 136 | double r = 10.0; 137 | double h = 2.0; 138 | nav_msgs::Path waypoints; 139 | geometry_msgs::PoseStamped pt; 140 | pt.pose.orientation = tf::createQuaternionMsgFromYaw(0.0); 141 | 142 | for(int i=0; i< 1; ++i) 143 | { 144 | 145 | pt.pose.position.x = r + offset_x; 146 | pt.pose.position.y = -r + offset_y; 147 | pt.pose.position.z = h/2; 148 | waypoints.poses.push_back(pt); 149 | pt.pose.position.x = r*2 + offset_x * 2; 150 | pt.pose.position.y = 0 ; 151 | pt.pose.position.z = h; 152 | waypoints.poses.push_back(pt); 153 | pt.pose.position.x = r*3 + offset_x * 3; 154 | pt.pose.position.y = r ; 155 | pt.pose.position.z = h/2; 156 | waypoints.poses.push_back(pt); 157 | pt.pose.position.x = r*4 + offset_x * 4; 158 | pt.pose.position.y = 0 ; 159 | pt.pose.position.z = h; 160 | waypoints.poses.push_back(pt); 161 | pt.pose.position.x = r*3 + offset_x * 3; 162 | pt.pose.position.y = -r ; 163 | pt.pose.position.z = h/2; 164 | waypoints.poses.push_back(pt); 165 | pt.pose.position.x = r*2 + offset_x * 2; 166 | pt.pose.position.y = 0 ; 167 | pt.pose.position.z = h; 168 | waypoints.poses.push_back(pt); 169 | pt.pose.position.x = r + offset_x * 2; 170 | pt.pose.position.y = r ; 171 | pt.pose.position.z = h/2; 172 | waypoints.poses.push_back(pt); 173 | pt.pose.position.x = 0 + offset_x; 174 | pt.pose.position.y = 0; 175 | pt.pose.position.z = h; 176 | waypoints.poses.push_back(pt); 177 | 178 | pt.pose.position.x = r + offset_x; 179 | pt.pose.position.y = -r; 180 | pt.pose.position.z = h / 2 * 3; 181 | waypoints.poses.push_back(pt); 182 | pt.pose.position.x = r*2 + offset_x * 2; 183 | pt.pose.position.y = 0; 184 | pt.pose.position.z = h; 185 | waypoints.poses.push_back(pt); 186 | pt.pose.position.x = r*3 + offset_x * 3; 187 | pt.pose.position.y = r; 188 | pt.pose.position.z = h / 2 * 3; 189 | waypoints.poses.push_back(pt); 190 | pt.pose.position.x = r*4 + offset_x * 4; 191 | pt.pose.position.y = 0; 192 | pt.pose.position.z = h; 193 | waypoints.poses.push_back(pt); 194 | pt.pose.position.x = r*3 + offset_x * 3; 195 | pt.pose.position.y = -r; 196 | pt.pose.position.z = h / 2 * 3; 197 | waypoints.poses.push_back(pt); 198 | pt.pose.position.x = r*2 + offset_x * 2; 199 | pt.pose.position.y = 0; 200 | pt.pose.position.z = h; 201 | waypoints.poses.push_back(pt); 202 | pt.pose.position.x = r + offset_x; 203 | pt.pose.position.y = r + offset_y; 204 | pt.pose.position.z = h / 2 * 3; 205 | waypoints.poses.push_back(pt); 206 | pt.pose.position.x = 0; 207 | pt.pose.position.y = 0; 208 | pt.pose.position.z = h; 209 | waypoints.poses.push_back(pt); 210 | } 211 | return waypoints; 212 | } 213 | #endif 214 | -------------------------------------------------------------------------------- /grid_path_searcher/launch/rviz_config/demo.rviz: -------------------------------------------------------------------------------- 1 | Panels: 2 | - Class: rviz/Displays 3 | Help Height: 0 4 | Name: Displays 5 | Property Tree Widget: 6 | Expanded: 7 | - /AllMap1/Autocompute Value Bounds1 8 | - /visitedNodes1/Namespaces1 9 | - /gridPath1/Namespaces1 10 | Splitter Ratio: 0.609022558 11 | Tree Height: 566 12 | - Class: rviz/Selection 13 | Name: Selection 14 | - Class: rviz/Tool Properties 15 | Expanded: ~ 16 | Name: Tool Properties 17 | Splitter Ratio: 0.588679016 18 | - Class: rviz/Views 19 | Expanded: 20 | - /Current View1 21 | Name: Views 22 | Splitter Ratio: 0.5 23 | - Class: rviz/Time 24 | Experimental: false 25 | Name: Time 26 | SyncMode: 0 27 | SyncSource: AllMap 28 | Toolbars: 29 | toolButtonStyle: 2 30 | Visualization Manager: 31 | Class: "" 32 | Displays: 33 | - Alpha: 0.5 34 | Cell Size: 0.200000003 35 | Class: rviz/Grid 36 | Color: 0; 0; 0 37 | Enabled: true 38 | Line Style: 39 | Line Width: 0.0299999993 40 | Value: Lines 41 | Name: Grid 42 | Normal Cell Count: 0 43 | Offset: 44 | X: 0 45 | Y: 0 46 | Z: 0 47 | Plane: XY 48 | Plane Cell Count: 50 49 | Reference Frame: 50 | Value: true 51 | - Class: rviz/Axes 52 | Enabled: true 53 | Length: 2 54 | Name: Axes 55 | Radius: 0.0500000007 56 | Reference Frame: 57 | Value: true 58 | - Alpha: 1 59 | Autocompute Intensity Bounds: true 60 | Autocompute Value Bounds: 61 | Max Value: 1.89999998 62 | Min Value: 0.100000001 63 | Value: true 64 | Axis: Z 65 | Channel Name: intensity 66 | Class: rviz/PointCloud2 67 | Color: 193; 193; 193 68 | Color Transformer: AxisColor 69 | Decay Time: 0 70 | Enabled: true 71 | Invert Rainbow: false 72 | Max Color: 255; 255; 255 73 | Max Intensity: 4096 74 | Min Color: 0; 0; 0 75 | Min Intensity: 0 76 | Name: AllMap 77 | Position Transformer: XYZ 78 | Queue Size: 10 79 | Selectable: true 80 | Size (Pixels): 3 81 | Size (m): 0.200000003 82 | Style: Boxes 83 | Topic: /demo_node/grid_map_vis 84 | Unreliable: false 85 | Use Fixed Frame: true 86 | Use rainbow: true 87 | Value: true 88 | - Class: rviz/Marker 89 | Enabled: false 90 | Marker Topic: /demo_node/visited_nodes_vis 91 | Name: visitedNodes 92 | Namespaces: 93 | {} 94 | Queue Size: 100 95 | Value: false 96 | - Class: rviz/Marker 97 | Enabled: true 98 | Marker Topic: /demo_node/grid_path_vis 99 | Name: gridPath 100 | Namespaces: 101 | demo_node/jps_path: true 102 | Queue Size: 100 103 | Value: true 104 | Enabled: true 105 | Global Options: 106 | Background Color: 255; 255; 127 107 | Default Light: true 108 | Fixed Frame: world 109 | Frame Rate: 30 110 | Name: root 111 | Tools: 112 | - Class: rviz/Interact 113 | Hide Inactive Objects: true 114 | - Class: rviz/MoveCamera 115 | - Class: rviz/FocusCamera 116 | - Class: rviz_plugins/Goal3DTool 117 | Topic: goal 118 | Value: true 119 | Views: 120 | Current: 121 | Class: rviz/Orbit 122 | Distance: 9.74612236 123 | Enable Stereo Rendering: 124 | Stereo Eye Separation: 0.0599999987 125 | Stereo Focal Distance: 1 126 | Swap Stereo Eyes: false 127 | Value: false 128 | Focal Point: 129 | X: 2.19087362 130 | Y: 0.484706104 131 | Z: 0.618929148 132 | Focal Shape Fixed Size: true 133 | Focal Shape Size: 0.0500000007 134 | Invert Z Axis: false 135 | Name: Current View 136 | Near Clip Distance: 0.00999999978 137 | Pitch: 1.56979632 138 | Target Frame: 139 | Value: Orbit (rviz) 140 | Yaw: 3.77436399 141 | Saved: 142 | - Class: rviz/Orbit 143 | Distance: 79.2448425 144 | Enable Stereo Rendering: 145 | Stereo Eye Separation: 0.0599999987 146 | Stereo Focal Distance: 1 147 | Swap Stereo Eyes: false 148 | Value: false 149 | Focal Point: 150 | X: -13.6964359 151 | Y: -5.96537924 152 | Z: -19.0381603 153 | Focal Shape Fixed Size: true 154 | Focal Shape Size: 0.0500000007 155 | Invert Z Axis: false 156 | Name: Orbit 157 | Near Clip Distance: 0.00999999978 158 | Pitch: 1.1997968 159 | Target Frame: 160 | Value: Orbit (rviz) 161 | Yaw: 4.55750179 162 | - Angle: -0.00499992538 163 | Class: rviz/TopDownOrtho 164 | Enable Stereo Rendering: 165 | Stereo Eye Separation: 0.0599999987 166 | Stereo Focal Distance: 1 167 | Swap Stereo Eyes: false 168 | Value: false 169 | Invert Z Axis: false 170 | Name: TopDownOrtho 171 | Near Clip Distance: 0.00999999978 172 | Scale: 17.4224415 173 | Target Frame: 174 | Value: TopDownOrtho (rviz) 175 | X: -8.52147961 176 | Y: -7.69360256 177 | - Angle: 0.0150001263 178 | Class: rviz/TopDownOrtho 179 | Enable Stereo Rendering: 180 | Stereo Eye Separation: 0.0599999987 181 | Stereo Focal Distance: 1 182 | Swap Stereo Eyes: false 183 | Value: false 184 | Invert Z Axis: false 185 | Name: TopDownOrtho 186 | Near Clip Distance: 0.00999999978 187 | Scale: 134.654221 188 | Target Frame: 189 | Value: TopDownOrtho (rviz) 190 | X: -15.3867512 191 | Y: -4.14116335 192 | - Angle: -0.0249942318 193 | Class: rviz/TopDownOrtho 194 | Enable Stereo Rendering: 195 | Stereo Eye Separation: 0.0599999987 196 | Stereo Focal Distance: 1 197 | Swap Stereo Eyes: false 198 | Value: false 199 | Invert Z Axis: false 200 | Name: TopDownOrtho 201 | Near Clip Distance: 0.00999999978 202 | Scale: 10.9894609 203 | Target Frame: 204 | Value: TopDownOrtho (rviz) 205 | X: -15.1368361 206 | Y: -11.9202261 207 | Window Geometry: 208 | Displays: 209 | collapsed: false 210 | Height: 1028 211 | Hide Left Dock: false 212 | Hide Right Dock: false 213 | QMainWindow State: 000000ff00000000fd0000000400000000000001a2000003befc020000000bfb000000100044006900730070006c006100790073010000002800000277000000d700fffffffb0000000a0056006900650077007301000002a500000141000000ad00fffffffb0000001200530065006c0065006300740069006f006e00000000000000009b0000006100fffffffb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb0000001e0054006f006f006c002000500072006f007000650072007400690065007300000000e3000001c60000006100fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000a0049006d006100670065020000037e000000e30000016a00000089fb0000000a0049006d0061006700650200000593000001f50000016a000000ed000000010000010f000002c4fc0200000002fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000001200530065006c0065006300740069006f006e010000025a000000b20000000000000000000000020000073f000000ddfc0100000002fb0000000c00430061006d006500720061020000012e00000138000002d9000001a9fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000005730000003efc0100000002fb0000000800540069006d00650000000000000005730000030000fffffffb0000000800540069006d0065010000000000000450000000000000000000000597000003be00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 214 | Selection: 215 | collapsed: false 216 | Time: 217 | collapsed: false 218 | Tool Properties: 219 | collapsed: false 220 | Views: 221 | collapsed: false 222 | Width: 1855 223 | X: 142 224 | Y: 69 225 | -------------------------------------------------------------------------------- /grid_path_searcher/src/random_complex_generator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | using namespace Eigen; 22 | 23 | ros::Publisher _all_map_pub; 24 | 25 | int _obs_num, _cir_num; 26 | double _x_size, _y_size, _z_size, _init_x, _init_y, _resolution, _sense_rate; 27 | double _x_l, _x_h, _y_l, _y_h, _w_l, _w_h, _h_l, _h_h, _w_c_l, _w_c_h; 28 | 29 | bool _has_map = false; 30 | 31 | sensor_msgs::PointCloud2 globalMap_pcd; 32 | pcl::PointCloud cloudMap; 33 | 34 | pcl::search::KdTree kdtreeMap; 35 | vector pointIdxSearch; 36 | vector pointSquaredDistance; 37 | 38 | void RandomMapGenerate() 39 | { 40 | random_device rd; 41 | default_random_engine eng(rd()); 42 | 43 | uniform_real_distribution rand_x = uniform_real_distribution(_x_l, _x_h ); 44 | uniform_real_distribution rand_y = uniform_real_distribution(_y_l, _y_h ); 45 | uniform_real_distribution rand_w = uniform_real_distribution(_w_l, _w_h); 46 | uniform_real_distribution rand_h = uniform_real_distribution(_h_l, _h_h); 47 | 48 | uniform_real_distribution rand_x_circle = uniform_real_distribution(_x_l + 1.0, _x_h - 1.0); 49 | uniform_real_distribution rand_y_circle = uniform_real_distribution(_y_l + 1.0, _y_h - 1.0); 50 | uniform_real_distribution rand_r_circle = uniform_real_distribution(_w_c_l , _w_c_h ); 51 | 52 | uniform_real_distribution rand_roll = uniform_real_distribution(- M_PI, + M_PI); 53 | uniform_real_distribution rand_pitch = uniform_real_distribution(+ M_PI/4.0, + M_PI/2.0); 54 | uniform_real_distribution rand_yaw = uniform_real_distribution(+ M_PI/4.0, + M_PI/2.0); 55 | uniform_real_distribution rand_ellipse_c = uniform_real_distribution(0.5, 2.0); 56 | uniform_real_distribution rand_num = uniform_real_distribution(0.0, 1.0); 57 | 58 | pcl::PointXYZ pt_random; 59 | 60 | for(int i = 0; i < _cir_num; i ++) 61 | { 62 | double x0, y0, z0, R; 63 | std::vector circle_set; 64 | 65 | x0 = rand_x_circle(eng); 66 | y0 = rand_y_circle(eng); 67 | z0 = rand_h(eng) / 2.0; 68 | R = rand_r_circle(eng); 69 | 70 | if(sqrt( pow(x0-_init_x, 2) + pow(y0-_init_y, 2) ) < 2.0 ) 71 | continue; 72 | 73 | double a, b; 74 | a = rand_ellipse_c(eng); 75 | b = rand_ellipse_c(eng); 76 | 77 | double x, y, z; 78 | Vector3d pt3, pt3_rot; 79 | for(double theta = -M_PI; theta < M_PI; theta += 0.025) 80 | { 81 | x = a * cos(theta) * R; 82 | y = b * sin(theta) * R; 83 | z = 0; 84 | pt3 << x, y, z; 85 | circle_set.push_back(pt3); 86 | } 87 | 88 | Matrix3d Rot; 89 | double roll, pitch, yaw; 90 | double alpha, beta, gama; 91 | roll = rand_roll(eng); 92 | pitch = rand_pitch(eng); 93 | yaw = rand_yaw(eng); 94 | 95 | alpha = roll; 96 | beta = pitch; 97 | gama = yaw; 98 | 99 | double p = rand_num(eng); 100 | if(p < 0.5) 101 | { 102 | beta = M_PI / 2.0; 103 | gama = M_PI / 2.0; 104 | } 105 | 106 | Rot << cos(alpha) * cos(gama) - cos(beta) * sin(alpha) * sin(gama), - cos(beta) * cos(gama) * sin(alpha) - cos(alpha) * sin(gama), sin(alpha) * sin(beta), 107 | cos(gama) * sin(alpha) + cos(alpha) * cos(beta) * sin(gama), cos(alpha) * cos(beta) * cos(gama) - sin(alpha) * sin(gama), - cos(alpha) * sin(beta), 108 | sin(beta) * sin(gama), cos(gama) * sin(beta), cos(beta); 109 | 110 | for(auto pt: circle_set) 111 | { 112 | pt3_rot = Rot * pt; 113 | pt_random.x = pt3_rot(0) + x0 + 0.001; 114 | pt_random.y = pt3_rot(1) + y0 + 0.001; 115 | pt_random.z = pt3_rot(2) + z0 + 0.001; 116 | 117 | if(pt_random.z >= 0.0) 118 | cloudMap.points.push_back( pt_random ); 119 | } 120 | } 121 | 122 | bool is_kdtree_empty = false; 123 | if(cloudMap.points.size() > 0) 124 | kdtreeMap.setInputCloud( cloudMap.makeShared() ); 125 | else 126 | is_kdtree_empty = true; 127 | 128 | 129 | for(int i = 0; i < _obs_num; i ++) 130 | { 131 | double x, y, w, h; 132 | x = rand_x(eng); 133 | y = rand_y(eng); 134 | w = rand_w(eng); 135 | 136 | 137 | if(sqrt( pow(x - _init_x, 2) + pow(y - _init_y, 2) ) < 0.8 ) 138 | continue; 139 | 140 | pcl::PointXYZ searchPoint(x, y, (_h_l + _h_h)/2.0); 141 | pointIdxSearch.clear(); 142 | pointSquaredDistance.clear(); 143 | 144 | if(is_kdtree_empty == false) 145 | { 146 | if ( kdtreeMap.nearestKSearch (searchPoint, 1, pointIdxSearch, pointSquaredDistance) > 0 ) 147 | { 148 | if(sqrt(pointSquaredDistance[0]) < 1.0 ) 149 | continue; 150 | } 151 | } 152 | 153 | x = floor(x/_resolution) * _resolution + _resolution / 2.0; 154 | y = floor(y/_resolution) * _resolution + _resolution / 2.0; 155 | 156 | int widNum = ceil(w/_resolution); 157 | for(int r = -widNum/2.0; r < widNum/2.0; r ++ ) 158 | { 159 | for(int s = -widNum/2.0; s < widNum/2.0; s ++ ) 160 | { 161 | h = rand_h(eng); 162 | int heiNum = 2.0 * ceil(h/_resolution); 163 | for(int t = 0; t < heiNum; t ++ ){ 164 | pt_random.x = x + (r+0.0) * _resolution + 0.001; 165 | pt_random.y = y + (s+0.0) * _resolution + 0.001; 166 | pt_random.z = (t+0.0) * _resolution * 0.5 + 0.001; 167 | cloudMap.points.push_back( pt_random ); 168 | } 169 | } 170 | } 171 | } 172 | 173 | cloudMap.width = cloudMap.points.size(); 174 | cloudMap.height = 1; 175 | cloudMap.is_dense = true; 176 | 177 | _has_map = true; 178 | 179 | pcl::toROSMsg(cloudMap, globalMap_pcd); 180 | globalMap_pcd.header.frame_id = "world"; 181 | } 182 | 183 | void pubSensedPoints() 184 | { 185 | if( !_has_map ) return; 186 | 187 | _all_map_pub.publish(globalMap_pcd); 188 | } 189 | 190 | int main (int argc, char** argv) 191 | { 192 | ros::init (argc, argv, "random_complex_scene"); 193 | ros::NodeHandle n( "~" ); 194 | 195 | _all_map_pub = n.advertise("global_map", 1); 196 | 197 | n.param("init_state_x", _init_x, 0.0); 198 | n.param("init_state_y", _init_y, 0.0); 199 | 200 | n.param("map/x_size", _x_size, 50.0); 201 | n.param("map/y_size", _y_size, 50.0); 202 | n.param("map/z_size", _z_size, 5.0 ); 203 | 204 | n.param("map/obs_num", _obs_num, 30); 205 | n.param("map/circle_num", _cir_num, 30); 206 | n.param("map/resolution", _resolution, 0.2); 207 | 208 | n.param("ObstacleShape/lower_rad", _w_l, 0.3); 209 | n.param("ObstacleShape/upper_rad", _w_h, 0.8); 210 | n.param("ObstacleShape/lower_hei", _h_l, 3.0); 211 | n.param("ObstacleShape/upper_hei", _h_h, 7.0); 212 | 213 | n.param("CircleShape/lower_circle_rad", _w_c_l, 0.3); 214 | n.param("CircleShape/upper_circle_rad", _w_c_h, 0.8); 215 | 216 | n.param("sensing/rate", _sense_rate, 1.0); 217 | 218 | _x_l = - _x_size / 2.0; 219 | _x_h = + _x_size / 2.0; 220 | 221 | _y_l = - _y_size / 2.0; 222 | _y_h = + _y_size / 2.0; 223 | 224 | RandomMapGenerate(); 225 | ros::Rate loop_rate(_sense_rate); 226 | while (ros::ok()) 227 | { 228 | pubSensedPoints(); 229 | ros::spinOnce(); 230 | loop_rate.sleep(); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /grid_path_searcher/src/demo_node.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "Astar_searcher.h" 18 | #include "JPS_searcher.h" 19 | #include "backward.hpp" 20 | 21 | using namespace std; 22 | using namespace Eigen; 23 | 24 | #define _use_jps 1 //0 -> 只使用A*, 1 -> 使用JPS 25 | 26 | namespace backward { 27 | backward::SignalHandling sh; 28 | } 29 | 30 | 31 | double _resolution, _inv_resolution, _cloud_margin; 32 | 33 | double _x_size, _y_size, _z_size; 34 | 35 | bool _has_map = false; 36 | 37 | Vector3d _start_pt; 38 | 39 | Vector3d _map_lower, _map_upper; 40 | 41 | int _max_x_id, _max_y_id, _max_z_id; 42 | 43 | 44 | ros::Subscriber _map_sub, _pts_sub; 45 | ros::Publisher _grid_path_vis_pub, _visited_nodes_vis_pub, _grid_map_vis_pub; 46 | 47 | AstarPathFinder * _astar_path_finder = new AstarPathFinder(); 48 | JPSPathFinder *_jps_path_finder = new JPSPathFinder(); 49 | 50 | void rcvWaypointsCallback(const nav_msgs::Path & wp); 51 | 52 | void rcvPointCloudCallBack(const sensor_msgs::PointCloud2 & pointcloud_map); 53 | 54 | void visGridPath( vector nodes, bool is_use_jps ); 55 | 56 | void visVisitedNode( vector nodes ); 57 | 58 | void pathFinding(const Vector3d start_pt, const Vector3d target_pt); 59 | 60 | void rcvWaypointsCallback(const nav_msgs::Path & wp) 61 | { 62 | if( wp.poses[0].pose.position.z < 0.0 || _has_map == false ) 63 | return; 64 | 65 | Vector3d target_pt; 66 | target_pt << wp.poses[0].pose.position.x, 67 | wp.poses[0].pose.position.y, 68 | wp.poses[0].pose.position.z; 69 | 70 | ROS_INFO("[node] receive the planning target"); 71 | pathFinding(_start_pt, target_pt); 72 | } 73 | 74 | void rcvPointCloudCallBack(const sensor_msgs::PointCloud2 & pointcloud_map) 75 | { 76 | if(_has_map ) return; 77 | 78 | pcl::PointCloud cloud; 79 | pcl::PointCloud cloud_vis; 80 | sensor_msgs::PointCloud2 map_vis; 81 | 82 | pcl::fromROSMsg(pointcloud_map, cloud); 83 | 84 | if( (int)cloud.points.size() == 0 ) return; 85 | 86 | pcl::PointXYZ pt; 87 | for (int idx = 0; idx < (int)cloud.points.size(); idx++) 88 | { 89 | pt = cloud.points[idx]; 90 | 91 | _astar_path_finder->setObs(pt.x, pt.y, pt.z); 92 | _jps_path_finder->setObs(pt.x, pt.y, pt.z); 93 | 94 | Vector3d cor_round = _astar_path_finder->coordRounding(Vector3d(pt.x, pt.y, pt.z)); 95 | pt.x = cor_round(0); 96 | pt.y = cor_round(1); 97 | pt.z = cor_round(2); 98 | cloud_vis.points.push_back(pt); 99 | } 100 | 101 | cloud_vis.width = cloud_vis.points.size(); 102 | cloud_vis.height = 1; 103 | cloud_vis.is_dense = true; 104 | 105 | pcl::toROSMsg(cloud_vis, map_vis); 106 | 107 | map_vis.header.frame_id = "/world"; 108 | _grid_map_vis_pub.publish(map_vis); 109 | 110 | _has_map = true; 111 | } 112 | 113 | 114 | void pathFinding(const Vector3d start_pt, const Vector3d target_pt) 115 | { 116 | _astar_path_finder->AstarGraphSearch(start_pt, target_pt); 117 | 118 | auto grid_path = _astar_path_finder->getPath(); 119 | auto visited_nodes = _astar_path_finder->getVisitedNodes(); 120 | 121 | visGridPath (grid_path, false); 122 | 123 | visVisitedNode(visited_nodes); 124 | 125 | _astar_path_finder->resetUsedGrids(); 126 | 127 | if(_use_jps) 128 | { 129 | // 调用JPS算法 130 | _jps_path_finder->JPSGraphSearch(start_pt, target_pt); 131 | 132 | //获得最优路径和访问的节点 133 | auto visited_nodes = _jps_path_finder->getVisitedNodes(); 134 | auto grid_path = _jps_path_finder->getPath(); 135 | 136 | //可视化 137 | visGridPath(grid_path, _use_jps); 138 | visVisitedNode(visited_nodes); 139 | 140 | //重置栅格地图,为下次调用做准备 141 | _jps_path_finder->resetUsedGrids(); 142 | } 143 | 144 | 145 | 146 | } 147 | 148 | int main(int argc, char** argv) 149 | { 150 | ros::init(argc, argv, "demo_node"); 151 | ros::NodeHandle nh("~"); 152 | 153 | _map_sub = nh.subscribe( "map", 1, rcvPointCloudCallBack ); 154 | _pts_sub = nh.subscribe( "waypoints", 1, rcvWaypointsCallback ); 155 | 156 | _grid_map_vis_pub = nh.advertise("grid_map_vis", 1); 157 | _grid_path_vis_pub = nh.advertise("grid_path_vis", 1); 158 | _visited_nodes_vis_pub = nh.advertise("visited_nodes_vis",1); 159 | 160 | 161 | nh.param("map/cloud_margin", _cloud_margin, 0.0); 162 | nh.param("map/resolution", _resolution, 0.2); 163 | 164 | nh.param("map/x_size", _x_size, 50.0); 165 | nh.param("map/y_size", _y_size, 50.0); 166 | nh.param("map/z_size", _z_size, 5.0 ); 167 | 168 | nh.param("planning/start_x", _start_pt(0), 0.0); 169 | nh.param("planning/start_y", _start_pt(1), 0.0); 170 | nh.param("planning/start_z", _start_pt(2), 0.0); 171 | 172 | _map_lower << - _x_size/2.0, - _y_size/2.0, 0.0; 173 | _map_upper << + _x_size/2.0, + _y_size/2.0, _z_size; 174 | 175 | _inv_resolution = 1.0 / _resolution; 176 | 177 | _max_x_id = (int)(_x_size * _inv_resolution); 178 | _max_y_id = (int)(_y_size * _inv_resolution); 179 | _max_z_id = (int)(_z_size * _inv_resolution); 180 | 181 | _astar_path_finder = new AstarPathFinder(); 182 | 183 | _astar_path_finder -> initGridMap(_resolution, _map_lower, _map_upper, _max_x_id, _max_y_id, _max_z_id); 184 | 185 | _jps_path_finder = new JPSPathFinder(); 186 | _jps_path_finder->initGridMap(_resolution, _map_lower, _map_upper, _max_x_id, _max_y_id, _max_z_id); 187 | 188 | ros::Rate rate(100); 189 | bool status = ros::ok(); 190 | while(status) 191 | { 192 | ros::spinOnce(); 193 | status = ros::ok(); 194 | rate.sleep(); 195 | } 196 | 197 | delete _astar_path_finder; 198 | delete _jps_path_finder; 199 | return 0; 200 | } 201 | 202 | void visGridPath( vector nodes, bool is_use_jps ) 203 | { 204 | visualization_msgs::Marker node_vis; 205 | node_vis.header.frame_id = "world"; 206 | node_vis.header.stamp = ros::Time::now(); 207 | 208 | if(is_use_jps) 209 | node_vis.ns = "demo_node/jps_path"; 210 | else 211 | node_vis.ns = "demo_node/astar_path"; 212 | 213 | node_vis.type = visualization_msgs::Marker::CUBE_LIST; 214 | node_vis.action = visualization_msgs::Marker::ADD; 215 | node_vis.id = 0; 216 | 217 | node_vis.pose.orientation.x = 0.0; 218 | node_vis.pose.orientation.y = 0.0; 219 | node_vis.pose.orientation.z = 0.0; 220 | node_vis.pose.orientation.w = 1.0; 221 | 222 | if(is_use_jps){ 223 | node_vis.color.a = 1.0; //jps black 224 | node_vis.color.r = 0.0; 225 | node_vis.color.g = 0.0; 226 | node_vis.color.b = 0.0; 227 | } 228 | else{ 229 | node_vis.color.a = 1.0; //astar white 230 | node_vis.color.r = 1.0; 231 | node_vis.color.g = 1.0; 232 | node_vis.color.b = 1.0; 233 | } 234 | 235 | 236 | node_vis.scale.x = _resolution; 237 | node_vis.scale.y = _resolution; 238 | node_vis.scale.z = _resolution; 239 | 240 | geometry_msgs::Point pt; 241 | for(int i = 0; i < int(nodes.size()); i++) 242 | { 243 | Vector3d coord = nodes[i]; 244 | pt.x = coord(0); 245 | pt.y = coord(1); 246 | pt.z = coord(2); 247 | 248 | node_vis.points.push_back(pt); 249 | } 250 | 251 | _grid_path_vis_pub.publish(node_vis); 252 | } 253 | 254 | void visVisitedNode( vector nodes ) 255 | { 256 | visualization_msgs::Marker node_vis; 257 | node_vis.header.frame_id = "world"; 258 | node_vis.header.stamp = ros::Time::now(); 259 | node_vis.ns = "demo_node/expanded_nodes"; 260 | node_vis.type = visualization_msgs::Marker::CUBE_LIST; 261 | node_vis.action = visualization_msgs::Marker::ADD; 262 | node_vis.id = 0; 263 | 264 | node_vis.pose.orientation.x = 0.0; 265 | node_vis.pose.orientation.y = 0.0; 266 | node_vis.pose.orientation.z = 0.0; 267 | node_vis.pose.orientation.w = 1.0; 268 | node_vis.color.a = 0.5; 269 | node_vis.color.r = 0.0; 270 | node_vis.color.g = 0.0; 271 | node_vis.color.b = 1.0; 272 | 273 | node_vis.scale.x = _resolution; 274 | node_vis.scale.y = _resolution; 275 | node_vis.scale.z = _resolution; 276 | 277 | geometry_msgs::Point pt; 278 | for(int i = 0; i < int(nodes.size()); i++) 279 | { 280 | Vector3d coord = nodes[i]; 281 | pt.x = coord(0); 282 | pt.y = coord(1); 283 | pt.z = coord(2); 284 | 285 | node_vis.points.push_back(pt); 286 | } 287 | 288 | _visited_nodes_vis_pub.publish(node_vis); 289 | } 290 | -------------------------------------------------------------------------------- /waypoint_generator/src/waypoint_generator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "sample_waypoints.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | using bfmt = boost::format; 17 | 18 | ros::Publisher pub1; 19 | ros::Publisher pub2; 20 | ros::Publisher pub3; 21 | string waypoint_type = string("manual"); 22 | bool is_odom_ready; 23 | nav_msgs::Odometry odom; 24 | nav_msgs::Path waypoints; 25 | 26 | 27 | std::deque waypointSegments; 28 | ros::Time trigged_time; 29 | 30 | void load_seg(ros::NodeHandle& nh, int segid, const ros::Time& time_base) { 31 | std::string seg_str = boost::str(bfmt("seg%d/") % segid); 32 | double yaw; 33 | double time_from_start; 34 | ROS_INFO("Getting segment %d", segid); 35 | ROS_ASSERT(nh.getParam(seg_str + "yaw", yaw)); 36 | ROS_ASSERT_MSG((yaw > -3.1499999) && (yaw < 3.14999999), "yaw=%.3f", yaw); 37 | ROS_ASSERT(nh.getParam(seg_str + "time_from_start", time_from_start)); 38 | ROS_ASSERT(time_from_start >= 0.0); 39 | 40 | std::vector ptx; 41 | std::vector pty; 42 | std::vector ptz; 43 | 44 | ROS_ASSERT(nh.getParam(seg_str + "x", ptx)); 45 | ROS_ASSERT(nh.getParam(seg_str + "y", pty)); 46 | ROS_ASSERT(nh.getParam(seg_str + "z", ptz)); 47 | 48 | ROS_ASSERT(ptx.size()); 49 | ROS_ASSERT(ptx.size() == pty.size() && ptx.size() == ptz.size()); 50 | 51 | nav_msgs::Path path_msg; 52 | 53 | path_msg.header.stamp = time_base + ros::Duration(time_from_start); 54 | 55 | double baseyaw = tf::getYaw(odom.pose.pose.orientation); 56 | 57 | for (size_t k = 0; k < ptx.size(); ++k) { 58 | geometry_msgs::PoseStamped pt; 59 | pt.pose.orientation = tf::createQuaternionMsgFromYaw(baseyaw + yaw); 60 | Eigen::Vector2d dp(ptx.at(k), pty.at(k)); 61 | Eigen::Vector2d rdp; 62 | rdp.x() = std::cos(-baseyaw-yaw)*dp.x() + std::sin(-baseyaw-yaw)*dp.y(); 63 | rdp.y() =-std::sin(-baseyaw-yaw)*dp.x() + std::cos(-baseyaw-yaw)*dp.y(); 64 | pt.pose.position.x = rdp.x() + odom.pose.pose.position.x; 65 | pt.pose.position.y = rdp.y() + odom.pose.pose.position.y; 66 | pt.pose.position.z = ptz.at(k) + odom.pose.pose.position.z; 67 | path_msg.poses.push_back(pt); 68 | } 69 | 70 | waypointSegments.push_back(path_msg); 71 | } 72 | 73 | void load_waypoints(ros::NodeHandle& nh, const ros::Time& time_base) { 74 | int seg_cnt = 0; 75 | waypointSegments.clear(); 76 | ROS_ASSERT(nh.getParam("segment_cnt", seg_cnt)); 77 | for (int i = 0; i < seg_cnt; ++i) { 78 | load_seg(nh, i, time_base); 79 | if (i > 0) { 80 | ROS_ASSERT(waypointSegments[i - 1].header.stamp < waypointSegments[i].header.stamp); 81 | } 82 | } 83 | ROS_INFO("Overall load %zu segments", waypointSegments.size()); 84 | } 85 | 86 | void publish_waypoints() { 87 | waypoints.header.frame_id = std::string("world"); 88 | waypoints.header.stamp = ros::Time::now(); 89 | pub1.publish(waypoints); 90 | geometry_msgs::PoseStamped init_pose; 91 | init_pose.header = odom.header; 92 | init_pose.pose = odom.pose.pose; 93 | waypoints.poses.insert(waypoints.poses.begin(), init_pose); 94 | 95 | waypoints.poses.clear(); 96 | } 97 | 98 | void publish_waypoints_vis() { 99 | nav_msgs::Path wp_vis = waypoints; 100 | geometry_msgs::PoseArray poseArray; 101 | poseArray.header.frame_id = std::string("world"); 102 | poseArray.header.stamp = ros::Time::now(); 103 | 104 | { 105 | geometry_msgs::Pose init_pose; 106 | init_pose = odom.pose.pose; 107 | poseArray.poses.push_back(init_pose); 108 | } 109 | 110 | for (auto it = waypoints.poses.begin(); it != waypoints.poses.end(); ++it) { 111 | geometry_msgs::Pose p; 112 | p = it->pose; 113 | poseArray.poses.push_back(p); 114 | } 115 | pub2.publish(poseArray); 116 | } 117 | 118 | void odom_callback(const nav_msgs::Odometry::ConstPtr& msg) { 119 | is_odom_ready = true; 120 | odom = *msg; 121 | 122 | if (waypointSegments.size()) { 123 | ros::Time expected_time = waypointSegments.front().header.stamp; 124 | if (odom.header.stamp >= expected_time) { 125 | waypoints = waypointSegments.front(); 126 | 127 | std::stringstream ss; 128 | ss << bfmt("Series send %.3f from start:\n") % trigged_time.toSec(); 129 | for (auto& pose_stamped : waypoints.poses) { 130 | ss << bfmt("P[%.2f, %.2f, %.2f] q(%.2f,%.2f,%.2f,%.2f)") % 131 | pose_stamped.pose.position.x % pose_stamped.pose.position.y % 132 | pose_stamped.pose.position.z % pose_stamped.pose.orientation.w % 133 | pose_stamped.pose.orientation.x % pose_stamped.pose.orientation.y % 134 | pose_stamped.pose.orientation.z << std::endl; 135 | } 136 | ROS_INFO_STREAM(ss.str()); 137 | 138 | publish_waypoints_vis(); 139 | publish_waypoints(); 140 | 141 | waypointSegments.pop_front(); 142 | } 143 | } 144 | } 145 | 146 | 147 | void goal_callback(const geometry_msgs::PoseStamped::ConstPtr& msg) { 148 | 149 | trigged_time = ros::Time::now(); 150 | 151 | 152 | ros::NodeHandle n("~"); 153 | n.param("waypoint_type", waypoint_type, string("manual")); 154 | 155 | if (waypoint_type == string("circle")) { 156 | waypoints = circle(); 157 | publish_waypoints_vis(); 158 | publish_waypoints(); 159 | } else if (waypoint_type == string("eight")) { 160 | waypoints = eight(); 161 | publish_waypoints_vis(); 162 | publish_waypoints(); 163 | } else if (waypoint_type == string("point")) { 164 | waypoints = point(); 165 | publish_waypoints_vis(); 166 | publish_waypoints(); 167 | } else if (waypoint_type == string("series")) { 168 | load_waypoints(n, trigged_time); 169 | 170 | 171 | } else if (waypoint_type == string("manual-lonely-waypoint")) { 172 | if (msg->pose.position.z >= 0) { 173 | 174 | geometry_msgs::PoseStamped pt = *msg; 175 | waypoints.poses.clear(); 176 | waypoints.poses.push_back(pt); 177 | publish_waypoints_vis(); 178 | publish_waypoints(); 179 | } else { 180 | ROS_WARN("[waypoint_generator] invalid goal in manual-lonely-waypoint mode."); 181 | } 182 | } else { 183 | if (msg->pose.position.z > 0) { 184 | 185 | geometry_msgs::PoseStamped pt = *msg; 186 | if (waypoint_type == string("noyaw")) { 187 | double yaw = tf::getYaw(odom.pose.pose.orientation); 188 | pt.pose.orientation = tf::createQuaternionMsgFromYaw(yaw); 189 | } 190 | waypoints.poses.push_back(pt); 191 | publish_waypoints_vis(); 192 | } else if (msg->pose.position.z > -1.0) { 193 | 194 | if (waypoints.poses.size() >= 1) { 195 | waypoints.poses.erase(std::prev(waypoints.poses.end())); 196 | } 197 | publish_waypoints_vis(); 198 | } else { 199 | 200 | if (waypoints.poses.size() >= 1) { 201 | publish_waypoints_vis(); 202 | publish_waypoints(); 203 | } 204 | } 205 | } 206 | } 207 | 208 | void traj_start_trigger_callback(const geometry_msgs::PoseStamped& msg) { 209 | if (!is_odom_ready) { 210 | ROS_ERROR("[waypoint_generator] No odom!"); 211 | return; 212 | } 213 | 214 | ROS_WARN("[waypoint_generator] Trigger!"); 215 | trigged_time = odom.header.stamp; 216 | ROS_ASSERT(trigged_time > ros::Time(0)); 217 | 218 | ros::NodeHandle n("~"); 219 | n.param("waypoint_type", waypoint_type, string("manual")); 220 | 221 | ROS_ERROR_STREAM("Pattern " << waypoint_type << " generated!"); 222 | if (waypoint_type == string("free")) { 223 | waypoints = point(); 224 | publish_waypoints_vis(); 225 | publish_waypoints(); 226 | } else if (waypoint_type == string("circle")) { 227 | waypoints = circle(); 228 | publish_waypoints_vis(); 229 | publish_waypoints(); 230 | } else if (waypoint_type == string("eight")) { 231 | waypoints = eight(); 232 | publish_waypoints_vis(); 233 | publish_waypoints(); 234 | } else if (waypoint_type == string("point")) { 235 | waypoints = point(); 236 | publish_waypoints_vis(); 237 | publish_waypoints(); 238 | } else if (waypoint_type == string("series")) { 239 | load_waypoints(n, trigged_time); 240 | } 241 | } 242 | 243 | int main(int argc, char** argv) { 244 | ros::init(argc, argv, "waypoint_generator"); 245 | ros::NodeHandle n("~"); 246 | n.param("waypoint_type", waypoint_type, string("manual")); 247 | ros::Subscriber sub1 = n.subscribe("odom", 10, odom_callback); 248 | ros::Subscriber sub2 = n.subscribe("goal", 10, goal_callback); 249 | ros::Subscriber sub3 = n.subscribe("traj_start_trigger", 10, traj_start_trigger_callback); 250 | pub1 = n.advertise("waypoints", 50); 251 | pub2 = n.advertise("waypoints_vis", 10); 252 | 253 | trigged_time = ros::Time(0); 254 | 255 | ros::spin(); 256 | return 0; 257 | } 258 | -------------------------------------------------------------------------------- /grid_path_searcher/src/JPS_searcher.cpp: -------------------------------------------------------------------------------- 1 | #include "JPS_searcher.h" 2 | 3 | using namespace std; 4 | using namespace Eigen; 5 | 6 | void JPSPathFinder::JPSGraphSearch(Eigen::Vector3d start_pt, Eigen::Vector3d end_pt) 7 | { 8 | ros::Time time_1 = ros::Time::now(); 9 | 10 | //起点和终点的索引向量 11 | Vector3i start_idx = coord2gridIndex(start_pt); 12 | Vector3i end_idx = coord2gridIndex(end_pt); 13 | goalIdx = end_idx; 14 | 15 | //起点和终点的位置向量 16 | start_pt = gridIndex2coord(start_idx); 17 | end_pt = gridIndex2coord(end_idx); 18 | 19 | //初始化起点和终点的节点(指针) 20 | GridNodePtr startPtr = GridNodeMap[start_idx(0)][start_idx(1)][start_idx(2)]; 21 | GridNodePtr endPtr = GridNodeMap[end_idx(0)][end_idx(1)][end_idx(2)]; 22 | 23 | openSet.clear(); //使用STL库中的multimap维护openset 24 | 25 | GridNodePtr currentPtr = NULL; // currentPtr代表openset中f(n)最小的节点 26 | GridNodePtr neighborPtr = NULL; 27 | 28 | startPtr->gScore = 0; 29 | startPtr->fScore = getHeu2(startPtr, endPtr); 30 | startPtr->id = 1; //标记起始节点为未访问 31 | openSet.insert(make_pair(startPtr->fScore, startPtr)); //将起始节点加入openset 32 | 33 | double tentative_gScore; 34 | vector neighborPtrSets; 35 | vector edgeCostSets; 36 | 37 | //主循环 38 | while (!openSet.empty()) 39 | { 40 | 41 | std::multimap::iterator itFoundmin; 42 | for (itFoundmin = openSet.begin(); itFoundmin != openSet.end(); itFoundmin++) 43 | { 44 | if (itFoundmin->second->id == 1) //说明该节点没被访问过 45 | { 46 | currentPtr = itFoundmin->second; 47 | currentPtr->id = -1; //标记当前节点为已访问状态 48 | break; 49 | } 50 | } 51 | 52 | //找到Goal,返回 53 | if (currentPtr->index == goalIdx) 54 | { 55 | ros::Time time_2 = ros::Time::now(); 56 | terminatePtr = currentPtr; 57 | ROS_WARN("[Better_A*_JPS_Black] succeed ! Time consumed : %f ms, path cost : %f m", (time_2 - time_1).toSec() * 1000.0, currentPtr->gScore * resolution); 58 | return; 59 | } 60 | 61 | //得到当前节点的继承 62 | JPSGetSucc(currentPtr, neighborPtrSets, edgeCostSets); 63 | 64 | //处理发现的neighbor 65 | for (int i = 0; i < (int)neighborPtrSets.size(); i++) 66 | { 67 | 68 | neighborPtr = neighborPtrSets[i]; 69 | if (neighborPtr->id == 0) //发现一个新节点 70 | { 71 | neighborPtr->id = 1; //标记该节点为未访问状态 72 | neighborPtr->cameFrom = currentPtr; 73 | neighborPtr->gScore = currentPtr->gScore + edgeCostSets[i]; 74 | neighborPtr->fScore = neighborPtr->gScore + getHeu2(neighborPtr, endPtr); 75 | openSet.insert(make_pair(neighborPtr->fScore, neighborPtr)); 76 | continue; 77 | } 78 | else if(neighborPtr->id == 1) //该节点已经在openSet内 79 | { 80 | tentative_gScore = currentPtr->gScore + edgeCostSets[i]; 81 | 82 | if(tentative_gScore <= neighborPtr->gScore) //当前路线的g(n) <= openSet中的g(n), 需要更新 83 | { 84 | neighborPtr->gScore = tentative_gScore; 85 | neighborPtr->fScore = neighborPtr->gScore + getHeu2(neighborPtr, endPtr); 86 | neighborPtr->cameFrom = currentPtr; 87 | for (int i = 0; i < 3; i++) //计算新的扩展方向 88 | { 89 | neighborPtr->dir(i) = neighborPtr->index(i) - currentPtr->index(i); 90 | if (neighborPtr->dir(i) != 0) 91 | neighborPtr->dir(i) /= abs(neighborPtr->dir(i)); 92 | } 93 | } 94 | } 95 | 96 | } 97 | } 98 | 99 | //搜索失败 100 | ros::Time time_2 = ros::Time::now(); 101 | if ((time_2 - time_1).toSec() > 0.1) 102 | ROS_WARN("[JPS] failed, Time consume in JPS path finding is %f", (time_2 - time_1).toSec()); 103 | } 104 | 105 | inline void JPSPathFinder::JPSGetSucc(GridNodePtr currentPtr, vector &neighborPtrSets, vector &edgeCostSets) 106 | { 107 | neighborPtrSets.clear(); 108 | edgeCostSets.clear(); 109 | const int norm1 = abs(currentPtr->dir(0)) + abs(currentPtr->dir(1)) + abs(currentPtr->dir(2)); 110 | 111 | int num_neib = jn3d->nsz[norm1][0]; 112 | int num_fneib = jn3d->nsz[norm1][1]; 113 | int id = (currentPtr->dir(0) + 1) + 3 * (currentPtr->dir(1) + 1) + 9 * (currentPtr->dir(2) + 1); 114 | 115 | for (int dev = 0; dev < num_neib + num_fneib; ++dev) 116 | { 117 | Vector3i neighborIdx; 118 | Vector3i expandDir; 119 | 120 | if (dev < num_neib) 121 | { 122 | expandDir(0) = jn3d->ns[id][0][dev]; 123 | expandDir(1) = jn3d->ns[id][1][dev]; 124 | expandDir(2) = jn3d->ns[id][2][dev]; 125 | 126 | if (!jump(currentPtr->index, expandDir, neighborIdx)) 127 | continue; 128 | } 129 | else 130 | { 131 | int nx = currentPtr->index(0) + jn3d->f1[id][0][dev - num_neib]; 132 | int ny = currentPtr->index(1) + jn3d->f1[id][1][dev - num_neib]; 133 | int nz = currentPtr->index(2) + jn3d->f1[id][2][dev - num_neib]; 134 | 135 | if (isOccupied(nx, ny, nz)) 136 | { 137 | expandDir(0) = jn3d->f2[id][0][dev - num_neib]; 138 | expandDir(1) = jn3d->f2[id][1][dev - num_neib]; 139 | expandDir(2) = jn3d->f2[id][2][dev - num_neib]; 140 | 141 | if (!jump(currentPtr->index, expandDir, neighborIdx)) 142 | continue; 143 | } 144 | else 145 | continue; 146 | } 147 | 148 | GridNodePtr nodePtr = GridNodeMap[neighborIdx(0)][neighborIdx(1)][neighborIdx(2)]; 149 | nodePtr->dir = expandDir; 150 | 151 | neighborPtrSets.push_back(nodePtr); 152 | edgeCostSets.push_back( //当前节点与邻居节点之间的cost 153 | sqrt( 154 | (neighborIdx(0) - currentPtr->index(0)) * (neighborIdx(0) - currentPtr->index(0)) + 155 | (neighborIdx(1) - currentPtr->index(1)) * (neighborIdx(1) - currentPtr->index(1)) + 156 | (neighborIdx(2) - currentPtr->index(2)) * (neighborIdx(2) - currentPtr->index(2)))); 157 | } 158 | } 159 | 160 | bool JPSPathFinder::jump(const Vector3i &curIdx, const Vector3i &expDir, Vector3i &neiIdx) 161 | { 162 | neiIdx = curIdx + expDir; 163 | 164 | if (!isFree(neiIdx)) 165 | return false; 166 | 167 | if (neiIdx == goalIdx) 168 | return true; 169 | 170 | if (hasForced(neiIdx, expDir)) 171 | return true; 172 | 173 | const int id = (expDir(0) + 1) + 3 * (expDir(1) + 1) + 9 * (expDir(2) + 1); 174 | const int norm1 = abs(expDir(0)) + abs(expDir(1)) + abs(expDir(2)); 175 | int num_neib = jn3d->nsz[norm1][0]; 176 | 177 | for (int k = 0; k < num_neib - 1; ++k) 178 | { 179 | Vector3i newNeiIdx; 180 | Vector3i newDir(jn3d->ns[id][0][k], jn3d->ns[id][1][k], jn3d->ns[id][2][k]); 181 | if (jump(neiIdx, newDir, newNeiIdx)) 182 | return true; 183 | } 184 | 185 | return jump(neiIdx, expDir, neiIdx); 186 | } 187 | 188 | inline bool JPSPathFinder::hasForced(const Vector3i &idx, const Vector3i &dir) 189 | { 190 | int norm1 = abs(dir(0)) + abs(dir(1)) + abs(dir(2)); 191 | int id = (dir(0) + 1) + 3 * (dir(1) + 1) + 9 * (dir(2) + 1); 192 | 193 | switch (norm1) 194 | { 195 | case 1: 196 | // 1-d move, check 8 neighbors 197 | for (int fn = 0; fn < 8; ++fn) 198 | { 199 | int nx = idx(0) + jn3d->f1[id][0][fn]; 200 | int ny = idx(1) + jn3d->f1[id][1][fn]; 201 | int nz = idx(2) + jn3d->f1[id][2][fn]; 202 | if (isOccupied(nx, ny, nz)) 203 | return true; 204 | } 205 | return false; 206 | 207 | case 2: 208 | // 2-d move, check 8 neighbors 209 | for (int fn = 0; fn < 8; ++fn) 210 | { 211 | int nx = idx(0) + jn3d->f1[id][0][fn]; 212 | int ny = idx(1) + jn3d->f1[id][1][fn]; 213 | int nz = idx(2) + jn3d->f1[id][2][fn]; 214 | if (isOccupied(nx, ny, nz)) 215 | return true; 216 | } 217 | return false; 218 | 219 | case 3: 220 | // 3-d move, check 6 neighbors 221 | for (int fn = 0; fn < 6; ++fn) 222 | { 223 | int nx = idx(0) + jn3d->f1[id][0][fn]; 224 | int ny = idx(1) + jn3d->f1[id][1][fn]; 225 | int nz = idx(2) + jn3d->f1[id][2][fn]; 226 | if (isOccupied(nx, ny, nz)) 227 | return true; 228 | } 229 | return false; 230 | 231 | default: 232 | return false; 233 | } 234 | } 235 | 236 | inline bool JPSPathFinder::isOccupied(const Eigen::Vector3i &index) const 237 | { 238 | return isOccupied(index(0), index(1), index(2)); 239 | } 240 | 241 | inline bool JPSPathFinder::isFree(const Eigen::Vector3i &index) const 242 | { 243 | return isFree(index(0), index(1), index(2)); 244 | } 245 | 246 | inline bool JPSPathFinder::isOccupied(const int &idx_x, const int &idx_y, const int &idx_z) const 247 | { 248 | return (idx_x >= 0 && idx_x < GLX_SIZE && idx_y >= 0 && idx_y < GLY_SIZE && idx_z >= 0 && idx_z < GLZ_SIZE && 249 | (data[idx_x * GLYZ_SIZE + idx_y * GLZ_SIZE + idx_z] == 1)); 250 | } 251 | 252 | inline bool JPSPathFinder::isFree(const int &idx_x, const int &idx_y, const int &idx_z) const 253 | { 254 | return (idx_x >= 0 && idx_x < GLX_SIZE && idx_y >= 0 && idx_y < GLY_SIZE && idx_z >= 0 && idx_z < GLZ_SIZE && 255 | (data[idx_x * GLYZ_SIZE + idx_y * GLZ_SIZE + idx_z] < 1)); 256 | } 257 | -------------------------------------------------------------------------------- /rviz_plugins/src/multi_probmap_display.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include "rviz/frame_manager.h" 15 | #include "rviz/ogre_helpers/grid.h" 16 | #include "rviz/properties/float_property.h" 17 | #include "rviz/properties/int_property.h" 18 | #include "rviz/properties/property.h" 19 | #include "rviz/properties/quaternion_property.h" 20 | #include "rviz/properties/ros_topic_property.h" 21 | #include "rviz/properties/vector_property.h" 22 | #include "rviz/validate_floats.h" 23 | #include "rviz/display_context.h" 24 | 25 | #include "multi_probmap_display.h" 26 | 27 | namespace rviz 28 | { 29 | 30 | MultiProbMapDisplay::MultiProbMapDisplay() 31 | : Display() 32 | , loaded_( false ) 33 | , new_map_(false) 34 | { 35 | topic_property_ = new RosTopicProperty( "Topic", "", 36 | QString::fromStdString( ros::message_traits::datatype() ), 37 | "multi_map_server::MultiOccupancyGrid topic to subscribe to.", 38 | this, SLOT( updateTopic() )); 39 | 40 | draw_under_property_ = new Property( "Draw Behind", false, 41 | "Rendering option, controls whether or not the map is always" 42 | " drawn behind everything else.", 43 | this, SLOT( updateDrawUnder() )); 44 | } 45 | 46 | MultiProbMapDisplay::~MultiProbMapDisplay() 47 | { 48 | unsubscribe(); 49 | clear(); 50 | } 51 | 52 | void MultiProbMapDisplay::onInitialize() 53 | { 54 | } 55 | 56 | void MultiProbMapDisplay::onEnable() 57 | { 58 | subscribe(); 59 | } 60 | 61 | void MultiProbMapDisplay::onDisable() 62 | { 63 | unsubscribe(); 64 | clear(); 65 | } 66 | 67 | void MultiProbMapDisplay::subscribe() 68 | { 69 | if ( !isEnabled() ) 70 | { 71 | return; 72 | } 73 | 74 | if( !topic_property_->getTopic().isEmpty() ) 75 | { 76 | try 77 | { 78 | map_sub_ = update_nh_.subscribe( topic_property_->getTopicStd(), 1, &MultiProbMapDisplay::incomingMap, this ); 79 | setStatus( StatusProperty::Ok, "Topic", "OK" ); 80 | } 81 | catch( ros::Exception& e ) 82 | { 83 | setStatus( StatusProperty::Error, "Topic", QString( "Error subscribing: " ) + e.what() ); 84 | } 85 | } 86 | } 87 | 88 | void MultiProbMapDisplay::unsubscribe() 89 | { 90 | map_sub_.shutdown(); 91 | } 92 | 93 | void MultiProbMapDisplay::updateDrawUnder() 94 | { 95 | bool draw_under = draw_under_property_->getValue().toBool(); 96 | 97 | for (unsigned int k = 0; k < material_.size(); k++) 98 | material_[k]->setDepthWriteEnabled( !draw_under ); 99 | 100 | for (unsigned int k = 0; k < manual_object_.size(); k++) 101 | { 102 | if( draw_under ) 103 | manual_object_[k]->setRenderQueueGroup( Ogre::RENDER_QUEUE_4 ); 104 | else 105 | manual_object_[k]->setRenderQueueGroup( Ogre::RENDER_QUEUE_MAIN ); 106 | } 107 | } 108 | 109 | void MultiProbMapDisplay::updateTopic() 110 | { 111 | unsubscribe(); 112 | subscribe(); 113 | clear(); 114 | } 115 | 116 | void MultiProbMapDisplay::clear() 117 | { 118 | setStatus( StatusProperty::Warn, "Message", "No map received" ); 119 | 120 | if( !loaded_ ) 121 | { 122 | return; 123 | } 124 | 125 | for (unsigned k = 0; k < manual_object_.size(); k++) 126 | { 127 | scene_manager_->destroyManualObject( manual_object_[k] ); 128 | std::string tex_name = texture_[k]->getName(); 129 | texture_[k].setNull(); 130 | Ogre::TextureManager::getSingleton().unload( tex_name ); 131 | } 132 | manual_object_.clear(); 133 | texture_.clear(); 134 | material_.clear(); 135 | 136 | loaded_ = false; 137 | } 138 | 139 | // *********************************************************************************************************************************** 140 | 141 | void MultiProbMapDisplay::update( float wall_dt, float ros_dt ) 142 | { 143 | { 144 | boost::mutex::scoped_lock lock(mutex_); 145 | current_map_ = updated_map_; 146 | } 147 | 148 | if (!new_map_) 149 | return; 150 | new_map_ = false; 151 | 152 | clear(); 153 | 154 | //ros::Time t[5]; 155 | //double dt[4] = {0,0,0,0}; 156 | for (unsigned int k = 0; k < current_map_->maps.size(); k++) 157 | { 158 | if (current_map_->maps[k].data.empty()) 159 | continue; 160 | setStatus( StatusProperty::Ok, "Message", "Map received" ); 161 | 162 | // Map info 163 | float resolution = current_map_->maps[k].info.resolution; 164 | int width = current_map_->maps[k].info.width; 165 | int height = current_map_->maps[k].info.height; 166 | 167 | // Load pixel 168 | //t[0] = ros::Time::now(); 169 | unsigned int pixels_size = width * height; 170 | unsigned char* pixels = new unsigned char[pixels_size]; 171 | memset(pixels, 255, pixels_size); 172 | unsigned int num_pixels_to_copy = pixels_size; 173 | if( pixels_size != current_map_->maps[k].data.size() ) 174 | if( current_map_->maps[k].data.size() < pixels_size ) 175 | num_pixels_to_copy = current_map_->maps[k].data.size(); 176 | for( unsigned int pixel_index = 0; pixel_index < num_pixels_to_copy; pixel_index++ ) 177 | { 178 | unsigned char val; 179 | int8_t data = current_map_->maps[k].data[ pixel_index ]; 180 | if(data > 0) 181 | val = 255; 182 | else if(data < 0) 183 | val = 180; 184 | else 185 | val = 0; 186 | pixels[ pixel_index ] = val; 187 | } 188 | /* 189 | int pixels_size = current_map_->maps[k].data.size(); 190 | unsigned char* pixels = new unsigned char[pixels_size]; 191 | memcpy(pixels, ¤t_map_->maps[k].data[0], pixels_size); 192 | */ 193 | // Set texture 194 | //t[1] = ros::Time::now(); 195 | Ogre::DataStreamPtr pixel_stream; 196 | pixel_stream.bind( new Ogre::MemoryDataStream( pixels, pixels_size )); 197 | static int tex_count = 0; 198 | std::stringstream ss1; 199 | ss1 << "MultiMapTexture" << tex_count++; 200 | Ogre::TexturePtr _texture_; 201 | //t[2] = ros::Time::now(); 202 | _texture_ = Ogre::TextureManager::getSingleton().loadRawData( ss1.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 203 | pixel_stream, width, height, Ogre::PF_L8, Ogre::TEX_TYPE_2D, 0); 204 | //t[3] = ros::Time::now(); 205 | texture_.push_back(_texture_); 206 | delete [] pixels; 207 | setStatus( StatusProperty::Ok, "Map", "Map OK" ); 208 | //t[4] = ros::Time::now(); 209 | 210 | // Set material 211 | static int material_count = 0; 212 | std::stringstream ss0; 213 | ss0 << "MultiMapObjectMaterial" << material_count++; 214 | Ogre::MaterialPtr _material_; 215 | _material_ = Ogre::MaterialManager::getSingleton().create( ss0.str(), 216 | Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); 217 | _material_->setReceiveShadows(false); 218 | _material_->getTechnique(0)->setLightingEnabled(false); 219 | _material_->setDepthBias( -16.0f, 0.0f ); 220 | _material_->setCullingMode( Ogre::CULL_NONE ); 221 | _material_->setDepthWriteEnabled(false); 222 | material_.push_back(_material_); 223 | material_.back()->setSceneBlending( Ogre::SBT_TRANSPARENT_COLOUR ); 224 | material_.back()->setDepthWriteEnabled( false ); 225 | Ogre::Pass* pass = material_.back()->getTechnique(0)->getPass(0); 226 | Ogre::TextureUnitState* tex_unit = NULL; 227 | if (pass->getNumTextureUnitStates() > 0) 228 | tex_unit = pass->getTextureUnitState(0); 229 | else 230 | tex_unit = pass->createTextureUnitState(); 231 | tex_unit->setTextureName(texture_.back()->getName()); 232 | tex_unit->setTextureFiltering( Ogre::TFO_NONE ); 233 | 234 | // Set manual object 235 | static int map_count = 0; 236 | std::stringstream ss2; 237 | ss2 << "MultiMapObject" << map_count++; 238 | Ogre::ManualObject* _manual_object_ = scene_manager_->createManualObject( ss2.str() ); 239 | manual_object_.push_back(_manual_object_); 240 | scene_node_->attachObject( manual_object_.back() ); 241 | float yo = tf::getYaw(current_map_->origins[k].orientation); 242 | float co = cos(yo); 243 | float so = sin(yo); 244 | float dxo = current_map_->origins[k].position.x; 245 | float dyo = current_map_->origins[k].position.y; 246 | float ym = tf::getYaw(current_map_->maps[k].info.origin.orientation); 247 | float dxm = current_map_->maps[k].info.origin.position.x; 248 | float dym = current_map_->maps[k].info.origin.position.y; 249 | float yaw = yo + ym; 250 | float c = cos(yaw); 251 | float s = sin(yaw); 252 | float dx = co * dxm - so * dym + dxo; 253 | float dy = so * dxm + co * dym + dyo; 254 | float x = 0.0; 255 | float y = 0.0; 256 | manual_object_.back()->begin(material_.back()->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST); 257 | { 258 | 259 | { 260 | 261 | x = c * 0.0 - s * 0.0 + dx; 262 | y = s * 0.0 + c * 0.0 + dy; 263 | manual_object_.back()->position( x, y, 0.0f ); 264 | manual_object_.back()->textureCoord(0.0f, 0.0f); 265 | manual_object_.back()->normal( 0.0f, 0.0f, 1.0f ); 266 | 267 | 268 | x = c * resolution*width - s * resolution*height + dx; 269 | y = s * resolution*width + c * resolution*height + dy; 270 | manual_object_.back()->position( x, y, 0.0f ); 271 | manual_object_.back()->textureCoord(1.0f, 1.0f); 272 | manual_object_.back()->normal( 0.0f, 0.0f, 1.0f ); 273 | 274 | 275 | x = c * 0.0 - s * resolution*height + dx; 276 | y = s * 0.0 + c * resolution*height + dy; 277 | manual_object_.back()->position( x, y, 0.0f ); 278 | manual_object_.back()->textureCoord(0.0f, 1.0f); 279 | manual_object_.back()->normal( 0.0f, 0.0f, 1.0f ); 280 | } 281 | 282 | 283 | { 284 | 285 | x = c * 0.0 - s * 0.0 + dx; 286 | y = s * 0.0 + c * 0.0 + dy; 287 | manual_object_.back()->position( x, y, 0.0f ); 288 | manual_object_.back()->textureCoord(0.0f, 0.0f); 289 | manual_object_.back()->normal( 0.0f, 0.0f, 1.0f ); 290 | 291 | 292 | x = c * resolution*width - s * 0.0 + dx; 293 | y = s * resolution*width + c * 0.0 + dy; 294 | manual_object_.back()->position( x, y, 0.0f ); 295 | manual_object_.back()->textureCoord(1.0f, 0.0f); 296 | manual_object_.back()->normal( 0.0f, 0.0f, 1.0f ); 297 | 298 | 299 | x = c * resolution*width - s * resolution*height + dx; 300 | y = s * resolution*width + c * resolution*height + dy; 301 | manual_object_.back()->position( x, y, 0.0f ); 302 | manual_object_.back()->textureCoord(1.0f, 1.0f); 303 | manual_object_.back()->normal( 0.0f, 0.0f, 1.0f ); 304 | } 305 | } 306 | manual_object_.back()->end(); 307 | if( draw_under_property_->getValue().toBool() ) 308 | manual_object_.back()->setRenderQueueGroup(Ogre::RENDER_QUEUE_4); 309 | 310 | 311 | } 312 | loaded_ = true; 313 | context_->queueRender(); 314 | 315 | } 316 | 317 | // *********************************************************************************************************************************** 318 | 319 | void MultiProbMapDisplay::incomingMap(const multi_map_server::MultiOccupancyGrid::ConstPtr& msg) 320 | { 321 | updated_map_ = msg; 322 | boost::mutex::scoped_lock lock(mutex_); 323 | new_map_ = true; 324 | } 325 | 326 | void MultiProbMapDisplay::reset() 327 | { 328 | Display::reset(); 329 | clear(); 330 | updateTopic(); 331 | } 332 | 333 | } 334 | 335 | #include 336 | PLUGINLIB_EXPORT_CLASS( rviz::MultiProbMapDisplay, rviz::Display ) 337 | -------------------------------------------------------------------------------- /grid_path_searcher/src/Astar_searcher.cpp: -------------------------------------------------------------------------------- 1 | #include "Astar_searcher.h" 2 | 3 | using namespace std; 4 | using namespace Eigen; 5 | 6 | void AstarPathFinder::initGridMap(double _resolution, Vector3d global_xyz_l, Vector3d global_xyz_u, int max_x_id, int max_y_id, int max_z_id) 7 | { 8 | gl_xl = global_xyz_l(0); 9 | gl_yl = global_xyz_l(1); 10 | gl_zl = global_xyz_l(2); 11 | 12 | gl_xu = global_xyz_u(0); 13 | gl_yu = global_xyz_u(1); 14 | gl_zu = global_xyz_u(2); 15 | 16 | GLX_SIZE = max_x_id; 17 | GLY_SIZE = max_y_id; 18 | GLZ_SIZE = max_z_id; 19 | GLYZ_SIZE = GLY_SIZE * GLZ_SIZE; 20 | GLXYZ_SIZE = GLX_SIZE * GLYZ_SIZE; 21 | 22 | resolution = _resolution; 23 | inv_resolution = 1.0 / _resolution; 24 | 25 | data = new uint8_t[GLXYZ_SIZE]; 26 | 27 | memset(data, 0, GLXYZ_SIZE * sizeof(uint8_t)); 28 | 29 | GridNodeMap = new GridNodePtr ** [GLX_SIZE]; 30 | for(int i = 0; i < GLX_SIZE; i++){ 31 | GridNodeMap[i] = new GridNodePtr * [GLY_SIZE]; 32 | for(int j = 0; j < GLY_SIZE; j++){ 33 | GridNodeMap[i][j] = new GridNodePtr [GLZ_SIZE]; 34 | for( int k = 0; k < GLZ_SIZE;k++){ 35 | Vector3i tmpIdx(i,j,k); 36 | Vector3d pos = gridIndex2coord(tmpIdx); 37 | GridNodeMap[i][j][k] = new GridNode(tmpIdx, pos); 38 | } 39 | } 40 | } 41 | } 42 | 43 | void AstarPathFinder::resetGrid(GridNodePtr ptr) 44 | { 45 | ptr->id = 0; 46 | ptr->cameFrom = NULL; 47 | ptr->gScore = inf; 48 | ptr->fScore = inf; 49 | } 50 | 51 | void AstarPathFinder::resetUsedGrids() 52 | { 53 | for(int i=0; i < GLX_SIZE ; i++) 54 | for(int j=0; j < GLY_SIZE ; j++) 55 | for(int k=0; k < GLZ_SIZE ; k++) 56 | resetGrid(GridNodeMap[i][j][k]); 57 | } 58 | 59 | void AstarPathFinder::setObs(const double coord_x, const double coord_y, const double coord_z) 60 | { 61 | if( coord_x < gl_xl || coord_y < gl_yl || coord_z < gl_zl || 62 | coord_x >= gl_xu || coord_y >= gl_yu || coord_z >= gl_zu ) 63 | return; 64 | 65 | int idx_x = static_cast( (coord_x - gl_xl) * inv_resolution); 66 | int idx_y = static_cast( (coord_y - gl_yl) * inv_resolution); 67 | int idx_z = static_cast( (coord_z - gl_zl) * inv_resolution); 68 | 69 | data[idx_x * GLYZ_SIZE + idx_y * GLZ_SIZE + idx_z] = 1; 70 | } 71 | 72 | 73 | vector AstarPathFinder::getVisitedNodes() 74 | { 75 | vector visited_nodes; 76 | for(int i = 0; i < GLX_SIZE; i++) 77 | for(int j = 0; j < GLY_SIZE; j++) 78 | for(int k = 0; k < GLZ_SIZE; k++){ 79 | if(GridNodeMap[i][j][k]->id == -1) 80 | visited_nodes.push_back(GridNodeMap[i][j][k]->coord); 81 | } 82 | 83 | ROS_WARN("visited_nodes size : %d", visited_nodes.size()); 84 | return visited_nodes; 85 | } 86 | 87 | Vector3d AstarPathFinder::gridIndex2coord(const Vector3i & index) 88 | { 89 | Vector3d pt; 90 | 91 | pt(0) = ((double)index(0) + 0.5) * resolution + gl_xl; 92 | pt(1) = ((double)index(1) + 0.5) * resolution + gl_yl; 93 | pt(2) = ((double)index(2) + 0.5) * resolution + gl_zl; 94 | 95 | return pt; 96 | } 97 | 98 | 99 | Vector3i AstarPathFinder::coord2gridIndex(const Vector3d & pt) 100 | { 101 | Vector3i idx; 102 | idx << min( max( int( (pt(0) - gl_xl) * inv_resolution), 0), GLX_SIZE - 1), 103 | min( max( int( (pt(1) - gl_yl) * inv_resolution), 0), GLY_SIZE - 1), 104 | min( max( int( (pt(2) - gl_zl) * inv_resolution), 0), GLZ_SIZE - 1); 105 | 106 | return idx; 107 | } 108 | 109 | Eigen::Vector3d AstarPathFinder::coordRounding(const Eigen::Vector3d & coord) 110 | { 111 | return gridIndex2coord(coord2gridIndex(coord)); 112 | } 113 | 114 | inline bool AstarPathFinder::isOccupied(const Eigen::Vector3i & index) const 115 | { 116 | return isOccupied(index(0), index(1), index(2)); 117 | } 118 | 119 | inline bool AstarPathFinder::isFree(const Eigen::Vector3i & index) const 120 | { 121 | return isFree(index(0), index(1), index(2)); 122 | } 123 | 124 | inline bool AstarPathFinder::isOccupied(const int & idx_x, const int & idx_y, const int & idx_z) const 125 | { 126 | return (idx_x >= 0 && idx_x < GLX_SIZE && idx_y >= 0 && idx_y < GLY_SIZE && idx_z >= 0 && idx_z < GLZ_SIZE && 127 | (data[idx_x * GLYZ_SIZE + idx_y * GLZ_SIZE + idx_z] == 1)); 128 | } 129 | 130 | inline bool AstarPathFinder::isFree(const int & idx_x, const int & idx_y, const int & idx_z) const 131 | { 132 | return (idx_x >= 0 && idx_x < GLX_SIZE && idx_y >= 0 && idx_y < GLY_SIZE && idx_z >= 0 && idx_z < GLZ_SIZE && 133 | (data[idx_x * GLYZ_SIZE + idx_y * GLZ_SIZE + idx_z] < 1)); 134 | } 135 | 136 | 137 | inline void AstarPathFinder::AstarGetSucc(GridNodePtr currentPtr, vector & neighborPtrSets, vector & edgeCostSets) 138 | { 139 | neighborPtrSets.clear(); 140 | edgeCostSets.clear(); 141 | 142 | if(currentPtr == nullptr) 143 | std::cout << "Error: Current pointer is null!" << endl; 144 | 145 | Eigen::Vector3i thisNode = currentPtr -> index; 146 | int this_x = thisNode[0]; 147 | int this_y = thisNode[1]; 148 | int this_z = thisNode[2]; 149 | auto this_coord = currentPtr -> coord; 150 | int n_x, n_y, n_z; 151 | double dist; 152 | 153 | GridNodePtr temp_ptr = nullptr; 154 | Eigen::Vector3d n_coord; 155 | 156 | for(int i = -1;i <= 1;++i ){ 157 | for(int j = -1;j <= 1;++j ){ 158 | for(int k = -1;k <= 1;++k){ 159 | if( i == 0 && j == 0 && k == 0) 160 | continue; 161 | 162 | n_x = this_x + i; 163 | n_y = this_y + j; 164 | n_z = this_z + k; 165 | 166 | if( (n_x < 0) || (n_x > (GLX_SIZE - 1)) || (n_y < 0) || (n_y > (GLY_SIZE - 1) ) || (n_z < 0) || (n_z > (GLZ_SIZE - 1))) 167 | continue; 168 | 169 | if(isOccupied(n_x, n_y, n_z)) 170 | continue; 171 | 172 | temp_ptr = GridNodeMap[n_x][n_y][n_z]; 173 | 174 | if(temp_ptr->id == -1) 175 | continue; 176 | 177 | n_coord = temp_ptr->coord; 178 | 179 | if(temp_ptr == currentPtr){ 180 | std::cout << "Error: temp_ptr == currentPtr)" << std::endl; 181 | } 182 | 183 | if( (std::abs(n_coord[0] - this_coord[0]) < 1e-6) and (std::abs(n_coord[1] - this_coord[1]) < 1e-6) and (std::abs(n_coord[2] - this_coord[2]) < 1e-6 )){ 184 | std::cout << "Error: Not expanding correctly!" << std::endl; 185 | std::cout << "n_coord:" << n_coord[0] << " "<coord; 208 | auto node2_coord = node2->coord; 209 | 210 | // Heuristics 1: Manhattan 211 | // h = std::abs(node1_coord(0) - node2_coord(0) ) + 212 | // std::abs(node1_coord(1) - node2_coord(1) ) + 213 | // std::abs(node1_coord(2) - node2_coord(2) ); 214 | 215 | //Heuristics 2: Euclidean 216 | // h = std::sqrt(std::pow((node1_coord(0) - node2_coord(0)), 2 ) + 217 | // std::pow((node1_coord(1) - node2_coord(1)), 2 ) + 218 | // std::pow((node1_coord(2) - node2_coord(2)), 2 )); 219 | 220 | // Heuristics 3: Diagnol distance 221 | double dx = std::abs(node1_coord(0) - node2_coord(0) ); 222 | double dy = std::abs(node1_coord(1) - node2_coord(1) ); 223 | double dz = std::abs(node1_coord(2) - node2_coord(2) ); 224 | double min_xyz = std::min({dx, dy, dz}); 225 | h = dx + dy + dz + (std::sqrt(3.0) -3) * min_xyz; 226 | 227 | return 0; //0 -> h DIjkstra -> Astar 228 | } 229 | 230 | //This is the better h(n) that will be applied in JPS_searcher.cpp 231 | double AstarPathFinder::getHeu2(GridNodePtr node1, GridNodePtr node2) 232 | { 233 | //f(n)=g(n)+w(n)*h(n) 234 | double h; //heuristic(n) 235 | double distance; //distance 236 | double w; //weight(n) 237 | 238 | w = 8.0; 239 | distance = calEuclideanDistance(node1, node2); 240 | // if(distance > 2) 241 | // { 242 | // w = 8.0; 243 | // } 244 | // else{ 245 | // w = 0.7; 246 | // } 247 | h = w * distance; 248 | 249 | return h; 250 | } 251 | 252 | //Heuristics 2: Euclidean Distance 253 | double AstarPathFinder::calEuclideanDistance(GridNodePtr node1, GridNodePtr node2) 254 | { 255 | double distance; 256 | auto node1_coord = node1->coord; 257 | auto node2_coord = node2->coord; 258 | 259 | distance = std::sqrt(std::pow((node1_coord(0) - node2_coord(0)), 2 ) + 260 | std::pow((node1_coord(1) - node2_coord(1)), 2 ) + 261 | std::pow((node1_coord(2) - node2_coord(2)), 2 )); 262 | return distance; 263 | } 264 | 265 | void AstarPathFinder::AstarGraphSearch(Vector3d start_pt, Vector3d end_pt) 266 | { 267 | ros::Time time_1 = ros::Time::now(); 268 | 269 | Vector3i start_idx = coord2gridIndex(start_pt); 270 | Vector3i end_idx = coord2gridIndex(end_pt); 271 | goalIdx = end_idx; 272 | 273 | start_pt = gridIndex2coord(start_idx); 274 | end_pt = gridIndex2coord(end_idx); 275 | 276 | GridNodePtr startPtr = new GridNode(start_idx, start_pt); 277 | GridNodePtr endPtr = new GridNode(end_idx, end_pt); 278 | 279 | openSet.clear(); 280 | GridNodePtr currentPtr = NULL; 281 | GridNodePtr neighborPtr = NULL; 282 | 283 | 284 | startPtr -> gScore = 0; 285 | startPtr -> fScore = getHeu(startPtr,endPtr); 286 | startPtr -> id = 1; 287 | startPtr -> coord = start_pt; 288 | openSet.insert( make_pair(startPtr -> fScore, startPtr) ); 289 | 290 | GridNodeMap[start_idx[0]][start_idx[1]][start_idx[2]] -> id = 1; 291 | 292 | vector neighborPtrSets; 293 | vector edgeCostSets; 294 | Eigen::Vector3i current_idx; 295 | 296 | while ( !openSet.empty() ){ 297 | 298 | int x = openSet.begin()->second->index(0); 299 | int y = openSet.begin()->second->index(1); 300 | int z = openSet.begin()->second->index(2); 301 | openSet.erase(openSet.begin()); 302 | currentPtr = GridNodeMap[x][y][z]; 303 | 304 | if(currentPtr->id == -1) 305 | continue; 306 | 307 | currentPtr->id = -1; 308 | 309 | 310 | if( currentPtr->index == goalIdx ) 311 | { 312 | ros::Time time_2 = ros::Time::now(); 313 | terminatePtr = currentPtr; 314 | ROS_WARN("[A*_white] succeed ! Time consumed : %f ms, path cost : %f m", (time_2 - time_1).toSec() * 1000.0, currentPtr->gScore * resolution ); 315 | return; 316 | } 317 | 318 | 319 | AstarGetSucc(currentPtr, neighborPtrSets, edgeCostSets); 320 | 321 | for(int i = 0; i < (int)neighborPtrSets.size(); i++){ 322 | 323 | neighborPtr = neighborPtrSets[i]; 324 | if(neighborPtr -> id == 0){ 325 | 326 | neighborPtr->gScore = currentPtr->gScore + edgeCostSets[i]; 327 | neighborPtr->fScore = neighborPtr->gScore + getHeu(neighborPtr,endPtr); 328 | neighborPtr->cameFrom = currentPtr; 329 | 330 | openSet.insert(make_pair(neighborPtr -> fScore, neighborPtr)); 331 | neighborPtr -> id = 1; 332 | continue; 333 | } 334 | else if(neighborPtr -> id == 1){ 335 | if( neighborPtr->gScore > (currentPtr->gScore+edgeCostSets[i])) 336 | { 337 | neighborPtr -> gScore = currentPtr -> gScore + edgeCostSets[i]; 338 | neighborPtr -> fScore = neighborPtr -> gScore + getHeu(neighborPtr,endPtr); 339 | neighborPtr -> cameFrom = currentPtr; 340 | } 341 | 342 | continue; 343 | } 344 | else{ 345 | continue; 346 | } 347 | } 348 | } 349 | 350 | ros::Time time_2 = ros::Time::now(); 351 | if((time_2 - time_1).toSec() > 0.1) 352 | ROS_WARN("Time consume in Astar path finding is %f", (time_2 - time_1).toSec() ); 353 | } 354 | 355 | 356 | vector AstarPathFinder::getPath() 357 | { 358 | vector path; 359 | vector gridPath; 360 | 361 | auto ptr = terminatePtr; 362 | while(ptr -> cameFrom != NULL){ 363 | gridPath.push_back(ptr); 364 | ptr = ptr->cameFrom; 365 | } 366 | 367 | for (auto ptr: gridPath) 368 | path.push_back(ptr->coord); 369 | 370 | reverse(path.begin(),path.end()); 371 | return path; 372 | } 373 | -------------------------------------------------------------------------------- /grid_path_searcher/src/JPS_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "JPS_utils.h" 2 | 3 | constexpr int JPS3DNeib::nsz[4][2]; 4 | JPS3DNeib::JPS3DNeib() 5 | { 6 | int id = 0; 7 | for(int dz = -1; dz <= 1; ++ dz) 8 | { 9 | for(int dy = -1; dy <= 1; ++ dy) 10 | { 11 | for(int dx = -1; dx <= 1; ++ dx) 12 | { 13 | int norm1 = abs(dx) + abs(dy) + abs(dz); //0~3 14 | 15 | for(int dev = 0; dev < nsz[norm1][0]; ++ dev) //norm1 = 0,dev = 0~25 16 | Neib(dx,dy,dz,norm1,dev, ns[id][0][dev], ns[id][1][dev], ns[id][2][dev]); 17 | 18 | for(int dev = 0; dev < nsz[norm1][1]; ++ dev) 19 | { 20 | FNeib(dx,dy,dz,norm1,dev, 21 | f1[id][0][dev],f1[id][1][dev], f1[id][2][dev], 22 | f2[id][0][dev],f2[id][1][dev], f2[id][2][dev]); 23 | } 24 | 25 | id ++; 26 | } 27 | } 28 | } 29 | } 30 | 31 | 32 | void JPS3DNeib::Neib(int dx, int dy, int dz, int norm1, int dev, 33 | int& tx, int& ty, int& tz) 34 | { 35 | switch(norm1) 36 | { 37 | case 0: // 0 38 | switch(dev) 39 | { 40 | case 0: tx=1; ty=0; tz=0; return; 41 | case 1: tx=-1; ty=0; tz=0; return; 42 | case 2: tx=0; ty=1; tz=0; return; 43 | case 3: tx=1; ty=1; tz=0; return; 44 | case 4: tx=-1; ty=1; tz=0; return; 45 | case 5: tx=0; ty=-1; tz=0; return; 46 | case 6: tx=1; ty=-1; tz=0; return; 47 | case 7: tx=-1; ty=-1; tz=0; return; 48 | case 8: tx=0; ty=0; tz=1; return; 49 | case 9: tx=1; ty=0; tz=1; return; 50 | case 10: tx=-1; ty=0; tz=1; return; 51 | case 11: tx=0; ty=1; tz=1; return; 52 | case 12: tx=1; ty=1; tz=1; return; 53 | case 13: tx=-1; ty=1; tz=1; return; 54 | case 14: tx=0; ty=-1; tz=1; return; 55 | case 15: tx=1; ty=-1; tz=1; return; 56 | case 16: tx=-1; ty=-1; tz=1; return; 57 | case 17: tx=0; ty=0; tz=-1; return; 58 | case 18: tx=1; ty=0; tz=-1; return; 59 | case 19: tx=-1; ty=0; tz=-1; return; 60 | case 20: tx=0; ty=1; tz=-1; return; 61 | case 21: tx=1; ty=1; tz=-1; return; 62 | case 22: tx=-1; ty=1; tz=-1; return; 63 | case 23: tx=0; ty=-1; tz=-1; return; 64 | case 24: tx=1; ty=-1; tz=-1; return; 65 | case 25: tx=-1; ty=-1; tz=-1; return; 66 | } 67 | case 1: // 1 68 | tx = dx; ty = dy; tz = dz; return; 69 | case 2: // sqrt2 70 | switch(dev) 71 | { 72 | case 0: 73 | if(dz == 0) 74 | { 75 | tx = 0; ty = dy; tz = 0; return; 76 | } 77 | else 78 | { 79 | tx = 0; ty = 0; tz = dz; return; 80 | } 81 | case 1: 82 | if(dx == 0) 83 | { 84 | tx = 0; ty = dy; tz = 0; return; 85 | } 86 | else 87 | { 88 | tx = dx; ty = 0; tz = 0; return; 89 | } 90 | case 2: 91 | tx = dx; ty = dy; tz = dz; return; 92 | } 93 | case 3: //sqrt3 94 | switch(dev) 95 | { 96 | case 0: tx = dx; ty = 0; tz = 0; return; 97 | case 1: tx = 0; ty = dy; tz = 0; return; 98 | case 2: tx = 0; ty = 0; tz = dz; return; 99 | case 3: tx = dx; ty = dy; tz = 0; return; 100 | case 4: tx = dx; ty = 0; tz = dz; return; 101 | case 5: tx = 0; ty = dy; tz = dz; return; 102 | case 6: tx = dx; ty = dy; tz = dz; return; 103 | } 104 | } 105 | } 106 | 107 | void JPS3DNeib::FNeib( int dx, int dy, int dz, int norm1, int dev, 108 | int& fx, int& fy, int& fz, 109 | int& nx, int& ny, int& nz) 110 | { 111 | switch(norm1) 112 | { 113 | case 1: 114 | switch(dev) 115 | { 116 | case 0: fx= 0; fy= 1; fz = 0; break; 117 | case 1: fx= 0; fy=-1; fz = 0; break; 118 | case 2: fx= 1; fy= 0; fz = 0; break; 119 | case 3: fx= 1; fy= 1; fz = 0; break; 120 | case 4: fx= 1; fy=-1; fz = 0; break; 121 | case 5: fx=-1; fy= 0; fz = 0; break; 122 | case 6: fx=-1; fy= 1; fz = 0; break; 123 | case 7: fx=-1; fy=-1; fz = 0; break; 124 | } 125 | nx = fx; ny = fy; nz = dz; 126 | // switch order if different direction 127 | if(dx != 0) 128 | { 129 | fz = fx; fx = 0; 130 | nz = fz; nx = dx; 131 | } 132 | 133 | if(dy != 0) 134 | { 135 | fz = fy; fy = 0; 136 | nz = fz; ny = dy; 137 | } 138 | return; 139 | case 2: 140 | if(dx == 0) 141 | { 142 | switch(dev) 143 | { 144 | case 0: 145 | fx = 0; fy = 0; fz = -dz; 146 | nx = 0; ny = dy; nz = -dz; 147 | return; 148 | case 1: 149 | fx = 0; fy = -dy; fz = 0; 150 | nx = 0; ny = -dy; nz = dz; 151 | return; 152 | case 2: 153 | fx = 1; fy = 0; fz = 0; 154 | nx = 1; ny = dy; nz = dz; 155 | return; 156 | case 3: 157 | fx = -1; fy = 0; fz = 0; 158 | nx = -1; ny = dy; nz = dz; 159 | return; 160 | case 4: 161 | fx = 1; fy = 0; fz = -dz; 162 | nx = 1; ny = dy; nz = -dz; 163 | return; 164 | case 5: 165 | fx = 1; fy = -dy; fz = 0; 166 | nx = 1; ny = -dy; nz = dz; 167 | return; 168 | case 6: 169 | fx = -1; fy = 0; fz = -dz; 170 | nx = -1; ny = dy; nz = -dz; 171 | return; 172 | case 7: 173 | fx = -1; fy = -dy; fz = 0; 174 | nx = -1; ny = -dy; nz = dz; 175 | return; 176 | // Extras 177 | case 8: 178 | fx = 1; fy = 0; fz = 0; 179 | nx = 1; ny = dy; nz = 0; 180 | return; 181 | case 9: 182 | fx = 1; fy = 0; fz = 0; 183 | nx = 1; ny = 0; nz = dz; 184 | return; 185 | case 10: 186 | fx = -1; fy = 0; fz = 0; 187 | nx = -1; ny = dy; nz = 0; 188 | return; 189 | case 11: 190 | fx = -1; fy = 0; fz = 0; 191 | nx = -1; ny = 0; nz = dz; 192 | return; 193 | } 194 | } 195 | else if(dy == 0) 196 | { 197 | switch(dev) 198 | { 199 | case 0: 200 | fx = 0; fy = 0; fz = -dz; 201 | nx = dx; ny = 0; nz = -dz; 202 | return; 203 | case 1: 204 | fx = -dx; fy = 0; fz = 0; 205 | nx = -dx; ny = 0; nz = dz; 206 | return; 207 | case 2: 208 | fx = 0; fy = 1; fz = 0; 209 | nx = dx; ny = 1; nz = dz; 210 | return; 211 | case 3: 212 | fx = 0; fy = -1; fz = 0; 213 | nx = dx; ny = -1;nz = dz; 214 | return; 215 | case 4: 216 | fx = 0; fy = 1; fz = -dz; 217 | nx = dx; ny = 1; nz = -dz; 218 | return; 219 | case 5: 220 | fx = -dx; fy = 1; fz = 0; 221 | nx = -dx; ny = 1; nz = dz; 222 | return; 223 | case 6: 224 | fx = 0; fy = -1; fz = -dz; 225 | nx = dx; ny = -1; nz = -dz; 226 | return; 227 | case 7: 228 | fx = -dx; fy = -1; fz = 0; 229 | nx = -dx; ny = -1; nz = dz; 230 | return; 231 | // Extras 232 | case 8: 233 | fx = 0; fy = 1; fz = 0; 234 | nx = dx; ny = 1; nz = 0; 235 | return; 236 | case 9: 237 | fx = 0; fy = 1; fz = 0; 238 | nx = 0; ny = 1; nz = dz; 239 | return; 240 | case 10: 241 | fx = 0; fy = -1; fz = 0; 242 | nx = dx; ny = -1; nz = 0; 243 | return; 244 | case 11: 245 | fx = 0; fy = -1; fz = 0; 246 | nx = 0; ny = -1; nz = dz; 247 | return; 248 | } 249 | } 250 | else 251 | {// dz==0 252 | switch(dev) 253 | { 254 | case 0: 255 | fx = 0; fy = -dy; fz = 0; 256 | nx = dx; ny = -dy; nz = 0; 257 | return; 258 | case 1: 259 | fx = -dx; fy = 0; fz = 0; 260 | nx = -dx; ny = dy; nz = 0; 261 | return; 262 | case 2: 263 | fx = 0; fy = 0; fz = 1; 264 | nx = dx; ny = dy; nz = 1; 265 | return; 266 | case 3: 267 | fx = 0; fy = 0; fz = -1; 268 | nx = dx; ny = dy; nz = -1; 269 | return; 270 | case 4: 271 | fx = 0; fy = -dy; fz = 1; 272 | nx = dx; ny = -dy; nz = 1; 273 | return; 274 | case 5: 275 | fx = -dx; fy = 0; fz = 1; 276 | nx = -dx; ny = dy; nz = 1; 277 | return; 278 | case 6: 279 | fx = 0; fy = -dy; fz = -1; 280 | nx = dx; ny = -dy; nz = -1; 281 | return; 282 | case 7: 283 | fx = -dx; fy = 0; fz = -1; 284 | nx = -dx; ny = dy; nz = -1; 285 | return; 286 | // Extras 287 | case 8: 288 | fx = 0; fy = 0; fz = 1; 289 | nx = dx; ny = 0; nz = 1; 290 | return; 291 | case 9: 292 | fx = 0; fy = 0; fz = 1; 293 | nx = 0; ny = dy; nz = 1; 294 | return; 295 | case 10: 296 | fx = 0; fy = 0; fz = -1; 297 | nx = dx; ny = 0; nz = -1; 298 | return; 299 | case 11: 300 | fx = 0; fy = 0; fz = -1; 301 | nx = 0; ny = dy; nz = -1; 302 | return; 303 | } 304 | } 305 | case 3: 306 | switch(dev) 307 | { 308 | case 0: 309 | fx = -dx; fy = 0; fz = 0; 310 | nx = -dx; ny = dy; nz = dz; 311 | return; 312 | case 1: 313 | fx = 0; fy = -dy; fz = 0; 314 | nx = dx; ny = -dy; nz = dz; 315 | return; 316 | case 2: 317 | fx = 0; fy = 0; fz = -dz; 318 | nx = dx; ny = dy; nz = -dz; 319 | return; 320 | // Need to check up to here for forced! 321 | case 3: 322 | fx = 0; fy = -dy; fz = -dz; 323 | nx = dx; ny = -dy; nz = -dz; 324 | return; 325 | case 4: 326 | fx = -dx; fy = 0; fz = -dz; 327 | nx = -dx; ny = dy; nz = -dz; 328 | return; 329 | case 5: 330 | fx = -dx; fy = -dy; fz = 0; 331 | nx = -dx; ny = -dy; nz = dz; 332 | return; 333 | // Extras 334 | case 6: 335 | fx = -dx; fy = 0; fz = 0; 336 | nx = -dx; ny = 0; nz = dz; 337 | return; 338 | case 7: 339 | fx = -dx; fy = 0; fz = 0; 340 | nx = -dx; ny = dy; nz = 0; 341 | return; 342 | case 8: 343 | fx = 0; fy = -dy; fz = 0; 344 | nx = 0; ny = -dy; nz = dz; 345 | return; 346 | case 9: 347 | fx = 0; fy = -dy; fz = 0; 348 | nx = dx; ny = -dy; nz = 0; 349 | return; 350 | case 10: 351 | fx = 0; fy = 0; fz = -dz; 352 | nx = 0; ny = dy; nz = -dz; 353 | return; 354 | case 11: 355 | fx = 0; fy = 0; fz = -dz; 356 | nx = dx; ny = 0; nz = -dz; 357 | return; 358 | } 359 | } 360 | } -------------------------------------------------------------------------------- /rviz_plugins/src/aerialmap_display.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include "rviz/frame_manager.h" 14 | #include "rviz/ogre_helpers/grid.h" 15 | #include "rviz/properties/float_property.h" 16 | #include "rviz/properties/int_property.h" 17 | #include "rviz/properties/property.h" 18 | #include "rviz/properties/quaternion_property.h" 19 | #include "rviz/properties/ros_topic_property.h" 20 | #include "rviz/properties/vector_property.h" 21 | #include "rviz/validate_floats.h" 22 | #include "rviz/display_context.h" 23 | 24 | #include "aerialmap_display.h" 25 | 26 | namespace rviz 27 | { 28 | 29 | AerialMapDisplay::AerialMapDisplay() 30 | : Display() 31 | , manual_object_( NULL ) 32 | //, material_( 0 ) 33 | , loaded_( false ) 34 | , resolution_( 0.0f ) 35 | , width_( 0 ) 36 | , height_( 0 ) 37 | , position_(Ogre::Vector3::ZERO) 38 | , orientation_(Ogre::Quaternion::IDENTITY) 39 | , new_map_(false) 40 | { 41 | topic_property_ = new RosTopicProperty( "Topic", "", 42 | QString::fromStdString( ros::message_traits::datatype() ), 43 | "nav_msgs::OccupancyGrid topic to subscribe to.", 44 | this, SLOT( updateTopic() )); 45 | 46 | alpha_property_ = new FloatProperty( "Alpha", 0.7, 47 | "Amount of transparency to apply to the map.", 48 | this, SLOT( updateAlpha() )); 49 | alpha_property_->setMin( 0 ); 50 | alpha_property_->setMax( 1 ); 51 | 52 | draw_under_property_ = new Property( "Draw Behind", false, 53 | "Rendering option, controls whether or not the map is always" 54 | " drawn behind everything else.", 55 | this, SLOT( updateDrawUnder() )); 56 | 57 | resolution_property_ = new FloatProperty( "Resolution", 0, 58 | "Resolution of the map. (not editable)", this ); 59 | resolution_property_->setReadOnly( true ); 60 | 61 | width_property_ = new IntProperty( "Width", 0, 62 | "Width of the map, in meters. (not editable)", this ); 63 | width_property_->setReadOnly( true ); 64 | 65 | height_property_ = new IntProperty( "Height", 0, 66 | "Height of the map, in meters. (not editable)", this ); 67 | height_property_->setReadOnly( true ); 68 | 69 | position_property_ = new VectorProperty( "Position", Ogre::Vector3::ZERO, 70 | "Position of the bottom left corner of the map, in meters. (not editable)", 71 | this ); 72 | position_property_->setReadOnly( true ); 73 | 74 | orientation_property_ = new QuaternionProperty( "Orientation", Ogre::Quaternion::IDENTITY, 75 | "Orientation of the map. (not editable)", 76 | this ); 77 | orientation_property_->setReadOnly( true ); 78 | } 79 | 80 | AerialMapDisplay::~AerialMapDisplay() 81 | { 82 | unsubscribe(); 83 | clear(); 84 | } 85 | 86 | void AerialMapDisplay::onInitialize() 87 | { 88 | static int count = 0; 89 | std::stringstream ss; 90 | ss << "AerialMapObjectMaterial" << count++; 91 | material_ = Ogre::MaterialManager::getSingleton().create( ss.str(), 92 | Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); 93 | material_->setReceiveShadows(false); 94 | material_->getTechnique(0)->setLightingEnabled(false); 95 | material_->setDepthBias( -16.0f, 0.0f ); 96 | material_->setCullingMode( Ogre::CULL_NONE ); 97 | material_->setDepthWriteEnabled(false); 98 | 99 | updateAlpha(); 100 | } 101 | 102 | void AerialMapDisplay::onEnable() 103 | { 104 | subscribe(); 105 | } 106 | 107 | void AerialMapDisplay::onDisable() 108 | { 109 | unsubscribe(); 110 | clear(); 111 | } 112 | 113 | void AerialMapDisplay::subscribe() 114 | { 115 | if ( !isEnabled() ) 116 | { 117 | return; 118 | } 119 | 120 | if( !topic_property_->getTopic().isEmpty() ) 121 | { 122 | try 123 | { 124 | map_sub_ = update_nh_.subscribe( topic_property_->getTopicStd(), 1, &AerialMapDisplay::incomingAerialMap, this ); 125 | setStatus( StatusProperty::Ok, "Topic", "OK" ); 126 | } 127 | catch( ros::Exception& e ) 128 | { 129 | setStatus( StatusProperty::Error, "Topic", QString( "Error subscribing: " ) + e.what() ); 130 | } 131 | } 132 | } 133 | 134 | void AerialMapDisplay::unsubscribe() 135 | { 136 | map_sub_.shutdown(); 137 | } 138 | 139 | void AerialMapDisplay::updateAlpha() 140 | { 141 | float alpha = alpha_property_->getFloat(); 142 | 143 | Ogre::Pass* pass = material_->getTechnique( 0 )->getPass( 0 ); 144 | Ogre::TextureUnitState* tex_unit = NULL; 145 | if( pass->getNumTextureUnitStates() > 0 ) 146 | { 147 | tex_unit = pass->getTextureUnitState( 0 ); 148 | } 149 | else 150 | { 151 | tex_unit = pass->createTextureUnitState(); 152 | } 153 | 154 | tex_unit->setAlphaOperation( Ogre::LBX_SOURCE1, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, alpha ); 155 | 156 | if( alpha < 0.9998 ) 157 | { 158 | material_->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA ); 159 | material_->setDepthWriteEnabled( false ); 160 | } 161 | else 162 | { 163 | material_->setSceneBlending( Ogre::SBT_REPLACE ); 164 | material_->setDepthWriteEnabled( !draw_under_property_->getValue().toBool() ); 165 | } 166 | } 167 | 168 | void AerialMapDisplay::updateDrawUnder() 169 | { 170 | bool draw_under = draw_under_property_->getValue().toBool(); 171 | 172 | if( alpha_property_->getFloat() >= 0.9998 ) 173 | { 174 | material_->setDepthWriteEnabled( !draw_under ); 175 | } 176 | 177 | if( manual_object_ ) 178 | { 179 | if( draw_under ) 180 | { 181 | manual_object_->setRenderQueueGroup( Ogre::RENDER_QUEUE_4 ); 182 | } 183 | else 184 | { 185 | manual_object_->setRenderQueueGroup( Ogre::RENDER_QUEUE_MAIN ); 186 | } 187 | } 188 | } 189 | 190 | void AerialMapDisplay::updateTopic() 191 | { 192 | unsubscribe(); 193 | subscribe(); 194 | clear(); 195 | } 196 | 197 | void AerialMapDisplay::clear() 198 | { 199 | setStatus( StatusProperty::Warn, "Message", "No map received" ); 200 | 201 | if( !loaded_ ) 202 | { 203 | return; 204 | } 205 | 206 | scene_manager_->destroyManualObject( manual_object_ ); 207 | manual_object_ = NULL; 208 | 209 | std::string tex_name = texture_->getName(); 210 | texture_.setNull(); 211 | Ogre::TextureManager::getSingleton().unload( tex_name ); 212 | 213 | loaded_ = false; 214 | } 215 | /* 216 | bool validateFloats(const nav_msgs::OccupancyGrid& msg) 217 | { 218 | bool valid = true; 219 | valid = valid && validateFloats( msg.info.resolution ); 220 | valid = valid && validateFloats( msg.info.origin ); 221 | return valid; 222 | } 223 | */ 224 | void AerialMapDisplay::update( float wall_dt, float ros_dt ) 225 | { 226 | { 227 | boost::mutex::scoped_lock lock(mutex_); 228 | 229 | current_map_ = updated_map_; 230 | } 231 | 232 | if (!current_map_ || !new_map_) 233 | { 234 | return; 235 | } 236 | 237 | if (current_map_->data.empty()) 238 | { 239 | return; 240 | } 241 | 242 | new_map_ = false; 243 | 244 | if( current_map_->info.width * current_map_->info.height == 0 ) 245 | { 246 | std::stringstream ss; 247 | ss << "AerialMap is zero-sized (" << current_map_->info.width << "x" << current_map_->info.height << ")"; 248 | setStatus( StatusProperty::Error, "AerialMap", QString::fromStdString( ss.str() )); 249 | return; 250 | } 251 | 252 | clear(); 253 | 254 | setStatus( StatusProperty::Ok, "Message", "AerialMap received" ); 255 | 256 | ROS_DEBUG( "Received a %d X %d map @ %.3f m/pix\n", 257 | current_map_->info.width, 258 | current_map_->info.height, 259 | current_map_->info.resolution ); 260 | 261 | float resolution = current_map_->info.resolution; 262 | 263 | int width = current_map_->info.width; 264 | int height = current_map_->info.height; 265 | 266 | 267 | Ogre::Vector3 position( current_map_->info.origin.position.x, 268 | current_map_->info.origin.position.y, 269 | current_map_->info.origin.position.z ); 270 | Ogre::Quaternion orientation( current_map_->info.origin.orientation.w, 271 | current_map_->info.origin.orientation.x, 272 | current_map_->info.origin.orientation.y, 273 | current_map_->info.origin.orientation.z ); 274 | frame_ = current_map_->header.frame_id; 275 | if (frame_.empty()) 276 | { 277 | frame_ = "/map"; 278 | } 279 | 280 | // Expand it to be RGB data 281 | unsigned int pixels_size = width * height * 3; 282 | unsigned char* pixels = new unsigned char[pixels_size]; 283 | memset(pixels, 255, pixels_size); 284 | 285 | bool map_status_set = false; 286 | unsigned int num_pixels_to_copy = pixels_size; 287 | if( pixels_size != current_map_->data.size() ) 288 | { 289 | std::stringstream ss; 290 | ss << "Data size doesn't match width*height: width = " << width 291 | << ", height = " << height << ", data size = " << current_map_->data.size(); 292 | setStatus( StatusProperty::Error, "AerialMap", QString::fromStdString( ss.str() )); 293 | map_status_set = true; 294 | 295 | // Keep going, but don't read past the end of the data. 296 | if( current_map_->data.size() < pixels_size ) 297 | { 298 | num_pixels_to_copy = current_map_->data.size(); 299 | } 300 | } 301 | 302 | // TODO: a fragment shader could do this on the video card, and 303 | // would allow a non-grayscale color to mark the out-of-range 304 | // values. 305 | for( unsigned int pixel_index = 0; pixel_index < num_pixels_to_copy; pixel_index++ ) 306 | { 307 | /* 308 | unsigned char val; 309 | int8_t data = current_map_->data[ pixel_index ]; 310 | if(data > 0) 311 | val = 0; 312 | else if(data < 0) 313 | val = 255; 314 | else 315 | val = 127; 316 | pixels[ pixel_index ] = val; 317 | */ 318 | pixels[ pixel_index ] = current_map_->data[ pixel_index ]; 319 | } 320 | 321 | Ogre::DataStreamPtr pixel_stream; 322 | pixel_stream.bind( new Ogre::MemoryDataStream( pixels, pixels_size )); 323 | static int tex_count = 0; 324 | std::stringstream ss; 325 | ss << "AerialMapTexture" << tex_count++; 326 | try 327 | { 328 | texture_ = Ogre::TextureManager::getSingleton().loadRawData( ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 329 | pixel_stream, width, height, Ogre::PF_R8G8B8, Ogre::TEX_TYPE_2D, 330 | 0); 331 | 332 | if( !map_status_set ) 333 | { 334 | setStatus( StatusProperty::Ok, "AerialMap", "AerialMap OK" ); 335 | } 336 | } 337 | catch(Ogre::RenderingAPIException&) 338 | { 339 | Ogre::Image image; 340 | pixel_stream->seek(0); 341 | float fwidth = width; 342 | float fheight = height; 343 | if( width > height ) 344 | { 345 | float aspect = fheight / fwidth; 346 | fwidth = 2048; 347 | fheight = fwidth * aspect; 348 | } 349 | else 350 | { 351 | float aspect = fwidth / fheight; 352 | fheight = 2048; 353 | fwidth = fheight * aspect; 354 | } 355 | 356 | { 357 | std::stringstream ss; 358 | ss << "AerialMap is larger than your graphics card supports. Downsampled from [" << width << "x" << height << "] to [" << fwidth << "x" << fheight << "]"; 359 | setStatus(StatusProperty::Ok, "AerialMap", QString::fromStdString( ss.str() )); 360 | } 361 | 362 | ROS_WARN("Failed to create full-size map texture, likely because your graphics card does not support textures of size > 2048. Downsampling to [%d x %d]...", (int)fwidth, (int)fheight); 363 | 364 | image.loadRawData(pixel_stream, width, height, Ogre::PF_R8G8B8); 365 | image.resize(fwidth, fheight, Ogre::Image::FILTER_NEAREST); 366 | ss << "Downsampled"; 367 | texture_ = Ogre::TextureManager::getSingleton().loadImage(ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, image); 368 | } 369 | 370 | delete [] pixels; 371 | 372 | Ogre::Pass* pass = material_->getTechnique(0)->getPass(0); 373 | Ogre::TextureUnitState* tex_unit = NULL; 374 | if (pass->getNumTextureUnitStates() > 0) 375 | { 376 | tex_unit = pass->getTextureUnitState(0); 377 | } 378 | else 379 | { 380 | tex_unit = pass->createTextureUnitState(); 381 | } 382 | 383 | tex_unit->setTextureName(texture_->getName()); 384 | tex_unit->setTextureFiltering( Ogre::TFO_NONE ); 385 | 386 | static int map_count = 0; 387 | std::stringstream ss2; 388 | ss2 << "AerialMapObject" << map_count++; 389 | manual_object_ = scene_manager_->createManualObject( ss2.str() ); 390 | scene_node_->attachObject( manual_object_ ); 391 | 392 | manual_object_->begin(material_->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST); 393 | { 394 | 395 | { 396 | manual_object_->position( 0.0f, 0.0f, 0.0f ); 397 | manual_object_->textureCoord(0.0f, 0.0f); 398 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 399 | 400 | manual_object_->position( resolution*width, resolution*height, 0.0f ); 401 | manual_object_->textureCoord(1.0f, 1.0f); 402 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 403 | 404 | manual_object_->position( 0.0f, resolution*height, 0.0f ); 405 | manual_object_->textureCoord(0.0f, 1.0f); 406 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 407 | } 408 | 409 | { 410 | manual_object_->position( 0.0f, 0.0f, 0.0f ); 411 | manual_object_->textureCoord(0.0f, 0.0f); 412 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 413 | 414 | manual_object_->position( resolution*width, 0.0f, 0.0f ); 415 | manual_object_->textureCoord(1.0f, 0.0f); 416 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 417 | 418 | manual_object_->position( resolution*width, resolution*height, 0.0f ); 419 | manual_object_->textureCoord(1.0f, 1.0f); 420 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 421 | } 422 | } 423 | manual_object_->end(); 424 | 425 | if( draw_under_property_->getValue().toBool() ) 426 | { 427 | manual_object_->setRenderQueueGroup(Ogre::RENDER_QUEUE_4); 428 | } 429 | 430 | resolution_property_->setValue( resolution ); 431 | width_property_->setValue( width ); 432 | height_property_->setValue( height ); 433 | position_property_->setVector( position ); 434 | orientation_property_->setQuaternion( orientation ); 435 | 436 | transformAerialMap(); 437 | 438 | loaded_ = true; 439 | 440 | context_->queueRender(); 441 | } 442 | 443 | void AerialMapDisplay::incomingAerialMap(const nav_msgs::OccupancyGrid::ConstPtr& msg) 444 | { 445 | 446 | updated_map_ = msg; 447 | boost::mutex::scoped_lock lock(mutex_); 448 | new_map_ = true; 449 | } 450 | 451 | 452 | 453 | void AerialMapDisplay::transformAerialMap() 454 | { 455 | if (!current_map_) 456 | { 457 | return; 458 | } 459 | 460 | Ogre::Vector3 position; 461 | Ogre::Quaternion orientation; 462 | if (!context_->getFrameManager()->transform(frame_, ros::Time(), current_map_->info.origin, position, orientation)) 463 | { 464 | ROS_DEBUG( "Error transforming map '%s' from frame '%s' to frame '%s'", 465 | qPrintable( getName() ), frame_.c_str(), qPrintable( fixed_frame_ )); 466 | 467 | setStatus( StatusProperty::Error, "Transform", 468 | "No transform from [" + QString::fromStdString( frame_ ) + "] to [" + fixed_frame_ + "]" ); 469 | } 470 | else 471 | { 472 | setStatus(StatusProperty::Ok, "Transform", "Transform OK"); 473 | } 474 | 475 | scene_node_->setPosition( position ); 476 | scene_node_->setOrientation( orientation ); 477 | } 478 | 479 | void AerialMapDisplay::fixedFrameChanged() 480 | { 481 | transformAerialMap(); 482 | } 483 | 484 | void AerialMapDisplay::reset() 485 | { 486 | Display::reset(); 487 | 488 | clear(); 489 | 490 | updateTopic(); 491 | } 492 | 493 | } 494 | 495 | #include 496 | PLUGINLIB_EXPORT_CLASS( rviz::AerialMapDisplay, rviz::Display ) 497 | -------------------------------------------------------------------------------- /rviz_plugins/src/probmap_display.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include "rviz/frame_manager.h" 15 | #include "rviz/ogre_helpers/grid.h" 16 | #include "rviz/properties/float_property.h" 17 | #include "rviz/properties/int_property.h" 18 | #include "rviz/properties/property.h" 19 | #include "rviz/properties/quaternion_property.h" 20 | #include "rviz/properties/ros_topic_property.h" 21 | #include "rviz/properties/vector_property.h" 22 | #include "rviz/validate_floats.h" 23 | #include "rviz/display_context.h" 24 | 25 | #include "probmap_display.h" 26 | 27 | namespace rviz 28 | { 29 | 30 | ProbMapDisplay::ProbMapDisplay() 31 | : Display() 32 | , manual_object_( NULL ) 33 | 34 | , loaded_( false ) 35 | , resolution_( 0.0f ) 36 | , width_( 0 ) 37 | , height_( 0 ) 38 | , position_(Ogre::Vector3::ZERO) 39 | , orientation_(Ogre::Quaternion::IDENTITY) 40 | , new_map_(false) 41 | { 42 | topic_property_ = new RosTopicProperty( "Topic", "", 43 | QString::fromStdString( ros::message_traits::datatype() ), 44 | "nav_msgs::OccupancyGrid topic to subscribe to.", 45 | this, SLOT( updateTopic() )); 46 | 47 | alpha_property_ = new FloatProperty( "Alpha", 0.7, 48 | "Amount of transparency to apply to the map.", 49 | this, SLOT( updateAlpha() )); 50 | alpha_property_->setMin( 0 ); 51 | alpha_property_->setMax( 1 ); 52 | 53 | draw_under_property_ = new Property( "Draw Behind", false, 54 | "Rendering option, controls whether or not the map is always" 55 | " drawn behind everything else.", 56 | this, SLOT( updateDrawUnder() )); 57 | 58 | resolution_property_ = new FloatProperty( "Resolution", 0, 59 | "Resolution of the map. (not editable)", this ); 60 | resolution_property_->setReadOnly( true ); 61 | 62 | width_property_ = new IntProperty( "Width", 0, 63 | "Width of the map, in meters. (not editable)", this ); 64 | width_property_->setReadOnly( true ); 65 | 66 | height_property_ = new IntProperty( "Height", 0, 67 | "Height of the map, in meters. (not editable)", this ); 68 | height_property_->setReadOnly( true ); 69 | 70 | position_property_ = new VectorProperty( "Position", Ogre::Vector3::ZERO, 71 | "Position of the bottom left corner of the map, in meters. (not editable)", 72 | this ); 73 | position_property_->setReadOnly( true ); 74 | 75 | orientation_property_ = new QuaternionProperty( "Orientation", Ogre::Quaternion::IDENTITY, 76 | "Orientation of the map. (not editable)", 77 | this ); 78 | orientation_property_->setReadOnly( true ); 79 | } 80 | 81 | ProbMapDisplay::~ProbMapDisplay() 82 | { 83 | unsubscribe(); 84 | clear(); 85 | } 86 | 87 | void ProbMapDisplay::onInitialize() 88 | { 89 | static int count = 0; 90 | std::stringstream ss; 91 | ss << "MapObjectMaterial" << count++; 92 | material_ = Ogre::MaterialManager::getSingleton().create( ss.str(), 93 | Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); 94 | material_->setReceiveShadows(false); 95 | material_->getTechnique(0)->setLightingEnabled(false); 96 | material_->setDepthBias( -16.0f, 0.0f ); 97 | material_->setCullingMode( Ogre::CULL_NONE ); 98 | material_->setDepthWriteEnabled(false); 99 | 100 | updateAlpha(); 101 | } 102 | 103 | void ProbMapDisplay::onEnable() 104 | { 105 | subscribe(); 106 | } 107 | 108 | void ProbMapDisplay::onDisable() 109 | { 110 | unsubscribe(); 111 | clear(); 112 | } 113 | 114 | void ProbMapDisplay::subscribe() 115 | { 116 | if ( !isEnabled() ) 117 | { 118 | return; 119 | } 120 | 121 | if( !topic_property_->getTopic().isEmpty() ) 122 | { 123 | try 124 | { 125 | map_sub_ = update_nh_.subscribe( topic_property_->getTopicStd(), 1, &ProbMapDisplay::incomingMap, this ); 126 | setStatus( StatusProperty::Ok, "Topic", "OK" ); 127 | } 128 | catch( ros::Exception& e ) 129 | { 130 | setStatus( StatusProperty::Error, "Topic", QString( "Error subscribing: " ) + e.what() ); 131 | } 132 | } 133 | } 134 | 135 | void ProbMapDisplay::unsubscribe() 136 | { 137 | map_sub_.shutdown(); 138 | } 139 | 140 | void ProbMapDisplay::updateAlpha() 141 | { 142 | float alpha = alpha_property_->getFloat(); 143 | 144 | Ogre::Pass* pass = material_->getTechnique( 0 )->getPass( 0 ); 145 | Ogre::TextureUnitState* tex_unit = NULL; 146 | if( pass->getNumTextureUnitStates() > 0 ) 147 | { 148 | tex_unit = pass->getTextureUnitState( 0 ); 149 | } 150 | else 151 | { 152 | tex_unit = pass->createTextureUnitState(); 153 | } 154 | 155 | tex_unit->setAlphaOperation( Ogre::LBX_SOURCE1, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, alpha ); 156 | 157 | if( alpha < 0.9998 ) 158 | { 159 | material_->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA ); 160 | material_->setDepthWriteEnabled( false ); 161 | } 162 | else 163 | { 164 | material_->setSceneBlending( Ogre::SBT_REPLACE ); 165 | material_->setDepthWriteEnabled( !draw_under_property_->getValue().toBool() ); 166 | } 167 | } 168 | 169 | void ProbMapDisplay::updateDrawUnder() 170 | { 171 | bool draw_under = draw_under_property_->getValue().toBool(); 172 | 173 | if( alpha_property_->getFloat() >= 0.9998 ) 174 | { 175 | material_->setDepthWriteEnabled( !draw_under ); 176 | } 177 | 178 | if( manual_object_ ) 179 | { 180 | if( draw_under ) 181 | { 182 | manual_object_->setRenderQueueGroup( Ogre::RENDER_QUEUE_4 ); 183 | } 184 | else 185 | { 186 | manual_object_->setRenderQueueGroup( Ogre::RENDER_QUEUE_MAIN ); 187 | } 188 | } 189 | } 190 | 191 | void ProbMapDisplay::updateTopic() 192 | { 193 | unsubscribe(); 194 | subscribe(); 195 | clear(); 196 | } 197 | 198 | void ProbMapDisplay::clear() 199 | { 200 | setStatus( StatusProperty::Warn, "Message", "No map received" ); 201 | 202 | if( !loaded_ ) 203 | { 204 | return; 205 | } 206 | 207 | scene_manager_->destroyManualObject( manual_object_ ); 208 | manual_object_ = NULL; 209 | 210 | std::string tex_name = texture_->getName(); 211 | texture_.setNull(); 212 | Ogre::TextureManager::getSingleton().unload( tex_name ); 213 | 214 | loaded_ = false; 215 | } 216 | 217 | bool validateFloats(const nav_msgs::OccupancyGrid& msg) 218 | { 219 | bool valid = true; 220 | valid = valid && validateFloats( msg.info.resolution ); 221 | valid = valid && validateFloats( msg.info.origin ); 222 | return valid; 223 | } 224 | 225 | void ProbMapDisplay::update( float wall_dt, float ros_dt ) 226 | { 227 | { 228 | boost::mutex::scoped_lock lock(mutex_); 229 | 230 | current_map_ = updated_map_; 231 | } 232 | 233 | if (!current_map_ || !new_map_) 234 | { 235 | return; 236 | } 237 | 238 | if (current_map_->data.empty()) 239 | { 240 | return; 241 | } 242 | 243 | new_map_ = false; 244 | 245 | if( !validateFloats( *current_map_ )) 246 | { 247 | setStatus( StatusProperty::Error, "Map", "Message contained invalid floating point values (nans or infs)" ); 248 | return; 249 | } 250 | 251 | if( current_map_->info.width * current_map_->info.height == 0 ) 252 | { 253 | std::stringstream ss; 254 | ss << "Map is zero-sized (" << current_map_->info.width << "x" << current_map_->info.height << ")"; 255 | setStatus( StatusProperty::Error, "Map", QString::fromStdString( ss.str() )); 256 | return; 257 | } 258 | 259 | clear(); 260 | 261 | setStatus( StatusProperty::Ok, "Message", "Map received" ); 262 | 263 | ROS_DEBUG( "Received a %d X %d map @ %.3f m/pix\n", 264 | current_map_->info.width, 265 | current_map_->info.height, 266 | current_map_->info.resolution ); 267 | 268 | float resolution = current_map_->info.resolution; 269 | 270 | int width = current_map_->info.width; 271 | int height = current_map_->info.height; 272 | 273 | 274 | Ogre::Vector3 position( current_map_->info.origin.position.x, 275 | current_map_->info.origin.position.y, 276 | current_map_->info.origin.position.z ); 277 | Ogre::Quaternion orientation( current_map_->info.origin.orientation.w, 278 | current_map_->info.origin.orientation.x, 279 | current_map_->info.origin.orientation.y, 280 | current_map_->info.origin.orientation.z ); 281 | frame_ = current_map_->header.frame_id; 282 | if (frame_.empty()) 283 | { 284 | frame_ = "/map"; 285 | } 286 | 287 | // Expand it to be RGB data 288 | unsigned int pixels_size = width * height; 289 | unsigned char* pixels = new unsigned char[pixels_size]; 290 | memset(pixels, 255, pixels_size); 291 | 292 | bool map_status_set = false; 293 | unsigned int num_pixels_to_copy = pixels_size; 294 | if( pixels_size != current_map_->data.size() ) 295 | { 296 | std::stringstream ss; 297 | ss << "Data size doesn't match width*height: width = " << width 298 | << ", height = " << height << ", data size = " << current_map_->data.size(); 299 | setStatus( StatusProperty::Error, "Map", QString::fromStdString( ss.str() )); 300 | map_status_set = true; 301 | 302 | // Keep going, but don't read past the end of the data. 303 | if( current_map_->data.size() < pixels_size ) 304 | { 305 | num_pixels_to_copy = current_map_->data.size(); 306 | } 307 | } 308 | 309 | // TODO: a fragment shader could do this on the video card, and 310 | // would allow a non-grayscale color to mark the out-of-range 311 | // values. 312 | for( unsigned int pixel_index = 0; pixel_index < num_pixels_to_copy; pixel_index++ ) 313 | { 314 | unsigned char val; 315 | int8_t data = current_map_->data[ pixel_index ]; 316 | if(data > 0) 317 | val = 0; 318 | else if(data < 0) 319 | val = 255; 320 | else 321 | val = 127; 322 | pixels[ pixel_index ] = val; 323 | } 324 | 325 | Ogre::DataStreamPtr pixel_stream; 326 | pixel_stream.bind( new Ogre::MemoryDataStream( pixels, pixels_size )); 327 | static int tex_count = 0; 328 | std::stringstream ss; 329 | ss << "MapTexture" << tex_count++; 330 | try 331 | { 332 | texture_ = Ogre::TextureManager::getSingleton().loadRawData( ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 333 | pixel_stream, width, height, Ogre::PF_L8, Ogre::TEX_TYPE_2D, 334 | 0); 335 | 336 | if( !map_status_set ) 337 | { 338 | setStatus( StatusProperty::Ok, "Map", "Map OK" ); 339 | } 340 | } 341 | catch(Ogre::RenderingAPIException&) 342 | { 343 | Ogre::Image image; 344 | pixel_stream->seek(0); 345 | float fwidth = width; 346 | float fheight = height; 347 | if( width > height ) 348 | { 349 | float aspect = fheight / fwidth; 350 | fwidth = 2048; 351 | fheight = fwidth * aspect; 352 | } 353 | else 354 | { 355 | float aspect = fwidth / fheight; 356 | fheight = 2048; 357 | fwidth = fheight * aspect; 358 | } 359 | 360 | { 361 | std::stringstream ss; 362 | ss << "Map is larger than your graphics card supports. Downsampled from [" << width << "x" << height << "] to [" << fwidth << "x" << fheight << "]"; 363 | setStatus(StatusProperty::Ok, "Map", QString::fromStdString( ss.str() )); 364 | } 365 | 366 | ROS_WARN("Failed to create full-size map texture, likely because your graphics card does not support textures of size > 2048. Downsampling to [%d x %d]...", (int)fwidth, (int)fheight); 367 | //ROS_INFO("Stream size [%d], width [%f], height [%f], w * h [%f]", pixel_stream->size(), width, height, width * height); 368 | image.loadRawData(pixel_stream, width, height, Ogre::PF_L8); 369 | image.resize(fwidth, fheight, Ogre::Image::FILTER_NEAREST); 370 | ss << "Downsampled"; 371 | texture_ = Ogre::TextureManager::getSingleton().loadImage(ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, image); 372 | } 373 | 374 | delete [] pixels; 375 | 376 | Ogre::Pass* pass = material_->getTechnique(0)->getPass(0); 377 | Ogre::TextureUnitState* tex_unit = NULL; 378 | if (pass->getNumTextureUnitStates() > 0) 379 | { 380 | tex_unit = pass->getTextureUnitState(0); 381 | } 382 | else 383 | { 384 | tex_unit = pass->createTextureUnitState(); 385 | } 386 | 387 | tex_unit->setTextureName(texture_->getName()); 388 | tex_unit->setTextureFiltering( Ogre::TFO_NONE ); 389 | 390 | static int map_count = 0; 391 | std::stringstream ss2; 392 | ss2 << "MapObject" << map_count++; 393 | manual_object_ = scene_manager_->createManualObject( ss2.str() ); 394 | scene_node_->attachObject( manual_object_ ); 395 | 396 | manual_object_->begin(material_->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST); 397 | { 398 | 399 | { 400 | manual_object_->position( 0.0f, 0.0f, 0.0f ); 401 | manual_object_->textureCoord(0.0f, 0.0f); 402 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 403 | 404 | manual_object_->position( resolution*width, resolution*height, 0.0f ); 405 | manual_object_->textureCoord(1.0f, 1.0f); 406 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 407 | 408 | manual_object_->position( 0.0f, resolution*height, 0.0f ); 409 | manual_object_->textureCoord(0.0f, 1.0f); 410 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 411 | } 412 | 413 | { 414 | manual_object_->position( 0.0f, 0.0f, 0.0f ); 415 | manual_object_->textureCoord(0.0f, 0.0f); 416 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 417 | 418 | manual_object_->position( resolution*width, 0.0f, 0.0f ); 419 | manual_object_->textureCoord(1.0f, 0.0f); 420 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 421 | 422 | manual_object_->position( resolution*width, resolution*height, 0.0f ); 423 | manual_object_->textureCoord(1.0f, 1.0f); 424 | manual_object_->normal( 0.0f, 0.0f, 1.0f ); 425 | } 426 | } 427 | manual_object_->end(); 428 | 429 | if( draw_under_property_->getValue().toBool() ) 430 | { 431 | manual_object_->setRenderQueueGroup(Ogre::RENDER_QUEUE_4); 432 | } 433 | 434 | resolution_property_->setValue( resolution ); 435 | width_property_->setValue( width ); 436 | height_property_->setValue( height ); 437 | position_property_->setVector( position ); 438 | orientation_property_->setQuaternion( orientation ); 439 | 440 | transformMap(); 441 | 442 | loaded_ = true; 443 | 444 | context_->queueRender(); 445 | } 446 | 447 | void ProbMapDisplay::incomingMap(const nav_msgs::OccupancyGrid::ConstPtr& msg) 448 | { 449 | 450 | updated_map_ = msg; 451 | boost::mutex::scoped_lock lock(mutex_); 452 | new_map_ = true; 453 | } 454 | 455 | 456 | 457 | void ProbMapDisplay::transformMap() 458 | { 459 | if (!current_map_) 460 | { 461 | return; 462 | } 463 | 464 | Ogre::Vector3 position; 465 | Ogre::Quaternion orientation; 466 | if (!context_->getFrameManager()->transform(frame_, ros::Time(), current_map_->info.origin, position, orientation)) 467 | { 468 | ROS_DEBUG( "Error transforming map '%s' from frame '%s' to frame '%s'", 469 | qPrintable( getName() ), frame_.c_str(), qPrintable( fixed_frame_ )); 470 | 471 | setStatus( StatusProperty::Error, "Transform", 472 | "No transform from [" + QString::fromStdString( frame_ ) + "] to [" + fixed_frame_ + "]" ); 473 | } 474 | else 475 | { 476 | setStatus(StatusProperty::Ok, "Transform", "Transform OK"); 477 | } 478 | 479 | scene_node_->setPosition( position ); 480 | scene_node_->setOrientation( orientation ); 481 | } 482 | 483 | void ProbMapDisplay::fixedFrameChanged() 484 | { 485 | transformMap(); 486 | } 487 | 488 | void ProbMapDisplay::reset() 489 | { 490 | Display::reset(); 491 | 492 | clear(); 493 | 494 | } 495 | 496 | } 497 | 498 | #include 499 | PLUGINLIB_EXPORT_CLASS( rviz::ProbMapDisplay, rviz::Display ) 500 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------