Add files
This commit is contained in:
parent
bcfaacd194
commit
a8c94b93eb
851 changed files with 74204 additions and 0 deletions
|
@ -0,0 +1,223 @@
|
|||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(control_turtlebot)
|
||||
|
||||
## Find catkin macros and libraries
|
||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
||||
## is used, also find other catkin packages
|
||||
find_package(catkin REQUIRED COMPONENTS
|
||||
roscpp
|
||||
rospy
|
||||
std_msgs
|
||||
geometry_msgs
|
||||
message_generation
|
||||
laser_geometry
|
||||
tf
|
||||
roslib
|
||||
)
|
||||
|
||||
## System dependencies are found with CMake's conventions
|
||||
find_package(Boost REQUIRED COMPONENTS system)
|
||||
#find_package(Eigen3 REQUIRED)
|
||||
#find_package(PCL REQUIRED)
|
||||
find_package(Octomap)
|
||||
find_package(OMPL REQUIRED)
|
||||
|
||||
## Uncomment this if the package has a setup.py. This macro ensures
|
||||
## modules and global scripts declared therein get installed
|
||||
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
|
||||
# catkin_python_setup()
|
||||
|
||||
################################################
|
||||
## Declare ROS messages, services and actions ##
|
||||
################################################
|
||||
|
||||
## To declare and build messages, services or actions from within this
|
||||
## package, follow these steps:
|
||||
## * Let MSG_DEP_SET be the set of packages whose message types you use in
|
||||
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
|
||||
## * In the file package.xml:
|
||||
## * add a build_depend tag for "message_generation"
|
||||
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
|
||||
## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
|
||||
## but can be declared for certainty nonetheless:
|
||||
## * add a run_depend tag for "message_runtime"
|
||||
## * In this file (CMakeLists.txt):
|
||||
## * add "message_generation" and every package in MSG_DEP_SET to
|
||||
## find_package(catkin REQUIRED COMPONENTS ...)
|
||||
## * add "message_runtime" and every package in MSG_DEP_SET to
|
||||
## catkin_package(CATKIN_DEPENDS ...)
|
||||
## * uncomment the add_*_files sections below as needed
|
||||
## and list every .msg/.srv/.action file to be processed
|
||||
## * uncomment the generate_messages entry below
|
||||
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
|
||||
|
||||
## Generate messages in the 'msg' folder
|
||||
# add_message_files(
|
||||
# FILES
|
||||
# Message1.msg
|
||||
# Message2.msg
|
||||
# )
|
||||
|
||||
## Generate services in the 'srv' folder
|
||||
add_service_files(
|
||||
FILES
|
||||
GotoWaypoint.srv
|
||||
FindPathToGoal.srv
|
||||
)
|
||||
|
||||
## Generate actions in the 'action' folder
|
||||
# add_action_files(
|
||||
# FILES
|
||||
# Action1.action
|
||||
# Action2.action
|
||||
# )
|
||||
|
||||
## Generate added messages and services with any dependencies listed here
|
||||
generate_messages(
|
||||
DEPENDENCIES
|
||||
std_msgs geometry_msgs
|
||||
)
|
||||
|
||||
################################################
|
||||
## Declare ROS dynamic reconfigure parameters ##
|
||||
################################################
|
||||
|
||||
## To declare and build dynamic reconfigure parameters within this
|
||||
## package, follow these steps:
|
||||
## * In the file package.xml:
|
||||
## * add a build_depend and a run_depend tag for "dynamic_reconfigure"
|
||||
## * In this file (CMakeLists.txt):
|
||||
## * add "dynamic_reconfigure" to
|
||||
## find_package(catkin REQUIRED COMPONENTS ...)
|
||||
## * uncomment the "generate_dynamic_reconfigure_options" section below
|
||||
## and list every .cfg file to be processed
|
||||
|
||||
## Generate dynamic reconfigure parameters in the 'cfg' folder
|
||||
# generate_dynamic_reconfigure_options(
|
||||
# cfg/DynReconf1.cfg
|
||||
# cfg/DynReconf2.cfg
|
||||
# )
|
||||
|
||||
###################################
|
||||
## catkin specific configuration ##
|
||||
###################################
|
||||
## The catkin_package macro generates cmake config files for your package
|
||||
## Declare things to be passed to dependent projects
|
||||
## INCLUDE_DIRS: uncomment this if you package contains header files
|
||||
## LIBRARIES: libraries you create in this project that dependent projects also need
|
||||
## CATKIN_DEPENDS: catkin_packages dependent projects also need
|
||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
||||
catkin_package(
|
||||
# INCLUDE_DIRS include
|
||||
# LIBRARIES control_turtlebot
|
||||
CATKIN_DEPENDS roscpp rospy std_msgs
|
||||
# DEPENDS system_lib
|
||||
# DEPENDS Eigen
|
||||
)
|
||||
|
||||
###########
|
||||
## Build ##
|
||||
###########
|
||||
|
||||
## Specify additional locations of header files
|
||||
## Your package locations should be listed before other locations
|
||||
# include_directories(include)
|
||||
include_directories(
|
||||
${catkin_INCLUDE_DIRS}
|
||||
# ${Eigen_INCLUDE_DIRS}
|
||||
${OMPL_INCLUDE_DIRS}
|
||||
# ${PCL_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
#add_definitions(${EIGEN_DEFINITIONS})
|
||||
|
||||
## Declare a C++ library
|
||||
# add_library(control_turtlebot
|
||||
# src/${PROJECT_NAME}/control_turtlebot.cpp
|
||||
# )
|
||||
|
||||
## Add cmake target dependencies of the library
|
||||
## as an example, code may need to be generated before libraries
|
||||
## either from message generation or dynamic reconfigure
|
||||
# add_dependencies(control_turtlebot ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
## Declare a C++ executable
|
||||
# add_executable(control_turtlebot_node src/control_turtlebot_node.cpp)
|
||||
|
||||
add_executable(laserscan_to_pointcloud src/laserscan_to_pointcloud.cpp)
|
||||
target_link_libraries(laserscan_to_pointcloud ${catkin_LIBRARIES} ${Eigen_LIBRARIES} )
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g")
|
||||
|
||||
add_executable(HelloWorld
|
||||
src/OMPL_Planning/HelloWorld/Hello_World.cpp
|
||||
src/OMPL_Planning/OMPL_Planner/OMPL_Planner.cpp
|
||||
src/OMPL_Planning/OMPL_Planner/StateChecker.cpp
|
||||
)
|
||||
target_link_libraries(HelloWorld ${catkin_LIBRARIES} ${catkin_LIBRARIES} ${Boost_LIBRARIES} ${CCD_LIBRARIES} ${OCTOMAP_LIBRARIES} ${OMPL_LIBRARIES})
|
||||
|
||||
add_executable(Planning_Node
|
||||
src/OMPL_Planning/ROS_Implementation/ROS_Planning_Node.cpp
|
||||
src/OMPL_Planning/ROS_Implementation/ROS_OMPL_Planner.cpp
|
||||
src/OMPL_Planning/OMPL_Planner/OMPL_Planner.cpp
|
||||
src/OMPL_Planning/OMPL_Planner/StateChecker.cpp
|
||||
)
|
||||
target_link_libraries(Planning_Node ${catkin_LIBRARIES} ${catkin_LIBRARIES} ${Boost_LIBRARIES} ${CCD_LIBRARIES} ${OCTOMAP_LIBRARIES} ${OMPL_LIBRARIES})
|
||||
add_dependencies(Planning_Node auv_msgs_generate_messages_cpp)
|
||||
|
||||
## Add cmake target dependencies of the executable
|
||||
## same as for the library above
|
||||
# add_dependencies(control_turtlebot_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
|
||||
|
||||
## Specify libraries to link a library or executable target against
|
||||
# target_link_libraries(control_turtlebot_node
|
||||
# ${catkin_LIBRARIES}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Install ##
|
||||
#############
|
||||
|
||||
# all install targets should use catkin DESTINATION variables
|
||||
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
|
||||
|
||||
## Mark executable scripts (Python etc.) for installation
|
||||
## in contrast to setup.py, you can choose the destination
|
||||
# install(PROGRAMS
|
||||
# scripts/my_python_script
|
||||
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark executables and/or libraries for installation
|
||||
# install(TARGETS control_turtlebot control_turtlebot_node
|
||||
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark cpp header files for installation
|
||||
# install(DIRECTORY include/${PROJECT_NAME}/
|
||||
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
|
||||
# FILES_MATCHING PATTERN "*.h"
|
||||
# PATTERN ".svn" EXCLUDE
|
||||
# )
|
||||
|
||||
## Mark other files for installation (e.g. launch and bag files, etc.)
|
||||
# install(FILES
|
||||
# # myfile1
|
||||
# # myfile2
|
||||
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Testing ##
|
||||
#############
|
||||
|
||||
## Add gtest based cpp test target and link libraries
|
||||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_control_turtlebot.cpp)
|
||||
# if(TARGET ${PROJECT_NAME}-test)
|
||||
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
|
||||
# endif()
|
||||
|
||||
## Add folders to be run by python nosetests
|
||||
# catkin_add_nosetests(test)
|
|
@ -0,0 +1,16 @@
|
|||
planning_dimension : "2D" # available dimension (2D,3D)
|
||||
planner_name : "CForest" # available planners (CForest, RRTstar)
|
||||
solving_time : 5.0 # available computation time to attempt to solve the query
|
||||
|
||||
#Configuration Space (C-Space) boundaries
|
||||
planning_bounds_x : [-15, 15]
|
||||
planning_bounds_y : [-15, 15]
|
||||
planning_bounds_z : [0, 15]
|
||||
|
||||
planning_depth_limit : 1
|
||||
|
||||
#Collision Mask
|
||||
collision_mask_x : 0.5
|
||||
collision_mask_y : 0.5
|
||||
collision_mask_z_2D : 0.2
|
||||
collision_mask_z_3D : 0.5
|
|
@ -0,0 +1,510 @@
|
|||
Panels:
|
||||
- Class: rviz/Displays
|
||||
Help Height: 81
|
||||
Name: Displays
|
||||
Property Tree Widget:
|
||||
Expanded:
|
||||
- /Global Options1
|
||||
- /TF1/Tree1
|
||||
- /TF2/Frames1
|
||||
Splitter Ratio: 0.5
|
||||
Tree Height: 409
|
||||
- Class: rviz/Selection
|
||||
Name: Selection
|
||||
- Class: rviz/Tool Properties
|
||||
Expanded:
|
||||
- /2D Pose Estimate1
|
||||
- /2D Nav Goal1
|
||||
Name: Tool Properties
|
||||
Splitter Ratio: 0.588679
|
||||
- Class: rviz/Views
|
||||
Expanded:
|
||||
- /Current View1
|
||||
Name: Views
|
||||
Splitter Ratio: 0.5
|
||||
- Class: rviz/Time
|
||||
Experimental: false
|
||||
Name: Time
|
||||
SyncMode: 0
|
||||
SyncSource: ""
|
||||
Visualization Manager:
|
||||
Class: ""
|
||||
Displays:
|
||||
- Alpha: 0.5
|
||||
Cell Size: 1
|
||||
Class: rviz/Grid
|
||||
Color: 160; 160; 164
|
||||
Enabled: true
|
||||
Line Style:
|
||||
Line Width: 0.03
|
||||
Value: Lines
|
||||
Name: Grid
|
||||
Normal Cell Count: 0
|
||||
Offset:
|
||||
X: 0
|
||||
Y: 0
|
||||
Z: 0
|
||||
Plane: XY
|
||||
Plane Cell Count: 10
|
||||
Reference Frame: odom
|
||||
Value: true
|
||||
- Alpha: 1
|
||||
Class: rviz/RobotModel
|
||||
Collision Enabled: false
|
||||
Enabled: true
|
||||
Links:
|
||||
All Links Enabled: true
|
||||
Expand Joint Details: false
|
||||
Expand Link Details: false
|
||||
Expand Tree: false
|
||||
Link Tree Style: Links in Alphabetic Order
|
||||
base_footprint:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
base_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
camera_depth_frame:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
camera_depth_optical_frame:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
camera_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
camera_rgb_frame:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
camera_rgb_optical_frame:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
caster_back_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
caster_front_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
cliff_sensor_front_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
cliff_sensor_left_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
cliff_sensor_right_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
gyro_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
plate_bottom_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
plate_middle_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
plate_top_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_bottom_0_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_bottom_1_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_bottom_2_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_bottom_3_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_bottom_4_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_bottom_5_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_kinect_0_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_kinect_1_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_middle_0_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_middle_1_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_middle_2_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_middle_3_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_top_0_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_top_1_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_top_2_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
pole_top_3_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
wheel_left_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
wheel_right_link:
|
||||
Alpha: 1
|
||||
Show Axes: false
|
||||
Show Trail: false
|
||||
Value: true
|
||||
Name: RobotModel
|
||||
Robot Description: robot_description
|
||||
TF Prefix: ""
|
||||
Update Interval: 0
|
||||
Value: true
|
||||
Visual Enabled: true
|
||||
- Class: rviz/TF
|
||||
Enabled: false
|
||||
Frame Timeout: 15
|
||||
Frames:
|
||||
All Enabled: true
|
||||
Marker Scale: 1
|
||||
Name: TF
|
||||
Show Arrows: true
|
||||
Show Axes: true
|
||||
Show Names: true
|
||||
Tree:
|
||||
{}
|
||||
Update Interval: 0
|
||||
Value: false
|
||||
- Alpha: 1
|
||||
Autocompute Intensity Bounds: true
|
||||
Autocompute Value Bounds:
|
||||
Max Value: 0.2972
|
||||
Min Value: 0.2972
|
||||
Value: true
|
||||
Axis: Z
|
||||
Channel Name: intensity
|
||||
Class: rviz/LaserScan
|
||||
Color: 255; 255; 255
|
||||
Color Transformer: AxisColor
|
||||
Decay Time: 0
|
||||
Enabled: false
|
||||
Invert Rainbow: false
|
||||
Max Color: 255; 255; 255
|
||||
Max Intensity: 4096
|
||||
Min Color: 0; 0; 0
|
||||
Min Intensity: 0
|
||||
Name: LaserScan
|
||||
Position Transformer: XYZ
|
||||
Queue Size: 10
|
||||
Selectable: true
|
||||
Size (Pixels): 3
|
||||
Size (m): 0.01
|
||||
Style: Squares
|
||||
Topic: /scan
|
||||
Use Fixed Frame: true
|
||||
Use rainbow: true
|
||||
Value: false
|
||||
- Alpha: 1
|
||||
Auto Size:
|
||||
Auto Size Factor: 1
|
||||
Value: true
|
||||
Autocompute Intensity Bounds: true
|
||||
Autocompute Value Bounds:
|
||||
Max Value: 3.286
|
||||
Min Value: 0.683
|
||||
Value: true
|
||||
Axis: X
|
||||
Channel Name: intensity
|
||||
Class: rviz/DepthCloud
|
||||
Color: 255; 255; 255
|
||||
Color Image Topic: ""
|
||||
Color Transformer: AxisColor
|
||||
Color Transport Hint: raw
|
||||
Decay Time: 0
|
||||
Depth Map Topic: /camera/depth/image_raw
|
||||
Depth Map Transport Hint: raw
|
||||
Enabled: false
|
||||
Invert Rainbow: false
|
||||
Max Color: 255; 255; 255
|
||||
Max Intensity: 4096
|
||||
Min Color: 0; 0; 0
|
||||
Min Intensity: 0
|
||||
Name: DepthCloud
|
||||
Occlusion Compensation:
|
||||
Occlusion Time-Out: 30
|
||||
Value: false
|
||||
Position Transformer: XYZ
|
||||
Queue Size: 5
|
||||
Selectable: true
|
||||
Size (Pixels): 3
|
||||
Style: Points
|
||||
Topic Filter: true
|
||||
Use Fixed Frame: true
|
||||
Use rainbow: true
|
||||
Value: false
|
||||
- Alpha: 1
|
||||
Auto Size:
|
||||
Auto Size Factor: 1
|
||||
Value: true
|
||||
Autocompute Intensity Bounds: true
|
||||
Autocompute Value Bounds:
|
||||
Max Value: 10
|
||||
Min Value: -10
|
||||
Value: true
|
||||
Axis: Z
|
||||
Channel Name: intensity
|
||||
Class: rviz/DepthCloud
|
||||
Color: 255; 255; 255
|
||||
Color Image Topic: /camera/rgb/image_color
|
||||
Color Transformer: RGB8
|
||||
Color Transport Hint: raw
|
||||
Decay Time: 0
|
||||
Depth Map Topic: /camera/depth_registered/image_raw
|
||||
Depth Map Transport Hint: raw
|
||||
Enabled: false
|
||||
Invert Rainbow: false
|
||||
Max Color: 255; 255; 255
|
||||
Max Intensity: 4096
|
||||
Min Color: 0; 0; 0
|
||||
Min Intensity: 0
|
||||
Name: Registered DepthCloud
|
||||
Occlusion Compensation:
|
||||
Occlusion Time-Out: 30
|
||||
Value: false
|
||||
Position Transformer: XYZ
|
||||
Queue Size: 5
|
||||
Selectable: true
|
||||
Size (Pixels): 3
|
||||
Style: Points
|
||||
Topic Filter: true
|
||||
Use Fixed Frame: true
|
||||
Use rainbow: true
|
||||
Value: false
|
||||
- Class: rviz/Image
|
||||
Enabled: false
|
||||
Image Topic: /camera/rgb/image_color
|
||||
Max Value: 1
|
||||
Median window: 5
|
||||
Min Value: 0
|
||||
Name: Image
|
||||
Normalize Range: true
|
||||
Queue Size: 2
|
||||
Transport Hint: raw
|
||||
Value: false
|
||||
- Alpha: 1
|
||||
Autocompute Intensity Bounds: true
|
||||
Autocompute Value Bounds:
|
||||
Max Value: 3.286
|
||||
Min Value: 0.681
|
||||
Value: true
|
||||
Axis: X
|
||||
Channel Name: intensity
|
||||
Class: rviz/PointCloud2
|
||||
Color: 255; 255; 255
|
||||
Color Transformer: AxisColor
|
||||
Decay Time: 0
|
||||
Enabled: false
|
||||
Invert Rainbow: false
|
||||
Max Color: 255; 255; 255
|
||||
Max Intensity: 4096
|
||||
Min Color: 0; 0; 0
|
||||
Min Intensity: 0
|
||||
Name: PointCloud
|
||||
Position Transformer: XYZ
|
||||
Queue Size: 10
|
||||
Selectable: true
|
||||
Size (Pixels): 3
|
||||
Size (m): 0.01
|
||||
Style: Points
|
||||
Topic: /camera/depth/points
|
||||
Use Fixed Frame: true
|
||||
Use rainbow: true
|
||||
Value: false
|
||||
- Alpha: 1
|
||||
Autocompute Intensity Bounds: true
|
||||
Autocompute Value Bounds:
|
||||
Max Value: 5.632
|
||||
Min Value: 0.65
|
||||
Value: true
|
||||
Axis: X
|
||||
Channel Name: intensity
|
||||
Class: rviz/PointCloud2
|
||||
Color: 255; 255; 255
|
||||
Color Transformer: RGB8
|
||||
Decay Time: 0
|
||||
Enabled: false
|
||||
Invert Rainbow: false
|
||||
Max Color: 255; 255; 255
|
||||
Max Intensity: 4096
|
||||
Min Color: 0; 0; 0
|
||||
Min Intensity: 0
|
||||
Name: Registered PointCloud
|
||||
Position Transformer: XYZ
|
||||
Queue Size: 10
|
||||
Selectable: true
|
||||
Size (Pixels): 3
|
||||
Size (m): 0.01
|
||||
Style: Points
|
||||
Topic: /camera/depth_registered/points
|
||||
Use Fixed Frame: true
|
||||
Use rainbow: true
|
||||
Value: false
|
||||
- Class: rviz/InteractiveMarkers
|
||||
Enable Transparency: true
|
||||
Enabled: false
|
||||
Name: InteractiveMarkers
|
||||
Show Axes: false
|
||||
Show Descriptions: true
|
||||
Show Visual Aids: false
|
||||
Update Topic: /turtlebot_marker_server/update
|
||||
Value: false
|
||||
- Class: rviz/MarkerArray
|
||||
Enabled: true
|
||||
Marker Topic: /occupied_cells_vis_array
|
||||
Name: Octomap
|
||||
Namespaces:
|
||||
{}
|
||||
Queue Size: 100
|
||||
Value: true
|
||||
- Class: rviz/Marker
|
||||
Enabled: true
|
||||
Marker Topic: /controller_turtlebot/solution_path
|
||||
Name: Planning Solution
|
||||
Namespaces:
|
||||
{}
|
||||
Queue Size: 100
|
||||
Value: true
|
||||
- Class: rviz/TF
|
||||
Enabled: false
|
||||
Frame Timeout: 15
|
||||
Frames:
|
||||
All Enabled: false
|
||||
Marker Scale: 1
|
||||
Name: TF
|
||||
Show Arrows: true
|
||||
Show Axes: true
|
||||
Show Names: true
|
||||
Tree:
|
||||
{}
|
||||
Update Interval: 0
|
||||
Value: false
|
||||
Enabled: true
|
||||
Global Options:
|
||||
Background Color: 48; 48; 48
|
||||
Fixed Frame: odom
|
||||
Frame Rate: 30
|
||||
Name: root
|
||||
Tools:
|
||||
- Class: rviz/MoveCamera
|
||||
- Class: rviz/Interact
|
||||
Hide Inactive Objects: true
|
||||
- Class: rviz/Select
|
||||
- Class: rviz/SetInitialPose
|
||||
Topic: /initialpose
|
||||
- Class: rviz/SetGoal
|
||||
Topic: /move_base_simple/goal
|
||||
Value: true
|
||||
Views:
|
||||
Current:
|
||||
Class: rviz/Orbit
|
||||
Distance: 7.04007
|
||||
Enable Stereo Rendering:
|
||||
Stereo Eye Separation: 0.06
|
||||
Stereo Focal Distance: 1
|
||||
Swap Stereo Eyes: false
|
||||
Value: false
|
||||
Focal Point:
|
||||
X: -0.102786
|
||||
Y: -0.0889391
|
||||
Z: 0.112978
|
||||
Name: Current View
|
||||
Near Clip Distance: 0.01
|
||||
Pitch: 0.584798
|
||||
Target Frame: <Fixed Frame>
|
||||
Value: Orbit (rviz)
|
||||
Yaw: 1.2554
|
||||
Saved: ~
|
||||
Window Geometry:
|
||||
Displays:
|
||||
collapsed: false
|
||||
Height: 625
|
||||
Hide Left Dock: false
|
||||
Hide Right Dock: false
|
||||
Image:
|
||||
collapsed: false
|
||||
QMainWindow State: 000000ff00000000fd0000000400000000000001950000022bfc0200000006fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000006400fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c00610079007301000000280000022b000000dd00fffffffb0000000a0049006d006100670065000000028d000000c60000001600ffffff000000010000010b00000294fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003300000294000000b000fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004a00000003efc0100000002fb0000000800540069006d00650000000000000004a0000002f600fffffffb0000000800540069006d00650100000000000004500000000000000000000003240000022b00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
|
||||
Selection:
|
||||
collapsed: false
|
||||
Time:
|
||||
collapsed: false
|
||||
Tool Properties:
|
||||
collapsed: false
|
||||
Views:
|
||||
collapsed: false
|
||||
Width: 1215
|
||||
X: 58
|
||||
Y: 24
|
|
@ -0,0 +1,17 @@
|
|||
<launch>
|
||||
<arg name="enable_octomap" value="true"/>
|
||||
<arg name="enable_goto_controller" value="false"/>
|
||||
|
||||
<group if="$(arg enable_octomap)">
|
||||
<node pkg="octomap_server" type="octomap_server_node" name="octomap_server" args=" " cwd="node" output="screen">
|
||||
<param name="frame_id" value="/odom" />
|
||||
<remap from="/cloud_in" to="/camera/depth/points" /> <!-- simulator -->
|
||||
<!--remap from="/cloud_in" to="/camera/depth_registered/points" /--> <!-- real turtlebot -->
|
||||
</node>
|
||||
</group>
|
||||
|
||||
<group if="$(arg enable_goto_controller)">
|
||||
<node pkg="control_turtlebot" type="controller_turtlebot.py" name="controller_turtlebot" respawn="true" output="screen" />
|
||||
</group>
|
||||
|
||||
</launch>
|
|
@ -0,0 +1,35 @@
|
|||
<launch>
|
||||
<arg name="enable_octomap" value="true"/>
|
||||
<arg name="enable_controller" value="true"/>
|
||||
|
||||
<arg name="enable_plannerV2" value="true"/>
|
||||
|
||||
<group if="$(arg enable_octomap)">
|
||||
<node pkg="octomap_server" type="octomap_server_node" name="octomap_server" args=" " cwd="node" output="screen">
|
||||
<param name="frame_id" value="/odom" />
|
||||
<!--remap from="/cloud_in" to="/pc_from_scan" /--> <!-- simulator -->
|
||||
<param name="resolution" value="0.05" />
|
||||
<param name="latch" value="True" />
|
||||
<param name="sensor_model/max_range" value="-1" /> <!-- -1 : unlimited -->
|
||||
<param name="sensor_model/hit" value="0.7" /> <!-- default value :0.7 -->
|
||||
<param name="sensor_model/miss" value="0.4" /> <!-- default value :0.4 -->
|
||||
|
||||
<param name="ground_filter/distance" value="0.04" /> <!-- default value :0.04 -->
|
||||
<param name="ground_filter/plane_distance" value="0.07" /> <!-- default value :0.07 -->
|
||||
<remap from="/cloud_in" to="/camera/depth/points" /> <!-- real turtlebot -->
|
||||
</node>
|
||||
</group>
|
||||
|
||||
<node pkg="control_turtlebot" type="laserscan_to_pointcloud" name="laserscan_to_pointcloud" respawn="true" output="screen" />
|
||||
|
||||
<group if="$(arg enable_controller)">
|
||||
<node pkg="control_turtlebot" type="controller_turtlebot.py" name="controller_turtlebot" respawn="true" output="screen" />
|
||||
</group>
|
||||
|
||||
<group if="$(arg enable_plannerV2)">
|
||||
<!-- OMPL planner -->
|
||||
<rosparam command="load" file="$(find control_turtlebot)/launch/config/planner_parameters.yaml" />
|
||||
<node pkg="control_turtlebot" type="Planning_Node" name="Planning_Node" output="screen" />
|
||||
</group>
|
||||
|
||||
</launch>
|
|
@ -0,0 +1,23 @@
|
|||
<launch>
|
||||
<arg name="enable_turtlebot_simulation" value="true"/>
|
||||
<arg name="enable_keyboard_teleoperation" value="true"/>
|
||||
<arg name="enable_rviz" value="true"/>
|
||||
|
||||
<group if="$(arg enable_turtlebot_simulation)">
|
||||
<include file="$(find turtlebot_gazebo)/launch/turtlebot_world.launch"/> <!-- other ROS distributions -->
|
||||
<!--include file="$(find turtlebot_gazebo)/launch/turtlebot_playground.launch"/--> <!-- ROS hydro -->
|
||||
|
||||
<group if="$(arg enable_rviz)">
|
||||
<include file="$(find control_turtlebot)/launch/view_robot.launch"/>
|
||||
</group>
|
||||
</group>
|
||||
<group unless="$(arg enable_turtlebot_simulation)">
|
||||
<include file="$(find turtlebot_bringup)/launch/minimal.launch"/>
|
||||
<include file="$(find turtlebot_bringup)/launch/3dsensor.launch"/>
|
||||
</group>
|
||||
|
||||
<group if="$(arg enable_keyboard_teleoperation)">
|
||||
<include file="$(find turtlebot_teleop)/launch/keyboard_teleop.launch">
|
||||
</include>
|
||||
</group>
|
||||
</launch>
|
|
@ -0,0 +1,7 @@
|
|||
<launch>
|
||||
<include file="$(find turtlebot_gazebo)/launch/turtlebot_world.launch">
|
||||
<arg name="world_file" value="$(find control_turtlebot)/worlds/willowgarage.world"/>
|
||||
</include>
|
||||
<include file="$(find turtlebot_teleop)/launch/keyboard_teleop.launch"/>
|
||||
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find control_turtlebot)/launch/config/robot.rviz"/>
|
||||
</launch>
|
|
@ -0,0 +1,6 @@
|
|||
<launch>
|
||||
<!-- Offline planner ompl -->
|
||||
<rosparam command="load" file="$(find control_turtlebot)/launch/config/tests_blocks.yaml" />
|
||||
<node pkg="control_turtlebot" type="tutorial_offline_planner_R2" name="tutorial_offline_planner_R2" output="screen" />
|
||||
|
||||
</launch>
|
|
@ -0,0 +1,8 @@
|
|||
<!--
|
||||
Used for visualising turtlebot in action.
|
||||
|
||||
It requires minimal.launch and optionally 3dsensor.launch to already be up and running.
|
||||
-->
|
||||
<launch>
|
||||
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find control_turtlebot)/launch/config/robot.rviz" />
|
||||
</launch>
|
|
@ -0,0 +1,7 @@
|
|||
trajectory/north: [8.7958369e-07, 8.7958369e-07, -1.0000000, -1.0000000]
|
||||
trajectory/east: [5.8188791e-07, 5.8188791e-07, -1.0000000, -1.0000000]
|
||||
trajectory/z: [0.0, 0.25000000, 0.25000000, 0.0]
|
||||
trajectory/altitude_mode: [False, False, False, False]
|
||||
trajectory/mode: 'los_cte'
|
||||
trajectory/time_out: 10
|
||||
trajectory/wait: [0.0, 0.0, 0.0, 0.0]
|
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<name>control_turtlebot</name>
|
||||
<version>0.0.0</version>
|
||||
<description>The control_turtlebot package</description>
|
||||
|
||||
<!-- One maintainer tag required, multiple allowed, one person per tag -->
|
||||
<!-- Example: -->
|
||||
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
|
||||
<maintainer email="juandhv@todo.todo">juandhv</maintainer>
|
||||
|
||||
|
||||
<!-- One license tag required, multiple allowed, one license per tag -->
|
||||
<!-- Commonly used license strings: -->
|
||||
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
|
||||
<license>TODO</license>
|
||||
|
||||
|
||||
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
|
||||
<!-- Optional attribute type can be: website, bugtracker, or repository -->
|
||||
<!-- Example: -->
|
||||
<!-- <url type="website">http://wiki.ros.org/control_turtlebot</url> -->
|
||||
|
||||
|
||||
<!-- Author tags are optional, mutiple are allowed, one per tag -->
|
||||
<!-- Authors do not have to be maintianers, but could be -->
|
||||
<!-- Example: -->
|
||||
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
|
||||
|
||||
|
||||
<!-- The *_depend tags are used to specify dependencies -->
|
||||
<!-- Dependencies can be catkin packages or system dependencies -->
|
||||
<!-- Examples: -->
|
||||
<!-- Use build_depend for packages you need at compile time: -->
|
||||
<build_depend>message_generation</build_depend>
|
||||
<!-- Use buildtool_depend for build tool packages: -->
|
||||
<!-- <buildtool_depend>catkin</buildtool_depend> -->
|
||||
<!-- Use run_depend for packages you need at runtime: -->
|
||||
<run_depend>message_runtime</run_depend>
|
||||
<!-- Use test_depend for packages you need only for testing: -->
|
||||
<!-- <test_depend>gtest</test_depend> -->
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
<build_depend>roscpp</build_depend>
|
||||
<build_depend>rospy</build_depend>
|
||||
<build_depend>std_msgs</build_depend>
|
||||
<build_depend>geometry_msgs</build_depend>
|
||||
<build_depend>tf</build_depend>
|
||||
<build_depend>laser_geometry</build_depend>
|
||||
<build_depend>roslib</build_depend>
|
||||
|
||||
<run_depend>roscpp</run_depend>
|
||||
<run_depend>rospy</run_depend>
|
||||
<run_depend>std_msgs</run_depend>
|
||||
<run_depend>geometry_msgs</run_depend>
|
||||
<run_depend>tf</run_depend>
|
||||
<run_depend>laser_geometry</run_depend>
|
||||
<run_depend>roslib</run_depend>
|
||||
|
||||
|
||||
|
||||
<!-- The export tag contains other, unspecified, tags -->
|
||||
<export>
|
||||
<!-- Other tools can request additional information be placed here -->
|
||||
|
||||
</export>
|
||||
</package>
|
|
@ -0,0 +1,219 @@
|
|||
/**
|
||||
* \file Hello_World.cpp
|
||||
* \author Harlé Antoine (antoine.h@flylab.io)
|
||||
* \date 7/2017 - 8/2017
|
||||
* \brief HelloWorld for OMPL_Planner class.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../OMPL_Planner/OMPL_Planner.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int planningDimension = 2, solvingTime = 5;
|
||||
std::string plannerName, mapFile;
|
||||
std::vector<double> start, goal, planning_bounds_x_, planning_bounds_y_, planning_bounds_z_;
|
||||
|
||||
planning_bounds_x_.resize(2);
|
||||
planning_bounds_y_.resize(2);
|
||||
planning_bounds_z_.resize(2);
|
||||
|
||||
cout<<"Path planning with OMPL version "<<OMPL_VERSION<<"\n";
|
||||
cout<<"Choose a dimension for planning 2D or 3D (default :"<<planningDimension<<") : ";
|
||||
cin >> planningDimension;
|
||||
|
||||
start.resize(planningDimension);
|
||||
goal.resize(planningDimension);
|
||||
|
||||
cout<<"Choose a planner (available planner : CForest, RRTstar) : ";
|
||||
cin >> plannerName;
|
||||
|
||||
OMPL_Planner planner(planningDimension);
|
||||
|
||||
planning_bounds_x_[0]=-15;
|
||||
planning_bounds_x_[1]=15;
|
||||
planning_bounds_y_[0]=-15;
|
||||
planning_bounds_y_[1]=15;
|
||||
planning_bounds_z_[0]=-15;
|
||||
planning_bounds_z_[1]=15;
|
||||
|
||||
if (planningDimension == 3)
|
||||
planner.setPlanningBounds(planning_bounds_x_, planning_bounds_y_, planning_bounds_z_);
|
||||
else
|
||||
planner.setPlanningBounds(planning_bounds_x_, planning_bounds_y_);
|
||||
|
||||
planner.setPlanningDepth();
|
||||
|
||||
planner.setPlanner(plannerName);
|
||||
|
||||
cout<<"Enter direction to the Octomap file (.bt file usually) : ";
|
||||
cin>> mapFile;
|
||||
planner.setStateChecker(mapFile,0.5,0.5,0.5);
|
||||
|
||||
cout<<"\n Planner initialization done !\n";
|
||||
|
||||
start[2]=0;
|
||||
goal[2]=0;
|
||||
|
||||
cout<<"Choose a start position (expecting "<< planningDimension <<" values) : ";
|
||||
if(planningDimension==2)
|
||||
cin>> start[0] >> start[1];
|
||||
else
|
||||
cin>> start[0] >> start[1] >> start[2];
|
||||
|
||||
cout<<"Choose a goal position (expecting "<< planningDimension <<" values) : ";
|
||||
if(planningDimension==2)
|
||||
cin>> goal[0] >> goal[1];
|
||||
else
|
||||
cin>> goal[0] >> goal[1] >> goal[2];
|
||||
|
||||
planner.setStartGoal(start,goal);
|
||||
|
||||
cout<<"Choose solving time (default :"<<solvingTime<<") : ";
|
||||
cin>> solvingTime;
|
||||
|
||||
//cout<<"Searching path from "<<start[0]<<" / "<<start[1]<<" / "<<start[2]<<" to "<<goal[0]<<" / "<<goal[1]<<" / "<<goal[2]<<"\n";
|
||||
|
||||
if(planner.findPath(solvingTime))
|
||||
{
|
||||
og::PathGeometric path = planner.getPath();
|
||||
path.print(cout);
|
||||
}
|
||||
else
|
||||
cout<<"\n No path found\n";
|
||||
|
||||
cout<<"Thanks for using this awsome Hello World !\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//// DOXYGEN DOC ////
|
||||
|
||||
/*! \mainpage Home page
|
||||
*
|
||||
* \section intro_sec Introduction
|
||||
*
|
||||
* This project regroup tools for path planning in 2D or in 3D using OMPL (http://ompl.kavrakilab.org/index.html).
|
||||
* It also include a ROS implementation for dynamic plannification.
|
||||
*
|
||||
* Work with Ubuntu 14.04 (and ROS Indigo) or with Ubuntu 16.04 (and ROS Kinetic).
|
||||
*
|
||||
* \section install_sec Installation
|
||||
*
|
||||
* \subsection step1 Step 1 : Workspace intialization
|
||||
*
|
||||
* Catkin Workspace :
|
||||
* mkdir -p ~/catkin_ws/src
|
||||
* cd ~/catkin_ws/src
|
||||
* catkin_init_workspace
|
||||
*
|
||||
* cd ~/catkin_ws/
|
||||
* catkin_make
|
||||
*
|
||||
* echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
|
||||
* source ~/.bashrc
|
||||
*
|
||||
* \subsection step2 Step 2 : Compilation
|
||||
*
|
||||
* It's possible to use the Turtlebot or the Hector Quadrotor (ROS Indigo only).
|
||||
*
|
||||
* \subsubsection ste2a Step 2a : Turtlebot
|
||||
*
|
||||
* Turtlebot dependencies :
|
||||
*
|
||||
* sudo apt-get install ros-kinetic-turtlebot* ros-kinetic-octomap* ros-kinetic-octovis
|
||||
*
|
||||
* or
|
||||
*
|
||||
* sudo apt-get install ros-indigo-turtlebot* ros-indigo-octomap* ros-indigo-octovis
|
||||
*
|
||||
* Turtlebot install :
|
||||
*
|
||||
* copy "mapping_planning_tutorial" folder (in Source Files directory) to "~/catkin_ws/src".
|
||||
*
|
||||
* cd ~/catkin_ws/
|
||||
*
|
||||
* catkin_make (mignt need to be performed multiple times if you have error messages with "FindPathToGoal". Warning : it's possible that you won't manage to compile if you don't have enough computation power)
|
||||
*
|
||||
* \subsubsection ste2b Step 2b : Hector Quadrotor (ROS Indigo only) WARNING : There might need some modification for the package path to make it work
|
||||
*
|
||||
* copy "hector_quadrotor_tutorial" folder (in Source Files directory) to "~/catkin_ws/src".
|
||||
*
|
||||
* Differences with Turtlebot
|
||||
*
|
||||
* Launch file : start_turtlebot_mapping_planning_control.launch
|
||||
*
|
||||
* "/odom" ===> "/world"
|
||||
*
|
||||
* <node pkg="control_turtlebot" type="controller_turtlebot.py" name="controller_turtlebot" respawn="true" output="screen" /> ===> <node pkg="control_turtlebot" type="controller_quadrotor.py" name="controller_quadrotor" respawn="true" output="screen" />
|
||||
*
|
||||
*
|
||||
* ROS_OMPL_Planner.cpp :
|
||||
*
|
||||
* odom_sub_ = _node_hand.subscribe("/odom", 1, &ROS_OMPL_Planner::odomCallback, this); ==> odom_sub_ = node_handler_.subscribe("/ground_truth/state", 1, &ROS_OMPL_Planner::odomCallback, this);
|
||||
*
|
||||
* visual_result_path.header.frame_id = result_path.header.frame_id = q_init_goal.header.frame_id = visual_rrt.header.frame_id = "/odom"; ===> visual_result_path.header.frame_id = result_path.header.frame_id = q_init_goal.header.frame_id = visual_rrt.header.frame_id = "/world";
|
||||
*
|
||||
*
|
||||
* \section run Running
|
||||
*
|
||||
* You can run HelloWorld program to understand how works OMPL_Planner alone or you can run the ROS implementation (ROS_OMPL_Planner) which will include the ROS implementation, the visual simulation, the Octomap server, etc.
|
||||
*
|
||||
* \subsection runHello Run HelloWorld
|
||||
*
|
||||
* copy the octomap file (.bt) (in Maps directory) you want to use from the Map folder in the project to "~/catkin_ws/devel/lib/control_turtlebot" folder.
|
||||
*
|
||||
* cd ~/catkin_ws/devel/lib/control_turtlebot
|
||||
*
|
||||
* run HelloWorld (./HelloWorld)
|
||||
*
|
||||
* Enjoy !
|
||||
*
|
||||
* \subsection runROS Run ROS implementation
|
||||
*
|
||||
* 1st terminal (Gazebo / Rviz / Controller) :
|
||||
*
|
||||
* Turtlebot : roslaunch control_turtlebot start_turtlebot_modules.launch
|
||||
*
|
||||
* Quadrotor : roslaunch hector_quadrotor_demo indoor
|
||||
*
|
||||
* 2nd terminal (Octomap / Planning): roslaunch control_turtlebot start_turtlebot_mapping_planning_control.launch
|
||||
*
|
||||
* 3rd terminal (Planning request) : rosservice call /controller_turtlebot/find_path_to_goal "goal_state_x: 0.0
|
||||
* goal_state_y: 0.0
|
||||
* goal_state_z: 0.0"
|
||||
* rosservice call /controller_turtlebot/goto "goal_state_x: 0.0
|
||||
* goal_state_y: 0.0
|
||||
* goal_state_z: 0.0"
|
||||
*
|
||||
* \subsubsection config Configurations files
|
||||
*
|
||||
* See launch folder for runtime configurations.
|
||||
*
|
||||
* In config folder : planner_parameters.yaml
|
||||
*
|
||||
* Contains all the necessary parameters for a basic use of the planner (planning dimension, collision mask, etc.).
|
||||
*
|
||||
*
|
||||
* See also start_turtlebot_mapping_planning_control.launch file and src folder for a deeper understanding of the ROS implementation.
|
||||
*
|
||||
* \section todo Todo
|
||||
*
|
||||
* BUG : Compilation sur certain linux : FindPathToGoal.h pb de génération avec cmake
|
||||
*
|
||||
* Frontier exploration
|
||||
*
|
||||
* Clean the dynmacilly allowed memory (Needed for dynamic check)
|
||||
*
|
||||
* Optimisation :
|
||||
*
|
||||
* prevent creation of too close state (Ex : start = goal is a problem)
|
||||
*
|
||||
* path check : don't check path already done
|
||||
*
|
||||
* Improving sending speed of the octomap
|
||||
*
|
||||
*
|
||||
*/
|
|
@ -0,0 +1,215 @@
|
|||
/**
|
||||
* \file OMPL_Planner.cpp
|
||||
* \author Harlé Antoine (antoine.h@flylab.io)
|
||||
* \date 7/2017 - 8/2017
|
||||
* \brief Path planning (without differential constraints) using OMPL with Octomap to represent workspace and to validate if configurations are collision-free.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OMPL_Planner.hpp"
|
||||
|
||||
OMPL_Planner::OMPL_Planner(int dim) : _planningDimension(dim), _space(new ob::RealVectorStateSpace(dim)), _simple_setup(_space)
|
||||
{
|
||||
_si = _simple_setup.getSpaceInformation();
|
||||
/*
|
||||
_start_state.resize(3);
|
||||
_goal_state.resize(3);
|
||||
*/
|
||||
}
|
||||
|
||||
OMPL_Planner::~OMPL_Planner()
|
||||
{
|
||||
/*
|
||||
if(_checker !=nullptr)
|
||||
{
|
||||
delete _checker;
|
||||
_checker = nullptr;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void OMPL_Planner::setPlanningBounds(const std::vector<double> planning_bounds_x, const std::vector<double> planning_bounds_y, const std::vector<double> planning_bounds_z)
|
||||
{
|
||||
ob::RealVectorBounds bounds(_planningDimension);
|
||||
|
||||
if(!planning_bounds_z.empty() && _planningDimension ==3)
|
||||
{
|
||||
bounds.setLow(2, planning_bounds_z[0]);
|
||||
bounds.setHigh(2, planning_bounds_z[1]);
|
||||
}
|
||||
|
||||
bounds.setLow(0, planning_bounds_x[0]);
|
||||
bounds.setHigh(0, planning_bounds_x[1]);
|
||||
bounds.setLow(1, planning_bounds_y[0]);
|
||||
bounds.setHigh(1, planning_bounds_y[1]);
|
||||
|
||||
_space->as<ob::RealVectorStateSpace>()->setBounds(bounds);
|
||||
}
|
||||
|
||||
void OMPL_Planner::setPlanningDepth(double depth_limit)
|
||||
{
|
||||
_depth_limit = depth_limit;
|
||||
if(_checker !=nullptr)
|
||||
_checker->setDepthLimit(depth_limit);
|
||||
}
|
||||
|
||||
void OMPL_Planner::setPlanner(const std::string plannerName)
|
||||
{
|
||||
ob::PlannerPtr planner;
|
||||
if(plannerName.compare("CForest")==0)
|
||||
planner = ob::PlannerPtr(new og::CForest(_si)); //Deleted by simple_setup destructor ?
|
||||
else //Default planner
|
||||
planner = ob::PlannerPtr(new og::RRTstar(_si));
|
||||
|
||||
//planner->as<og::RRTstar>()->setRange(0.2);
|
||||
//=======================================================================
|
||||
// Set the setup planner
|
||||
//=======================================================================
|
||||
_simple_setup.setPlanner(planner);
|
||||
}
|
||||
|
||||
void OMPL_Planner::setStateChecker(const ob::StateValidityCheckerPtr state_checker)
|
||||
{
|
||||
if(state_checker != nullptr)
|
||||
_simple_setup.setStateValidityChecker(state_checker);
|
||||
else
|
||||
cout<<"ERROR : invalid pointer on state_checker\n";
|
||||
}
|
||||
|
||||
void OMPL_Planner::setStateChecker(const std::string mapFile, double collision_mask_x, double collision_mask_y, double collision_mask_z)
|
||||
{
|
||||
if(_checker !=nullptr)
|
||||
{
|
||||
delete _checker;
|
||||
_checker = nullptr;
|
||||
}
|
||||
|
||||
_checker = new StateChecker(_si);
|
||||
_checker->loadMap(mapFile);
|
||||
_checker->setCollisionMask(collision_mask_x,collision_mask_y,collision_mask_z);
|
||||
_checker->setDepthLimit(_depth_limit);
|
||||
_simple_setup.setStateValidityChecker(ob::StateValidityCheckerPtr(_checker));
|
||||
}
|
||||
|
||||
void OMPL_Planner::setStateChecker(octomap::OcTree* octree, double collision_mask_x, double collision_mask_y, double collision_mask_z)
|
||||
{
|
||||
if(_checker !=nullptr)
|
||||
{
|
||||
delete _checker;
|
||||
_checker = nullptr;
|
||||
}
|
||||
|
||||
_checker = new StateChecker(_si);
|
||||
_checker->loadMap(octree);
|
||||
_checker->setCollisionMask(collision_mask_x,collision_mask_y,collision_mask_z);
|
||||
_checker->setDepthLimit(_depth_limit);
|
||||
_simple_setup.setStateValidityChecker(ob::StateValidityCheckerPtr(_checker));
|
||||
}
|
||||
|
||||
void OMPL_Planner::updateStateChecker(octomap::OcTree* octree)
|
||||
{
|
||||
if(_checker !=nullptr)
|
||||
_checker->loadMap(octree);
|
||||
//No error warned
|
||||
}
|
||||
|
||||
void OMPL_Planner::setStartGoal(const std::vector<double> start_state, const std::vector<double> goal_state)
|
||||
{
|
||||
ob::ScopedState<> start(_space);
|
||||
ob::ScopedState<> goal(_space);
|
||||
start[0] = double(start_state[0]);
|
||||
start[1] = double(start_state[1]);
|
||||
|
||||
goal[0] = double(goal_state[0]);
|
||||
goal[1] = double(goal_state[1]);
|
||||
|
||||
if(_planningDimension==3)
|
||||
{
|
||||
start[2] = double(start_state[2]);
|
||||
goal[2] = double(goal_state[2]);
|
||||
|
||||
//Prevent invalid states because of too low altitude (Octomap issue)
|
||||
if (start[2] < _depth_limit) start[2] = _depth_limit;
|
||||
if (goal[2] < _depth_limit) goal[2] = _depth_limit;
|
||||
}
|
||||
|
||||
_simple_setup.setStartAndGoalStates(start, goal);
|
||||
}
|
||||
|
||||
bool OMPL_Planner::findPath(double solving_time)
|
||||
{
|
||||
//Clear all previous planning data (Planner settings, start/goal states not affected)
|
||||
_simple_setup.clear();
|
||||
|
||||
_simple_setup.setup();
|
||||
|
||||
//_simple_setup.print(cout);
|
||||
|
||||
ob::PlannerStatus solved = _simple_setup.solve( solving_time );
|
||||
|
||||
if (solved && _simple_setup.haveExactSolutionPath())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OMPL_Planner::isValid(std::vector<double> position) const
|
||||
{
|
||||
if(_checker !=nullptr)
|
||||
{
|
||||
ob::ScopedState<> pos(_space);
|
||||
|
||||
if(_planningDimension==2)
|
||||
{
|
||||
pos[0] = double(position[0]);
|
||||
pos[1] = double(position[1]);
|
||||
return _checker->isValid(pos->as<ob::SE2StateSpace::StateType>());
|
||||
}
|
||||
else
|
||||
{
|
||||
pos[0] = double(position[0]);
|
||||
pos[1] = double(position[1]);
|
||||
|
||||
//Prevent invalid states because of too low altitude (Octomap issue)
|
||||
if(position[2]<_depth_limit)
|
||||
pos[2]=_depth_limit;
|
||||
else
|
||||
pos[2] = double(position[2]);
|
||||
return _checker->isValid(pos->as<ob::SE3StateSpace::StateType>());
|
||||
}
|
||||
}
|
||||
else
|
||||
return false; //No error warned
|
||||
}
|
||||
|
||||
bool OMPL_Planner::checkPath() const
|
||||
{
|
||||
og::PathGeometric path = getPath();
|
||||
|
||||
return path.check();
|
||||
}
|
||||
|
||||
bool OMPL_Planner::updatePath(octomap::OcTree* octree, double solving_time, const std::vector<double> start_state, const std::vector<double> goal_state)
|
||||
{
|
||||
updateStateChecker(octree);
|
||||
|
||||
if(! checkPath()) //Invalid path
|
||||
{
|
||||
setStartGoal(start_state,goal_state);
|
||||
return findPath(solving_time);
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
og::PathGeometric OMPL_Planner::getPath() const
|
||||
{
|
||||
return _simple_setup.getSolutionPath();
|
||||
}
|
||||
|
||||
og::SimpleSetup OMPL_Planner::getSimpleSetup() const
|
||||
{
|
||||
return _simple_setup;
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* \file OMPL_Planner.hpp
|
||||
* \author Harlé Antoine (antoine.h@flylab.io)
|
||||
* \date 7/2017 - 8/2017
|
||||
* \brief Path planning (without differential constraints) using OMPL with Octomap to represent workspace and to validate if configurations are collision-free.
|
||||
*
|
||||
*/
|
||||
|
||||
//#include <string>
|
||||
|
||||
//using namespace std;
|
||||
|
||||
//OMPL//
|
||||
//#include <ompl/config.h>
|
||||
//#include <ompl/base/SpaceInformation.h>
|
||||
//#include <ompl/base/spaces/RealVectorStateSpace.h>
|
||||
#include <ompl/geometric/SimpleSetup.h>
|
||||
|
||||
#include <ompl/geometric/planners/cforest/CForest.h>
|
||||
#include <ompl/geometric/planners/rrt/RRTstar.h>
|
||||
|
||||
#include <ompl/base/spaces/SE3StateSpace.h>
|
||||
#include <ompl/base/spaces/SE2StateSpace.h>
|
||||
|
||||
//OMPL namespaces
|
||||
namespace ob = ompl::base;
|
||||
namespace og = ompl::geometric;
|
||||
|
||||
#include "StateChecker.hpp"
|
||||
|
||||
/**
|
||||
* \class OMPL_Planner
|
||||
* \brief Class for planner for 2D and 3D planning.
|
||||
*/
|
||||
class OMPL_Planner
|
||||
{
|
||||
public :
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
* Create space and simple_setup instance for OMPL planning.
|
||||
* Set planning dimension.
|
||||
*/
|
||||
OMPL_Planner(int dim);
|
||||
|
||||
//! Set the bounds of the planner workspace.
|
||||
/*!
|
||||
* Workspace defined by a box with planning_bounds limits.
|
||||
* Optional argument : Planning_bounds_z (used only for 3D planning).
|
||||
*/
|
||||
void setPlanningBounds(const std::vector<double> planning_bounds_x, const std::vector<double> planning_bounds_y, const std::vector<double> planning_bounds_z = std::vector<double>());
|
||||
|
||||
//! Set the planning depth.
|
||||
/*! Set the lowest altitude for states.
|
||||
* Represent the planning depth (constant) for 2D planning.
|
||||
* Used to prevent unwanted invalid state (Issue with the ground in Octomap).
|
||||
*/
|
||||
void setPlanningDepth(double depth_limit = 1);
|
||||
|
||||
//! Set the planning algorithm used to solve the problem.
|
||||
/*!
|
||||
* Planner avalaible : RRTstar, CForest.
|
||||
* If no argument provided, RRTstar will be used (reliable planner for most of the situations).
|
||||
* Implementation of other planners (except control-based planners) is quite simple.
|
||||
*/
|
||||
void setPlanner(const std::string plannerName = "RRTstar");
|
||||
|
||||
//! Set the state checker.
|
||||
/*!
|
||||
* Check if a given position is collision-free.
|
||||
*/
|
||||
void setStateChecker(const ob::StateValidityCheckerPtr state_checker);
|
||||
void setStateChecker(const std::string mapFile, double collision_mask_x, double collision_mask_y, double collision_mask_z = 0.2);
|
||||
void setStateChecker(octomap::OcTree* octree, double collision_mask_x, double collision_mask_y, double collision_mask_z);
|
||||
|
||||
//! Update the state checker.
|
||||
/*!
|
||||
* The new map will be used for state checking.
|
||||
* If the state checker wasn't set before, there's no update and no warning message will be displayed.
|
||||
*/
|
||||
void updateStateChecker(octomap::OcTree* octree);
|
||||
|
||||
//! Set the planning objectives.
|
||||
/*!
|
||||
* If the state has an altitude lower than the planning depth, it's altitude will be set to the planning depth.
|
||||
*/
|
||||
void setStartGoal(const std::vector<double> start_state, const std::vector<double> goal_state);
|
||||
|
||||
//! Solve the planning problem.
|
||||
/*!
|
||||
* Find a path from the start state to the goal state in the map given to the state checker.
|
||||
* The planner will run during solving_time and optimize the solution during this time.
|
||||
*/
|
||||
bool findPath(double solving_time);
|
||||
|
||||
//! Check if position is collision-free.
|
||||
/*!
|
||||
* Checking is done on the last map given to the state checker.
|
||||
*/
|
||||
bool isValid(std::vector<double> position) const;
|
||||
|
||||
//! Check if the path is valid.
|
||||
bool checkPath() const;
|
||||
|
||||
//! Update the path.
|
||||
/*!
|
||||
* Search a new path from start_state to goal state if there's a collision with the path and an obstacle from the new map.
|
||||
* Update the state checker.
|
||||
* Return True if a new path is found or if the path is collision-free. Return False, if the planner found an obstacle but failed to found a new path.
|
||||
*/
|
||||
bool updatePath(octomap::OcTree* octree, double solving_time, const std::vector<double> start_state, const std::vector<double> goal_state);
|
||||
|
||||
//! Return the path found by the planner.
|
||||
og::PathGeometric getPath() const;
|
||||
|
||||
//! Return the OMPL object containing most of the information of the planning problem.
|
||||
og::SimpleSetup getSimpleSetup() const;
|
||||
|
||||
//! Destructor.
|
||||
/*!
|
||||
* Free dynamicly allowed data.
|
||||
*/
|
||||
~OMPL_Planner();
|
||||
|
||||
private :
|
||||
|
||||
int _planningDimension; /*!< 2D or 3D */
|
||||
|
||||
ob::SpaceInformationPtr _si; /*!< Contain all the information on the workspace*/
|
||||
ob::StateSpacePtr _space; /*!< Space in which we're working (2D /3D) */
|
||||
og::SimpleSetup _simple_setup; /*!< OMPL object for planning in simple configurations*/
|
||||
|
||||
StateChecker* _checker = nullptr; /*!< Object for checking if a position is collision-free */
|
||||
|
||||
//std::vector<double> _start_state, _goal_state;
|
||||
double _depth_limit; /*!< lowest altitude for checking (constant depth for 2D checking). Used to prevent unwanted invalid state (Issue with the ground in Octomap). */
|
||||
};
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* \file StateChecker.cpp
|
||||
* \author Harlé Antoine
|
||||
* \date 7/2017 - 8/2017
|
||||
* \brief Check if a given configuration is collision-free.
|
||||
* The workspace is represented by an octomap.
|
||||
*/
|
||||
|
||||
#include "StateChecker.hpp"
|
||||
|
||||
StateChecker::StateChecker(const ob::SpaceInformationPtr &si): ob::StateValidityChecker(si)
|
||||
{
|
||||
planningDimension = si->getStateDimension();
|
||||
}
|
||||
|
||||
StateChecker::~StateChecker()
|
||||
{
|
||||
if(_map !=nullptr)
|
||||
{
|
||||
delete _map;
|
||||
_map = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void StateChecker::loadMap(const std::string mapFile) //Take a look to memory mangaement for map
|
||||
{
|
||||
/*
|
||||
if(_map !=nullptr)
|
||||
{
|
||||
delete _map;
|
||||
_map = nullptr;
|
||||
}
|
||||
*/
|
||||
_map = (new octomap::OcTree(mapFile));
|
||||
_map_res = _map->getResolution();
|
||||
}
|
||||
|
||||
void StateChecker::loadMap(octomap::OcTree* octree)
|
||||
{
|
||||
/*
|
||||
if(_map !=nullptr)
|
||||
{
|
||||
delete _map;
|
||||
_map = nullptr;
|
||||
}
|
||||
*/
|
||||
_map = octree;
|
||||
_map_res = _map->getResolution();
|
||||
}
|
||||
|
||||
void StateChecker::setCollisionMask(double x, double y, double z)
|
||||
{
|
||||
_check_box.x=x;
|
||||
_check_box.y=y;
|
||||
_check_box.z=z;
|
||||
}
|
||||
|
||||
void StateChecker::setDepthLimit(double depth_limit)
|
||||
{
|
||||
_depth_limit = depth_limit;
|
||||
}
|
||||
|
||||
bool StateChecker::isValid(const ob::State *state) const
|
||||
{
|
||||
OcTreeNode* result;
|
||||
point3d query; //Octomap
|
||||
bool collision(false);
|
||||
double node_occupancy;
|
||||
|
||||
// extract the component of the state and cast it to what we expect
|
||||
const ob::RealVectorStateSpace::StateType *pos = state->as<ob::RealVectorStateSpace::StateType>();
|
||||
|
||||
//Constant depth for 2D planning (There might be a better way to implement this)
|
||||
|
||||
if(planningDimension==2)
|
||||
{
|
||||
pos->values[2]=_depth_limit;
|
||||
}
|
||||
|
||||
//Recherche dans le collision mask autour de pos
|
||||
for(double xi = pos->values[0]-(_check_box.x/2.0);xi <= pos->values[0]+(_check_box.x/2.0);xi=xi+_map_res)
|
||||
for(double yi = pos->values[1]-(_check_box.y/2.0);yi <= pos->values[1]+(_check_box.y/2.0);yi=yi+_map_res)
|
||||
for(double zi = pos->values[2]-(_check_box.z/2.0);zi <= pos->values[2]+(_check_box.z/2.0);zi=zi+_map_res){ //Trop sensible sur z
|
||||
query.x() = xi;
|
||||
query.y() = yi;
|
||||
query.z() = zi;
|
||||
result = _map->search (query); //Retourne le pointeur de la node à la position query, NULL si elle n'existe pas (terrain inconnu)
|
||||
|
||||
if(result != NULL){ // Node connue
|
||||
|
||||
node_occupancy = result->getOccupancy();
|
||||
|
||||
if (node_occupancy > 0.4)
|
||||
{
|
||||
collision = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !collision;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* \file State_Checker.hpp
|
||||
* \author Harlé Antoine
|
||||
* \date 7/2017 - 8/2017
|
||||
* \brief Check if a given configuration is collision-free.
|
||||
* The workspace is represented by an octomap.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//OCTOMAP//
|
||||
#include <octomap/octomap.h>
|
||||
|
||||
using namespace octomap;
|
||||
|
||||
//OMPL//
|
||||
#include <ompl/config.h>
|
||||
#include <ompl/base/SpaceInformation.h>
|
||||
#include <ompl/base/spaces/RealVectorStateSpace.h>
|
||||
|
||||
namespace ob = ompl::base;
|
||||
|
||||
/**
|
||||
* \struct Checking_Box
|
||||
* \brief Collision Mask : virtual representation of the drone as a box with x,y,z length
|
||||
*/
|
||||
struct Checking_Box
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class StateChecker
|
||||
* \brief Class for state checking for 2D and 3D planning.
|
||||
* Extension of an abstract class used to implement the state validity checker over an octomap (using FCL ?).
|
||||
*/
|
||||
class StateChecker : public ob::StateValidityChecker
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
* Call the StateValidityChecker constructor from OMPL library and set checking dimension.
|
||||
*/
|
||||
StateChecker(const ob::SpaceInformationPtr &si);
|
||||
|
||||
//! Load the octomap where the states are checked
|
||||
void loadMap(const std::string mapFile);
|
||||
void loadMap(octomap::OcTree* octree);
|
||||
|
||||
//! Set the area around every state considered for state checking.
|
||||
void setCollisionMask(double x, double y, double z = 0.2);
|
||||
|
||||
//! Set the depth limit (constant for 2D checking)
|
||||
/*! Set the lowest altitude for checking (constant depth for 2D checking).
|
||||
* Used to prevent unwanted invalid state (Issue with the ground in Octomap)
|
||||
*/
|
||||
void setDepthLimit(double depth_limit);
|
||||
|
||||
//! State validator.
|
||||
/*!
|
||||
* Function that verifies if the given state is valid (i.e. is free of collision) using FCL.
|
||||
*/
|
||||
virtual bool isValid(const ob::State *state) const;
|
||||
|
||||
//! Destructor.
|
||||
/*!
|
||||
* Free dynamicly allowed data.
|
||||
*/
|
||||
~StateChecker();
|
||||
|
||||
private :
|
||||
|
||||
int planningDimension; /*!< 2D or 3D */
|
||||
//Octomap
|
||||
octomap::OcTree* _map = nullptr; /*!< Pointer to the object containing the map (Heavy object ?)*/
|
||||
double _map_res, _depth_limit;
|
||||
|
||||
Checking_Box _check_box; /*!< Collision mask : area around every state considered for state checking. */
|
||||
};
|
|
@ -0,0 +1,467 @@
|
|||
/**
|
||||
* \file ROS_ OMPL_Planner.cpp
|
||||
* \author Harlé Antoine (antoine.h@flylab.io)
|
||||
* \date 7/2017 - 8/2017
|
||||
* \brief ROS implementation of OMPL_Planner.
|
||||
*/
|
||||
|
||||
#include "ROS_OMPL_Planner.hpp"
|
||||
|
||||
ROS_OMPL_Planner::ROS_OMPL_Planner(int dimension) : planningDimension(dimension), planner(dimension), _obstacle_flag(true)
|
||||
{
|
||||
//=======================================================================
|
||||
// Subscribers.
|
||||
//=======================================================================
|
||||
//Navigation data
|
||||
odom_sub_ = _node_hand.subscribe("/odom", 1, &ROS_OMPL_Planner::odomCallback, this);
|
||||
|
||||
//=======================================================================
|
||||
// Publishers (to visualize the resulting path).
|
||||
//=======================================================================
|
||||
visual_traj_pub_ = _node_hand.advertise<visualization_msgs::Marker> ("/controller_turtlebot/solution_path", 1, true);
|
||||
path_pub_ = _node_hand.advertise<geometry_msgs::PoseArray> ("/Planning_Module/path", 1, true);
|
||||
|
||||
//=======================================================================
|
||||
// Service
|
||||
//=======================================================================
|
||||
service_ = _node_hand.advertiseService("/controller_turtlebot/find_path_to_goal", &ROS_OMPL_Planner::findPathToGoal, this);
|
||||
|
||||
planning_bounds_x_.resize(2);
|
||||
planning_bounds_y_.resize(2);
|
||||
planning_bounds_z_.resize(2);
|
||||
current_position_.resize(3);
|
||||
goal_state.resize(3);
|
||||
|
||||
//=======================================================================
|
||||
// Get parameters from configuration file.
|
||||
//=======================================================================
|
||||
_node_hand.getParam("planning_bounds_x", planning_bounds_x_);
|
||||
_node_hand.getParam("planning_bounds_y", planning_bounds_y_);
|
||||
_node_hand.getParam("planning_bounds_z", planning_bounds_z_);
|
||||
|
||||
_node_hand.getParam("solving_time", solving_time_);
|
||||
_node_hand.getParam("planner_name", planner_name_);
|
||||
|
||||
_node_hand.getParam("collision_mask_x", collision_mask.x);
|
||||
_node_hand.getParam("collision_mask_y", collision_mask.y);
|
||||
|
||||
if(dimension==2)
|
||||
_node_hand.getParam("collision_mask_z_2D", collision_mask.z);
|
||||
else
|
||||
_node_hand.getParam("collision_mask_z_3D", collision_mask.z);
|
||||
|
||||
_node_hand.getParam("planning_depth_limit", planning_depth_limit);
|
||||
|
||||
//=======================================================================
|
||||
// Planner setup.
|
||||
//=======================================================================
|
||||
|
||||
planner.setPlanningDepth(planning_depth_limit);
|
||||
|
||||
if (dimension == 2)
|
||||
planner.setPlanningBounds(planning_bounds_x_, planning_bounds_y_);
|
||||
else
|
||||
planner.setPlanningBounds(planning_bounds_x_, planning_bounds_y_, planning_bounds_z_);
|
||||
|
||||
planner.setPlanner(planner_name_);
|
||||
|
||||
updateMap();
|
||||
planner.setStateChecker(octree_, collision_mask.x, collision_mask.y, collision_mask.z);
|
||||
|
||||
ROS_INFO("%s: %dD Planner Init done !", ros::this_node::getName().c_str(), dimension);
|
||||
}
|
||||
|
||||
bool ROS_OMPL_Planner::updateMap()
|
||||
{
|
||||
if(octree_ !=nullptr)
|
||||
{
|
||||
delete octree_;
|
||||
octree_ = nullptr;
|
||||
}
|
||||
|
||||
ROS_INFO("%s: requesting the map to %s...", ros::this_node::getName().c_str(), _node_hand.resolveName(serv_name).c_str());
|
||||
|
||||
while((_node_hand.ok() && !ros::service::call(serv_name, req, resp)) || resp.map.data.size()==0)
|
||||
{
|
||||
ROS_WARN("Request to %s failed; trying again...", _node_hand.resolveName(serv_name).c_str());
|
||||
usleep(1000000);
|
||||
}
|
||||
if (_node_hand.ok()){ // skip when CTRL-C
|
||||
abs_octree_ = octomap_msgs::msgToMap(resp.map);
|
||||
|
||||
if (abs_octree_)
|
||||
{
|
||||
octree_ = dynamic_cast<octomap::OcTree*>(abs_octree_);
|
||||
}
|
||||
|
||||
if (octree_){
|
||||
ROS_INFO("Octomap received (%zu nodes)", octree_->size());
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
ROS_ERROR("Error reading OcTree from stream");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ROS_OMPL_Planner::odomCallback(const nav_msgs::OdometryPtr &odom_msg)
|
||||
{
|
||||
current_position_[0] = odom_msg->pose.pose.position.x;
|
||||
current_position_[1] = odom_msg->pose.pose.position.y;
|
||||
current_position_[2] = odom_msg->pose.pose.position.z;
|
||||
}
|
||||
|
||||
bool ROS_OMPL_Planner::findPathToGoal(control_turtlebot::FindPathToGoal::Request& request, control_turtlebot::FindPathToGoal::Response& response)
|
||||
{
|
||||
goal_state[0] = request.goal_state_x;
|
||||
goal_state[1] = request.goal_state_y;
|
||||
goal_state[2] = request.goal_state_z;
|
||||
|
||||
//Prevent invalid states because of too low altitude (Octomap issue)
|
||||
if(goal_state[2]<planning_depth_limit) goal_state[2] = planning_depth_limit;
|
||||
if(current_position_[2]<planning_depth_limit) current_position_[2] = planning_depth_limit;
|
||||
|
||||
updateMap();
|
||||
planner.updateStateChecker(octree_);
|
||||
|
||||
// Start and Goal checking
|
||||
if(! planner.isValid(current_position_))
|
||||
ROS_WARN("%s: Start Position %lf/%lf/%lf is invalid !\n",ros::this_node::getName().c_str(), current_position_[0],current_position_[1],current_position_[2]);
|
||||
if(! planner.isValid(goal_state))
|
||||
ROS_WARN("%s: Goal Position %lf/%lf/%lf is invalid !\n",ros::this_node::getName().c_str(), goal_state[0],goal_state[1],goal_state[2]);
|
||||
|
||||
planner.setStartGoal(current_position_, goal_state);
|
||||
|
||||
ROS_INFO("%s: Searching path from %lf/%lf/%lf to %lf/%lf/%lf ...\n",ros::this_node::getName().c_str(), current_position_[0],current_position_[1],current_position_[2], goal_state[0],goal_state[1],goal_state[2]);
|
||||
|
||||
if(planner.findPath(solving_time_))
|
||||
{
|
||||
_obstacle_flag = false;
|
||||
ROS_INFO("%s: path has been found with simple_setup", ros::this_node::getName().c_str());
|
||||
PublishPath(response);
|
||||
}
|
||||
else
|
||||
ROS_WARN("%s: path has not been found", ros::this_node::getName().c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//REALLY Ugly function
|
||||
void ROS_OMPL_Planner::visualizeRRT(const og::SimpleSetup simple_setup)
|
||||
{
|
||||
og::PathGeometric geopath = simple_setup.getSolutionPath();
|
||||
// %Tag(MARKER_INIT)%
|
||||
visualization_msgs::Marker q_init_goal, visual_rrt, result_path, visual_result_path;
|
||||
visual_result_path.header.frame_id = result_path.header.frame_id = q_init_goal.header.frame_id = visual_rrt.header.frame_id = "/odom";
|
||||
visual_result_path.header.stamp = result_path.header.stamp = q_init_goal.header.stamp = visual_rrt.header.stamp = ros::Time::now();
|
||||
q_init_goal.ns = "online_planner_points";
|
||||
visual_rrt.ns = "online_planner_rrt";
|
||||
result_path.ns = "online_planner_result";
|
||||
visual_result_path.ns = "online_planner_result_path";
|
||||
visual_result_path.action = result_path.action = q_init_goal.action = visual_rrt.action = visualization_msgs::Marker::ADD;
|
||||
|
||||
visual_result_path.pose.orientation.w = result_path.pose.orientation.w = q_init_goal.pose.orientation.w = visual_rrt.pose.orientation.w = 1.0;
|
||||
// %EndTag(MARKER_INIT)%
|
||||
|
||||
// %Tag(ID)%
|
||||
q_init_goal.id = 0;
|
||||
visual_rrt.id = 1;
|
||||
result_path.id = 2;
|
||||
visual_result_path.id = 3;
|
||||
// %EndTag(ID)%
|
||||
|
||||
// %Tag(TYPE)%
|
||||
result_path.type = q_init_goal.type = visualization_msgs::Marker::POINTS;
|
||||
visual_rrt.type = visual_result_path.type = visualization_msgs::Marker::LINE_LIST;
|
||||
// %EndTag(TYPE)%
|
||||
|
||||
// %Tag(SCALE)%
|
||||
// POINTS markers use x and y scale for width/height respectively
|
||||
result_path.scale.x = q_init_goal.scale.x = 0.5;
|
||||
result_path.scale.y = q_init_goal.scale.y = 0.5;
|
||||
result_path.scale.z = q_init_goal.scale.z = 0.5;
|
||||
|
||||
// LINE_STRIP/LINE_LIST markers use only the x component of scale, for the line width
|
||||
visual_rrt.scale.x = 0.01;
|
||||
visual_result_path.scale.x = 0.02;
|
||||
// %EndTag(SCALE)%
|
||||
|
||||
// %Tag(COLOR)%
|
||||
// Points are green
|
||||
visual_result_path.color.g = 1.0;
|
||||
result_path.color.g = q_init_goal.color.g = 1.0;
|
||||
visual_result_path.color.a = result_path.color.a = q_init_goal.color.a = 1.0;
|
||||
|
||||
// Line strip is blue
|
||||
visual_rrt.color.b = 1.0;
|
||||
visual_rrt.color.a = 1.0;
|
||||
|
||||
|
||||
ob::PlannerData planner_data(simple_setup.getSpaceInformation());
|
||||
simple_setup.getPlannerData(planner_data);
|
||||
std::vector< unsigned int > edgeList;
|
||||
int num_parents;
|
||||
//const ob::SE2StateSpace::StateType *state_se2;
|
||||
const ob::RealVectorStateSpace::StateType *state_r2;
|
||||
|
||||
const ob::RealVectorStateSpace::StateType *state;
|
||||
geometry_msgs::Point p;
|
||||
|
||||
if(planningDimension==3)
|
||||
{
|
||||
for (unsigned int i = 1 ; i < planner_data.numVertices() ; ++i)
|
||||
{
|
||||
if (planner_data.getVertex(i).getState() && planner_data.getIncomingEdges(i,edgeList) > 0)
|
||||
{
|
||||
state_r2 = planner_data.getVertex(i).getState()->as<ob::RealVectorStateSpace::StateType>();
|
||||
p.x = state_r2->values[0];
|
||||
p.y = state_r2->values[1];
|
||||
p.z = state_r2->values[2];//3D change
|
||||
visual_rrt.points.push_back(p);
|
||||
|
||||
state_r2 = planner_data.getVertex(edgeList[0]).getState()->as<ob::RealVectorStateSpace::StateType>();
|
||||
p.x = state_r2->values[0];
|
||||
p.y = state_r2->values[1];
|
||||
p.z = state_r2->values[2];//3D change
|
||||
visual_rrt.points.push_back(p);
|
||||
}
|
||||
}
|
||||
std::vector< ob::State * > states = geopath.getStates();
|
||||
|
||||
for (uint32_t i = 0; i < geopath.getStateCount(); ++i)
|
||||
{
|
||||
// extract the component of the state and cast it to what we expect
|
||||
state = states[i]->as<ob::RealVectorStateSpace::StateType>();
|
||||
|
||||
p.x = state->values[0];
|
||||
p.y = state->values[1];
|
||||
p.z = state->values[2];//3D change
|
||||
|
||||
result_path.points.push_back(p);
|
||||
|
||||
if(i>0)
|
||||
{
|
||||
visual_result_path.points.push_back(p);
|
||||
state = states[i-1]->as<ob::RealVectorStateSpace::StateType>();
|
||||
|
||||
p.x = state->values[0];
|
||||
p.y = state->values[1];
|
||||
p.z = state->values[2];//3D change
|
||||
visual_result_path.points.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 1 ; i < planner_data.numVertices() ; ++i)
|
||||
{
|
||||
if (planner_data.getVertex(i).getState() && planner_data.getIncomingEdges(i,edgeList) > 0)
|
||||
{
|
||||
state_r2 = planner_data.getVertex(i).getState()->as<ob::RealVectorStateSpace::StateType>();
|
||||
p.x = state_r2->values[0];
|
||||
p.y = state_r2->values[1];
|
||||
p.z = planning_depth_limit; //2D change
|
||||
visual_rrt.points.push_back(p);
|
||||
|
||||
state_r2 = planner_data.getVertex(edgeList[0]).getState()->as<ob::RealVectorStateSpace::StateType>();
|
||||
p.x = state_r2->values[0];
|
||||
p.y = state_r2->values[1];
|
||||
p.z = planning_depth_limit; //2D change
|
||||
visual_rrt.points.push_back(p);
|
||||
}
|
||||
}
|
||||
std::vector< ob::State * > states = geopath.getStates();
|
||||
|
||||
for (uint32_t i = 0; i < geopath.getStateCount(); ++i)
|
||||
{
|
||||
// extract the component of the state and cast it to what we expect
|
||||
state = states[i]->as<ob::RealVectorStateSpace::StateType>();
|
||||
|
||||
p.x = state->values[0];
|
||||
p.y = state->values[1];
|
||||
p.z = planning_depth_limit; //2D change
|
||||
|
||||
result_path.points.push_back(p);
|
||||
|
||||
if(i>0)
|
||||
{
|
||||
visual_result_path.points.push_back(p);
|
||||
state = states[i-1]->as<ob::RealVectorStateSpace::StateType>();
|
||||
|
||||
p.x = state->values[0];
|
||||
p.y = state->values[1];
|
||||
p.z = planning_depth_limit; //2D change
|
||||
visual_result_path.points.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
//visual_traj_pub_.publish(q_init_goal);
|
||||
visual_traj_pub_.publish(visual_rrt);
|
||||
visual_traj_pub_.publish(visual_result_path);
|
||||
//visual_traj_pub_.publish(result_path);
|
||||
}
|
||||
|
||||
//Ugly function
|
||||
void ROS_OMPL_Planner::PublishPath(control_turtlebot::FindPathToGoal::Response& response)
|
||||
{
|
||||
og::PathGeometric path = planner.getPath();
|
||||
//Display path
|
||||
visualizeRRT(planner.getSimpleSetup());
|
||||
|
||||
std::vector< ob::State * > states = path.getStates();
|
||||
const ob::RealVectorStateSpace::StateType *state;
|
||||
|
||||
uint32_t state_nb = path.getStateCount();
|
||||
|
||||
geometry_msgs::PoseArray path_msg;
|
||||
|
||||
//A CHANGER : passage du nombre de state
|
||||
//Passer par stamp dans le header ?
|
||||
geometry_msgs::Pose state_nb_msg;
|
||||
state_nb_msg.position.x=state_nb;
|
||||
path_msg.poses.push_back(state_nb_msg);
|
||||
|
||||
//ROS_INFO("State nb : %d",state_nb);
|
||||
if(planningDimension==3)
|
||||
{
|
||||
for (uint32_t i = 0; i < state_nb; ++i)
|
||||
{
|
||||
geometry_msgs::Pose pose;
|
||||
geometry_msgs::Point point;
|
||||
// extract the component of the state and cast it to what we expect
|
||||
state = states[i]->as<ob::RealVectorStateSpace::StateType>();
|
||||
|
||||
point.x = state->values[0];
|
||||
point.y = state->values[1];
|
||||
point.z = state->values[2];
|
||||
|
||||
pose.position = point;
|
||||
|
||||
path_msg.poses.push_back(pose);
|
||||
//Send path as response of the planning request
|
||||
response.poses.push_back(pose);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < state_nb; ++i)
|
||||
{
|
||||
geometry_msgs::Pose pose;
|
||||
geometry_msgs::Point point;
|
||||
// extract the component of the state and cast it to what we expect
|
||||
state = states[i]->as<ob::RealVectorStateSpace::StateType>();
|
||||
|
||||
point.x = state->values[0];
|
||||
point.y = state->values[1];
|
||||
point.z = planning_depth_limit;
|
||||
|
||||
pose.position = point;
|
||||
|
||||
path_msg.poses.push_back(pose);
|
||||
//Send path as response of the planning request
|
||||
response.poses.push_back(pose);
|
||||
}
|
||||
}
|
||||
//Publish the path on a topic
|
||||
path_pub_.publish(path_msg);
|
||||
}
|
||||
|
||||
void ROS_OMPL_Planner::PublishPath()
|
||||
{
|
||||
og::PathGeometric path = planner.getPath();
|
||||
//Display path
|
||||
visualizeRRT(planner.getSimpleSetup());
|
||||
|
||||
std::vector< ob::State * > states = path.getStates();
|
||||
const ob::RealVectorStateSpace::StateType *state;
|
||||
|
||||
uint32_t state_nb = path.getStateCount();
|
||||
|
||||
geometry_msgs::PoseArray path_msg;
|
||||
|
||||
//A CHANGER : passage du nombre de state
|
||||
//Passer par stamp dans le header ?
|
||||
geometry_msgs::Pose state_nb_msg;
|
||||
state_nb_msg.position.x=state_nb;
|
||||
path_msg.poses.push_back(state_nb_msg);
|
||||
|
||||
//ROS_INFO("State nb : %d",state_nb);
|
||||
if(planningDimension==3)
|
||||
{
|
||||
for (uint32_t i = 0; i < state_nb; ++i)
|
||||
{
|
||||
geometry_msgs::Pose pose;
|
||||
geometry_msgs::Point point;
|
||||
// extract the component of the state and cast it to what we expect
|
||||
state = states[i]->as<ob::RealVectorStateSpace::StateType>();
|
||||
|
||||
point.x = state->values[0];
|
||||
point.y = state->values[1];
|
||||
point.z = state->values[2];
|
||||
|
||||
pose.position = point;
|
||||
|
||||
path_msg.poses.push_back(pose);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < state_nb; ++i)
|
||||
{
|
||||
geometry_msgs::Pose pose;
|
||||
geometry_msgs::Point point;
|
||||
// extract the component of the state and cast it to what we expect
|
||||
state = states[i]->as<ob::RealVectorStateSpace::StateType>();
|
||||
|
||||
point.x = state->values[0];
|
||||
point.y = state->values[1];
|
||||
point.z = planning_depth_limit;
|
||||
|
||||
pose.position = point;
|
||||
|
||||
path_msg.poses.push_back(pose);
|
||||
}
|
||||
}
|
||||
//Publish the path on a topic
|
||||
path_pub_.publish(path_msg);
|
||||
}
|
||||
|
||||
bool ROS_OMPL_Planner::getObstacleFlag() const
|
||||
{
|
||||
return _obstacle_flag;
|
||||
}
|
||||
|
||||
bool ROS_OMPL_Planner::updatePath()
|
||||
{
|
||||
ROS_INFO("%s: Updating path ...\n",ros::this_node::getName().c_str());
|
||||
|
||||
if(current_position_[2]<planning_depth_limit) current_position_[2] = planning_depth_limit;
|
||||
|
||||
updateMap();
|
||||
|
||||
// Start and Goal checking
|
||||
if(! planner.isValid(current_position_))
|
||||
ROS_WARN("%s: Start Position %lf/%lf/%lf is invalid !\n",ros::this_node::getName().c_str(), current_position_[0],current_position_[1],current_position_[2]);
|
||||
if(! planner.isValid(goal_state))
|
||||
ROS_WARN("%s: Goal Position %lf/%lf/%lf is invalid !\n",ros::this_node::getName().c_str(), goal_state[0],goal_state[1],goal_state[2]);
|
||||
|
||||
if(planner.updatePath(octree_, solving_time_, current_position_, goal_state))
|
||||
{
|
||||
_obstacle_flag=false;
|
||||
PublishPath();
|
||||
ROS_INFO("%s: Path update done !\n",ros::this_node::getName().c_str());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_obstacle_flag = true;
|
||||
ROS_WARN("%s: Path update failed !\n",ros::this_node::getName().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ROS_OMPL_Planner::~ROS_OMPL_Planner()
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
* \file ROS_ OMPL_Planner.hpp
|
||||
* \author Harlé Antoine (antoine.h@flylab.io)
|
||||
* \date 7/2017 - 8/2017
|
||||
* \brief ROS implementation of OMPL_Planner.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ros/ros.h>
|
||||
#include <visualization_msgs/Marker.h>
|
||||
#include <nav_msgs/Odometry.h>
|
||||
#include <std_msgs/Bool.h>
|
||||
#include <geometry_msgs/PoseArray.h>
|
||||
#include <ros/package.h>
|
||||
#include <std_srvs/Empty.h>
|
||||
#include <tf/message_filter.h>
|
||||
#include <tf/transform_listener.h>
|
||||
#include <control_turtlebot/FindPathToGoal.h>
|
||||
#include <geometry_msgs/Pose2D.h>
|
||||
#include <geometry_msgs/Pose.h>
|
||||
|
||||
#include <octomap_msgs/conversions.h>
|
||||
#include <octomap_msgs/GetOctomap.h>
|
||||
|
||||
//ROS-Octomap interface
|
||||
using octomap_msgs::GetOctomap;
|
||||
|
||||
#include "../OMPL_Planner/OMPL_Planner.hpp"
|
||||
|
||||
/**
|
||||
* \class ROS_OMPL_Planner
|
||||
* \brief ROS implementation class for OMPL_Planner.
|
||||
*/
|
||||
class ROS_OMPL_Planner
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
/*!
|
||||
* Load planning parameters from configuration file.
|
||||
* Create the connection with other ROS nodes.
|
||||
* Create the OMPL_Planner instance.
|
||||
*/
|
||||
ROS_OMPL_Planner(int dimension);
|
||||
|
||||
//! Request and load the actual map from the Octomap server.
|
||||
bool updateMap();
|
||||
|
||||
//! Callback for getting current vehicle position
|
||||
void odomCallback(const nav_msgs::OdometryPtr &odom_msg);
|
||||
|
||||
//! Find a path
|
||||
/*!
|
||||
* Find a path from the current position to the goal request.
|
||||
* Update the state checker, check the validity of the start/goal state.
|
||||
*/
|
||||
bool findPathToGoal(control_turtlebot::FindPathToGoal::Request& request, control_turtlebot::FindPathToGoal::Response& response);
|
||||
|
||||
//! Procedure to visualize the resulting path.
|
||||
/*!
|
||||
* Visualize resulting path.
|
||||
*/
|
||||
void visualizeRRT(const og::SimpleSetup simple_setup);
|
||||
|
||||
//! Publish the resulting path.
|
||||
/*!
|
||||
* Publish the path on a topic and in response of the request.
|
||||
* Display the path.
|
||||
* TOPIC : the first state of the path contains the number of states of the path.
|
||||
*/
|
||||
void PublishPath(control_turtlebot::FindPathToGoal::Response& response);
|
||||
|
||||
//! Publish the resulting path.
|
||||
/*!
|
||||
* Publish the path on a topic.
|
||||
* Display the path.
|
||||
* TOPIC : the first state of the path contains the number of states of the path.
|
||||
*/
|
||||
void PublishPath();
|
||||
|
||||
//! Return the flag representing the validity of the current path.
|
||||
bool getObstacleFlag() const;
|
||||
|
||||
//! Update the path.
|
||||
/*!
|
||||
* Search a new path from start_state to goal state if there's a collision with the path and an obstacle from the new map.
|
||||
* Update the state checker and the obstacle_flag.Check the validity of the start/goal state.
|
||||
* Return True if a new path is found or if the path is collision-free. Return False, if the planner found an obstacle but failed to found a new path.
|
||||
*/
|
||||
bool updatePath();
|
||||
|
||||
//! Destructor.
|
||||
/*!
|
||||
* Free dynamicly allowed data.
|
||||
*/
|
||||
~ROS_OMPL_Planner();
|
||||
|
||||
private:
|
||||
OMPL_Planner planner; /*!< Planner for 2D and 3D planning. */
|
||||
|
||||
//Octomap
|
||||
octomap::AbstractOcTree* abs_octree_;
|
||||
octomap::OcTree* octree_ = nullptr; /*!< Pointer to the object containing the map (Heavy object ?).*/
|
||||
|
||||
// *** ROS ***
|
||||
ros::NodeHandle _node_hand;
|
||||
ros::Publisher visual_traj_pub_, path_pub_;
|
||||
ros::Subscriber odom_sub_;
|
||||
ros::ServiceServer service_;
|
||||
// Octomap server
|
||||
GetOctomap::Request req;
|
||||
GetOctomap::Response resp;
|
||||
std::string serv_name = "/octomap_full"; /*!< Address of the Octomap server. */
|
||||
|
||||
bool _obstacle_flag; /*!< Flag representing the validity of the current path, whether there is obstacle on the path or not. */
|
||||
int planningDimension;
|
||||
double solving_time_,planning_depth_limit;
|
||||
std::string planner_name_;
|
||||
std::vector<double> current_position_, goal_state;
|
||||
std::vector<double> planning_bounds_x_, planning_bounds_y_, planning_bounds_z_; /*!< Limits of the planning workspace. */
|
||||
|
||||
Checking_Box collision_mask; /*!< Virtual representation of the drone used for collision checking. */
|
||||
};
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* \file ROS_ Planning_Node.cpp
|
||||
* \author Harlé Antoine (antoine.h@flylab.io)
|
||||
* \date 7/2017 - 8/2017
|
||||
* \brief Planning ROS node.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ROS_OMPL_Planner.hpp"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
ros::init(argc, argv, "offline_planner_with_services_R2");
|
||||
ros::NodeHandle node_handler_;
|
||||
ROS_INFO("%s: using OMPL version %s", ros::this_node::getName().c_str(), OMPL_VERSION);
|
||||
ompl::msg::setLogLevel(ompl::msg::LOG_NONE);
|
||||
|
||||
std::string planning_dimension;
|
||||
node_handler_.getParam("planning_dimension", planning_dimension);
|
||||
|
||||
|
||||
if(planning_dimension.compare("2D")==0) //2D planning
|
||||
{
|
||||
//Initialization planner
|
||||
ROS_OMPL_Planner planner(2);
|
||||
|
||||
ros::Rate loop_rate(10);
|
||||
while (ros::ok())
|
||||
{
|
||||
if(! planner.getObstacleFlag()) //Constantly check while the path is valid
|
||||
{
|
||||
planner.updatePath();
|
||||
}
|
||||
ros::spinOnce();
|
||||
loop_rate.sleep();
|
||||
}
|
||||
}
|
||||
else //3D planning
|
||||
{
|
||||
//Initialization planner
|
||||
ROS_OMPL_Planner planner(3);
|
||||
|
||||
ros::Rate loop_rate(10);
|
||||
while (ros::ok())
|
||||
{
|
||||
if(! planner.getObstacleFlag()) //Constantly check while the path is valid
|
||||
{
|
||||
planner.updatePath();
|
||||
}
|
||||
ros::spinOnce();
|
||||
loop_rate.sleep();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# ROS imports
|
||||
import roslib; roslib.load_manifest('control_turtlebot')
|
||||
import rospy
|
||||
import tf
|
||||
import math
|
||||
|
||||
#ROS messages
|
||||
from geometry_msgs.msg import Twist
|
||||
from nav_msgs.msg import Odometry
|
||||
from control_turtlebot.srv import GotoWaypoint, GotoWaypointResponse, FindPathToGoal, FindPathToGoalResponse, FindPathToGoalRequest
|
||||
|
||||
#Numpy
|
||||
import numpy as np
|
||||
|
||||
class Controller(object):
|
||||
|
||||
def __init__(self):
|
||||
self.odometry_sub_ = rospy.Subscriber("/ground_truth/state", Odometry, self.odomCallback, queue_size = 1)
|
||||
self.control_input_pub_ = rospy.Publisher("/cmd_vel", Twist, queue_size = 1)
|
||||
|
||||
self.serv_ = rospy.Service('/controller_turtlebot/goto',
|
||||
GotoWaypoint,
|
||||
self.calculateControlInput)
|
||||
|
||||
self.current_position_ = np.zeros(3)
|
||||
self.current_orientation_ = 0.0
|
||||
|
||||
self.desired_position_ = np.zeros(3)
|
||||
self.desired_orientation_ = 0.0
|
||||
|
||||
|
||||
rospy.wait_for_service('/controller_turtlebot/find_path_to_goal')
|
||||
try:
|
||||
self.find_path_to_goal_serv_ = rospy.ServiceProxy('/controller_turtlebot/find_path_to_goal', FindPathToGoal)
|
||||
except rospy.ServiceException, e:
|
||||
print "Service call failed: %s"%e
|
||||
|
||||
return
|
||||
|
||||
def calculateControlInput(self, req):
|
||||
|
||||
planner_request = FindPathToGoalRequest()
|
||||
planner_request.new_goal = True
|
||||
planner_request.goal_state_x = req.goal_state_x
|
||||
planner_request.goal_state_y = req.goal_state_y
|
||||
planner_request.goal_state_z = req.goal_state_z
|
||||
|
||||
planner_response = self.find_path_to_goal_serv_(planner_request)
|
||||
|
||||
for pose in planner_response.poses:
|
||||
print pose
|
||||
control_input = Twist()
|
||||
self.desired_position_[0] = pose.position.x
|
||||
self.desired_position_[1] = pose.position.y
|
||||
self.desired_position_[2] = pose.position.z
|
||||
|
||||
loop_rate = rospy.Rate(100) # 10Hz
|
||||
orientation_approach = False
|
||||
while not rospy.is_shutdown():
|
||||
inc_x = self.desired_position_[0] - self.current_position_[0]
|
||||
inc_y = self.desired_position_[1] - self.current_position_[1]
|
||||
inc_z = self.desired_position_[2] - self.current_position_[2]
|
||||
|
||||
self.desired_orientation_ = wrapAngle(math.atan2(inc_y, inc_x))
|
||||
yaw_error = wrapAngle(self.desired_orientation_ - self.current_orientation_)
|
||||
distance_to_goal = math.sqrt(math.pow(inc_x, 2.0) + math.pow(inc_y, 2.0))
|
||||
|
||||
if abs(yaw_error) > 0.04 and not orientation_approach:
|
||||
control_input.angular.x = 0.0
|
||||
control_input.angular.y = 0.0
|
||||
control_input.angular.z = yaw_error * 1.0
|
||||
|
||||
control_input.linear.x = 0.0
|
||||
control_input.linear.y = 0.0
|
||||
control_input.linear.z = 0.0
|
||||
else:
|
||||
control_input.angular.x = 0.0
|
||||
control_input.angular.y = 0.0
|
||||
control_input.angular.z = 0.0
|
||||
|
||||
orientation_approach = True
|
||||
liner_speed = abs(distance_to_goal) * 0.5
|
||||
altitude_speed = inc_z * 0.5
|
||||
|
||||
if liner_speed < 0.1:
|
||||
control_input.linear.x = 0.1
|
||||
elif liner_speed > 0.2:
|
||||
control_input.linear.x = 0.2
|
||||
else :
|
||||
control_input.linear.x = liner_speed
|
||||
|
||||
if abs(altitude_speed) < 0.1:
|
||||
if altitude_speed ==0 :
|
||||
control_input.linear.z = 0
|
||||
elif altitude_speed > 0 :
|
||||
control_input.linear.z = 0.1
|
||||
else:
|
||||
control_input.linear.z = -0.1
|
||||
|
||||
elif abs(altitude_speed) > 0.2:
|
||||
if altitude_speed > 0 :
|
||||
control_input.linear.z = 0.2
|
||||
else:
|
||||
control_input.linear.z = - 0.2
|
||||
else:
|
||||
control_input.linear.z = altitude_speed
|
||||
|
||||
control_input.linear.y = 0.0
|
||||
|
||||
|
||||
self.control_input_pub_.publish(control_input)
|
||||
|
||||
rospy.logdebug("%s: current position: [%f, %f]\n", rospy.get_name(), self.current_position_[0], self.current_position_[1])
|
||||
rospy.logdebug("%s: desired position: [%f, %f]\n", rospy.get_name(), self.desired_position_[0], self.desired_position_[1])
|
||||
rospy.logdebug("%s: yaw_error: %f\n", rospy.get_name(), yaw_error)
|
||||
rospy.logdebug("%s: current orientation: %f\n", rospy.get_name(), self.current_orientation_)
|
||||
rospy.logdebug("%s: desired orientation: %f\n", rospy.get_name(), self.desired_orientation_)
|
||||
rospy.logdebug("%s: distance_to_goal: %f\n", rospy.get_name(), distance_to_goal)
|
||||
rospy.logdebug("%s: control_input.linear.x %f\n", rospy.get_name(), control_input.linear.x)
|
||||
rospy.logdebug("%s: control_input.angular.z %f\n", rospy.get_name(), control_input.angular.z)
|
||||
|
||||
if distance_to_goal <= 0.2:
|
||||
break
|
||||
loop_rate.sleep()
|
||||
|
||||
return GotoWaypointResponse()
|
||||
|
||||
def odomCallback(self, odometry_msg):
|
||||
self.current_position_[0] = odometry_msg.pose.pose.position.x
|
||||
self.current_position_[1] = odometry_msg.pose.pose.position.y
|
||||
self.current_position_[2] = odometry_msg.pose.pose.position.z
|
||||
(r, p, y) = tf.transformations.euler_from_quaternion([odometry_msg.pose.pose.orientation.x, odometry_msg.pose.pose.orientation.y, odometry_msg.pose.pose.orientation.z, odometry_msg.pose.pose.orientation.w])
|
||||
self.current_orientation_ = wrapAngle(y)
|
||||
return
|
||||
|
||||
def wrapAngle(angle):
|
||||
"""wrapAngle
|
||||
|
||||
Calculates angles values between 0 and 2pi"""
|
||||
return (angle + ( 2.0 * math.pi * math.floor( ( math.pi - angle ) / ( 2.0 * math.pi ) ) ) )
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node('control_quadrotor', log_level=rospy.INFO)
|
||||
rospy.loginfo("%s: starting quadrotor controller", rospy.get_name())
|
||||
|
||||
controller = Controller()
|
||||
rospy.spin()
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# ROS imports
|
||||
import roslib; roslib.load_manifest('control_turtlebot')
|
||||
import rospy
|
||||
import tf
|
||||
import math
|
||||
|
||||
#ROS messages
|
||||
from geometry_msgs.msg import Twist
|
||||
from nav_msgs.msg import Odometry
|
||||
from control_turtlebot.srv import GotoWaypoint, GotoWaypointResponse, FindPathToGoal, FindPathToGoalResponse, FindPathToGoalRequest
|
||||
|
||||
#Numpy
|
||||
import numpy as np
|
||||
|
||||
class Controller(object):
|
||||
|
||||
def __init__(self):
|
||||
self.odometry_sub_ = rospy.Subscriber("/odom", Odometry, self.odomCallback, queue_size = 1)
|
||||
self.control_input_pub_ = rospy.Publisher("/mobile_base/commands/velocity", Twist, queue_size = 1)
|
||||
|
||||
self.serv_ = rospy.Service('/controller_turtlebot/goto',
|
||||
GotoWaypoint,
|
||||
self.calculateControlInput)
|
||||
|
||||
self.current_position_ = np.zeros(2)
|
||||
self.current_orientation_ = 0.0
|
||||
|
||||
self.desired_position_ = np.zeros(2)
|
||||
self.desired_orientation_ = 0.0
|
||||
|
||||
|
||||
rospy.wait_for_service('/controller_turtlebot/find_path_to_goal')
|
||||
try:
|
||||
self.find_path_to_goal_serv_ = rospy.ServiceProxy('/controller_turtlebot/find_path_to_goal', FindPathToGoal)
|
||||
except rospy.ServiceException, e:
|
||||
print "Service call failed: %s"%e
|
||||
|
||||
return
|
||||
|
||||
def calculateControlInput(self, req):
|
||||
|
||||
planner_request = FindPathToGoalRequest()
|
||||
planner_request.goal_state_x = req.goal_state_x
|
||||
planner_request.goal_state_y = req.goal_state_y
|
||||
#planner_request.goal_state_z = req.goal_state_z
|
||||
|
||||
planner_response = self.find_path_to_goal_serv_(planner_request)
|
||||
|
||||
for pose in planner_response.poses:
|
||||
#print pose
|
||||
control_input = Twist()
|
||||
self.desired_position_[0] = pose.position.x
|
||||
self.desired_position_[1] = pose.position.y
|
||||
#self.desired_position_[2] = pose.position.z
|
||||
|
||||
loop_rate = rospy.Rate(100) # 10Hz
|
||||
orientation_approach = False
|
||||
while not rospy.is_shutdown():
|
||||
inc_x = self.desired_position_[0] - self.current_position_[0]
|
||||
inc_y = self.desired_position_[1] - self.current_position_[1]
|
||||
|
||||
self.desired_orientation_ = wrapAngle(math.atan2(inc_y, inc_x))
|
||||
yaw_error = wrapAngle(self.desired_orientation_ - self.current_orientation_)
|
||||
distance_to_goal = math.sqrt(math.pow(inc_x, 2.0) + math.pow(inc_y, 2.0))
|
||||
|
||||
if abs(yaw_error) > 0.04 and not orientation_approach:
|
||||
control_input.angular.x = 0.0
|
||||
control_input.angular.y = 0.0
|
||||
control_input.angular.z = yaw_error * 1.0
|
||||
|
||||
control_input.linear.x = 0.08
|
||||
control_input.linear.y = 0.0
|
||||
control_input.linear.z = 0.0
|
||||
else:
|
||||
control_input.angular.x = 0.0
|
||||
control_input.angular.y = 0.0
|
||||
control_input.angular.z = 0.0
|
||||
|
||||
orientation_approach = True
|
||||
liner_speed = abs(distance_to_goal) * 0.5
|
||||
|
||||
if liner_speed < 0.1:
|
||||
control_input.linear.x = 0.1
|
||||
elif liner_speed > 0.2:
|
||||
control_input.linear.x = 0.2
|
||||
else:
|
||||
control_input.linear.x = liner_speed
|
||||
|
||||
control_input.linear.y = 0.0
|
||||
control_input.linear.z = 0.0
|
||||
|
||||
self.control_input_pub_.publish(control_input)
|
||||
|
||||
rospy.logdebug("%s: current position: [%f, %f]\n", rospy.get_name(), self.current_position_[0], self.current_position_[1])
|
||||
rospy.logdebug("%s: desired position: [%f, %f]\n", rospy.get_name(), self.desired_position_[0], self.desired_position_[1])
|
||||
rospy.logdebug("%s: yaw_error: %f\n", rospy.get_name(), yaw_error)
|
||||
rospy.logdebug("%s: current orientation: %f\n", rospy.get_name(), self.current_orientation_)
|
||||
rospy.logdebug("%s: desired orientation: %f\n", rospy.get_name(), self.desired_orientation_)
|
||||
rospy.logdebug("%s: distance_to_goal: %f\n", rospy.get_name(), distance_to_goal)
|
||||
rospy.logdebug("%s: control_input.linear.x %f\n", rospy.get_name(), control_input.linear.x)
|
||||
rospy.logdebug("%s: control_input.angular.z %f\n", rospy.get_name(), control_input.angular.z)
|
||||
|
||||
if distance_to_goal <= 0.2:
|
||||
break
|
||||
loop_rate.sleep()
|
||||
|
||||
return GotoWaypointResponse()
|
||||
|
||||
def odomCallback(self, odometry_msg):
|
||||
self.current_position_[0] = odometry_msg.pose.pose.position.x
|
||||
self.current_position_[1] = odometry_msg.pose.pose.position.y
|
||||
(r, p, y) = tf.transformations.euler_from_quaternion([odometry_msg.pose.pose.orientation.x, odometry_msg.pose.pose.orientation.y, odometry_msg.pose.pose.orientation.z, odometry_msg.pose.pose.orientation.w])
|
||||
self.current_orientation_ = wrapAngle(y)
|
||||
return
|
||||
|
||||
def wrapAngle(angle):
|
||||
"""wrapAngle
|
||||
|
||||
Calculates angles values between 0 and 2pi"""
|
||||
return (angle + ( 2.0 * math.pi * math.floor( ( math.pi - angle ) / ( 2.0 * math.pi ) ) ) )
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node('control_turtlebot', log_level=rospy.INFO)
|
||||
rospy.loginfo("%s: starting turtlebot controller", rospy.get_name())
|
||||
|
||||
controller = Controller()
|
||||
rospy.spin()
|
|
@ -0,0 +1,136 @@
|
|||
// ROS
|
||||
#include <ros/ros.h>
|
||||
|
||||
// ROS LaserScan tools
|
||||
#include <laser_geometry/laser_geometry.h>
|
||||
|
||||
// ROS messages
|
||||
#include <geometry_msgs/Pose.h>
|
||||
#include <message_filters/subscriber.h>
|
||||
#include <nav_msgs/Odometry.h>
|
||||
#include <sensor_msgs/LaserScan.h>
|
||||
#include <sensor_msgs/PointCloud.h>
|
||||
#include <std_msgs/ColorRGBA.h>
|
||||
#include <std_msgs/Bool.h>
|
||||
#include <visualization_msgs/MarkerArray.h>
|
||||
|
||||
// ROS services
|
||||
#include <std_srvs/Empty.h>
|
||||
|
||||
// ROS tf
|
||||
#include <tf/message_filter.h>
|
||||
#include <tf/transform_listener.h>
|
||||
|
||||
// Octomap
|
||||
#include <octomap/octomap.h>
|
||||
#include <octomap_msgs/conversions.h>
|
||||
//#include <octomap_msgs/OctomapBinary.h>
|
||||
#include <octomap_msgs/GetOctomap.h>
|
||||
typedef octomap_msgs::GetOctomap OctomapSrv;
|
||||
//#include <laser_octomap/BoundingBoxQuery.h>
|
||||
//typedef laser_octomap::BoundingBoxQuery BBXSrv;
|
||||
#include <octomap_ros/conversions.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
void stopNode(int sig)
|
||||
{
|
||||
ros::shutdown();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/// CLASS DEFINITION ===========================================================
|
||||
class LaserScanToPointCloud
|
||||
{
|
||||
public:
|
||||
// Constructor and destructor
|
||||
LaserScanToPointCloud();
|
||||
// virtual ~LaserScanToPointCloud();
|
||||
|
||||
// Callbacks
|
||||
void laserScanCallback(const sensor_msgs::LaserScanConstPtr& scan);
|
||||
|
||||
private:
|
||||
|
||||
// ROS
|
||||
ros::NodeHandle node_hand_;
|
||||
ros::Subscriber laser_scan_sub_;
|
||||
ros::Publisher pc_pub_;
|
||||
|
||||
//TF
|
||||
tf::TransformListener listener_;
|
||||
|
||||
//PC
|
||||
laser_geometry::LaserProjection projector_;
|
||||
};
|
||||
|
||||
/// Constructor and destructor =================================================
|
||||
LaserScanToPointCloud::LaserScanToPointCloud(){
|
||||
//=======================================================================
|
||||
// Subscribers
|
||||
//=======================================================================
|
||||
//Mission Flag (feedback)
|
||||
laser_scan_sub_ = node_hand_.subscribe("/scan", 2, &LaserScanToPointCloud::laserScanCallback, this);
|
||||
|
||||
//=======================================================================
|
||||
// Publishers
|
||||
//=======================================================================
|
||||
pc_pub_ = node_hand_.advertise<sensor_msgs::PointCloud2>("pc_from_scan", 2, true);
|
||||
// // Waiting for mission flag
|
||||
// ros::Rate loop_rate(10);
|
||||
// if(!mission_flag_available_)
|
||||
// ROS_WARN("Waiting for mission_flag");
|
||||
// while (ros::ok() && !mission_flag_available_)
|
||||
// {
|
||||
// ros::spinOnce();
|
||||
// loop_rate.sleep();
|
||||
// }
|
||||
// //Navigation data (feedback)
|
||||
// odomSub_ = node_hand_.subscribe("/pose_ekf_slam/odometry", 1, &LaserScanToPointCloud::odomCallback, this);
|
||||
// nav_sts_available_ = false;
|
||||
// while (ros::ok() && !nav_sts_available_)
|
||||
// {
|
||||
// ros::spinOnce();
|
||||
// loop_rate.sleep();
|
||||
// }
|
||||
}
|
||||
|
||||
void LaserScanToPointCloud::laserScanCallback(const sensor_msgs::LaserScanConstPtr &scan){
|
||||
if(!listener_.waitForTransform(
|
||||
scan->header.frame_id,
|
||||
"/odom",
|
||||
scan->header.stamp + ros::Duration().fromSec(scan->ranges.size()*scan->time_increment),
|
||||
ros::Duration(1.0))){
|
||||
return;
|
||||
}
|
||||
|
||||
sensor_msgs::PointCloud2 cloud;
|
||||
projector_.transformLaserScanToPointCloud("/base_link",*scan,
|
||||
cloud,listener_);
|
||||
|
||||
// Do something with cloud.
|
||||
pc_pub_.publish(cloud);
|
||||
}
|
||||
|
||||
/// MAIN NODE FUNCTION =========================================================
|
||||
int main(int argc, char** argv){
|
||||
|
||||
//=======================================================================
|
||||
// Override SIGINT handler
|
||||
//=======================================================================
|
||||
signal(SIGINT, stopNode);
|
||||
|
||||
// Init ROS node
|
||||
ros::init(argc, argv, "laserscan_to_pointcloud");
|
||||
ros::NodeHandle private_nh("~");
|
||||
|
||||
// Constructor
|
||||
LaserScanToPointCloud laserscan_to_pc;
|
||||
|
||||
// Spin
|
||||
ros::spin();
|
||||
|
||||
// Exit main function without errors
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
## Service
|
||||
float32 goal_state_x
|
||||
float32 goal_state_y
|
||||
float32 goal_state_z
|
||||
---
|
||||
geometry_msgs/Pose[] poses
|
|
@ -0,0 +1,5 @@
|
|||
## Service
|
||||
float32 goal_state_x
|
||||
float32 goal_state_y
|
||||
float32 goal_state_z
|
||||
---
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue