diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0cbc99c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,72 @@
+# Created by https://www.toptal.com/developers/gitignore/api/cmake,visualstudiocode,c++
+# Edit at https://www.toptal.com/developers/gitignore?templates=cmake,visualstudiocode,c++
+
+### C++ ###
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+### CMake ###
+CMakeLists.txt.user
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Testing
+Makefile
+cmake_install.cmake
+install_manifest.txt
+compile_commands.json
+CTestTestfile.cmake
+_deps
+
+### CMake Patch ###
+# External projects
+*-prefix/
+
+### VisualStudioCode ###
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+### VisualStudioCode Patch ###
+# Ignore all local history of files
+.history
+.ionide
+
+# End of https://www.toptal.com/developers/gitignore/api/cmake,visualstudiocode,c++
+.vscode/settings.json
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8842b0b..38ce075 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,7 +35,7 @@ catkin_package(
add_library(${PROJECT_NAME}
src/common.cpp
src/${PROJECT_NAME}.cpp
- src/spiral_stc.cpp
+ src/boustrophedon_stc.cpp
)
add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(${PROJECT_NAME}
@@ -65,13 +65,13 @@ catkin_install_python(
if (CATKIN_ENABLE_TESTING)
catkin_add_gtest(test_common test/src/test_common.cpp test/src/util.cpp src/common.cpp)
- catkin_add_gtest(test_spiral_stc test/src/test_spiral_stc.cpp test/src/util.cpp src/spiral_stc.cpp src/common.cpp src/${PROJECT_NAME}.cpp)
- add_dependencies(test_spiral_stc ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
- target_link_libraries(test_spiral_stc ${catkin_LIBRARIES})
+ catkin_add_gtest(test_boustrophedon_stc test/src/test_boustrophedon_stc.cpp test/src/util.cpp src/boustrophedon_stc.cpp src/common.cpp src/${PROJECT_NAME}.cpp)
+ add_dependencies(test_boustrophedon_stc ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
+ target_link_libraries(test_boustrophedon_stc ${catkin_LIBRARIES})
find_package(OpenCV)
include_directories(${OpenCV_INCLUDE_DIRS})
- target_link_libraries(test_spiral_stc ${OpenCV_LIBRARIES})
+ target_link_libraries(test_boustrophedon_stc ${OpenCV_LIBRARIES})
add_rostest(test/${PROJECT_NAME}/test_${PROJECT_NAME}.test)
diff --git a/README.md b/README.md
index a4b23ea..c0c9e56 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,19 @@
-# Full Coverage Path Planner (FCPP)
+# Boustrophedon Full Coverage Path Planner (Modified)
+## Acknowledgement
+
+This package is a modification of the Full Coverage Path Planner package from Nobleo.
+
+It is modified such that a Boustrophedon Pattern is used to plan the path rather than a Spiral algorithm in the original package.
+
+Refer to the original package here: http://wiki.ros.org/full_coverage_path_planner
## Overview
-This package provides an implementation of a Full Coverage Path Planner (FCPP) using the Backtracking Spiral Algorithm (BSA), see [1].
+This package provides an implementation of a Full Coverage Path Planner (FCPP) using the Boustrophedon Pattern. see [1] and [2].
This packages acts as a global planner plugin to the Move Base package (http://wiki.ros.org/move_base).
-![BSA](doc/fcpp_robot_0_5m_plus_tool_0_2m.png)
+![BSA](doc/fcpp_modified_boustrophedon.png)
The user can configure robot radius and tool radius separately:
@@ -15,17 +22,19 @@ The user can configure robot radius and tool radius separately:
**Keywords:** coverage path planning, move base
-### License
+### Authors
Apache 2.0
+**Package modified by Ethan Kim, ethanc.kim@uwaterloo.ca, MapaRobo Inc.**
+
**Author(s): Yury Brodskiy, Ferry Schoenmakers, Tim Clephas, Jerrel Unkel, Loy van Beek, Cesar lopez**
**Maintainer: Cesar Lopez, cesar.lopez@nobleo.nl**
**Affiliation: Nobleo Projects BV, Eindhoven, the Netherlands**
-The Full Coverage Path Planner package has been tested under [ROS] Melodic and Ubuntu 18.04.
+The Modified package has been tested under [ROS] Noetic and Ubuntu 20.04.
## Installation
@@ -57,8 +66,8 @@ All tests can be run using:
#### test_common
Unit test that checks the basic functions used by the repository
-#### test_spiral_stc
-Unit test that checks the basis spiral algorithm for full coverage. The test is performed for different situations to check that the algorithm coverage the accessible map cells. A test is also performed in randomly generated maps.
+#### test_boustrophedon_stc
+Unit test that checks the basis boustrophedon algorithm for full coverage. The test is performed for different situations to check that the algorithm coverage the accessible map cells. A test is also performed in randomly generated maps.
#### test_full_coverage_path_planner.test
ROS system test that checks the full coverage path planner together with a tracking pid. A simulation is run such that a robot moves to fully cover the accessible cells in a given map.
@@ -131,8 +140,8 @@ The CoverageProgressNode keeps track of coverage progress. It does this by perio
## Plugins
-### full_coverage_path_planner/SpiralSTC
-For use in move_base(\_flex) as "base_global_planner"="full_coverage_path_planner/SpiralSTC". It uses global_cost_map and global_costmap/robot_radius.
+### full_coverage_path_planner/BoustrophedonSTC
+For use in move_base(\_flex) as "base_global_planner"="full_coverage_path_planner/BoustrophedonSTC". It uses global_cost_map and global_costmap/robot_radius.
#### Parameters
@@ -142,18 +151,10 @@ For use in move_base(\_flex) as "base_global_planner"="full_coverage_path_planne
## References
-[1] GONZALEZ, Enrique, et al. BSA: A complete coverage algorithm. In: Proceedings of the 2005 IEEE International Conference on Robotics and Automation. IEEE, 2005. p. 2040-2044.
-
-## Bugs & Feature Requests
-
-Please report bugs and request features using the [Issue Tracker](https://github.com/nobleo/full_coverage_path_planner/issues).
-
-
-[ROS]: http://www.ros.org
-[rviz]: http://wiki.ros.org/rviz
-[MBF]: http://wiki.ros.org/move_base_flex
+[1] Choset, Howie, and Philippe Pignon. "Coverage path planning: The boustrophedon cellular decomposition." Field and service robotics. Springer, London, 1998.
+[2] Zelinsky, Alexander, et al. "Planning paths of complete coverage of an unstructured environment by a mobile robot." Proceedings of international conference on advanced robotics. Vol. 13. 1993.
-## Acknowledgments
+## Acknowledgments from Original Authors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/full_coverage_path_planner/param/costmap_common_params.yaml b/test/full_coverage_path_planner/param/costmap_common_params.yaml
new file mode 100644
index 0000000..a689051
--- /dev/null
+++ b/test/full_coverage_path_planner/param/costmap_common_params.yaml
@@ -0,0 +1,19 @@
+transform_tolerance: 0.2
+
+map_topic: map
+
+footprint: [[0.46, 0.28], [-0.50, 0.28], [-0.50, -0.28], [0.46, -0.28]]
+footprint_padding: 0.05
+inflation_radius: 0.55
+
+#observation_sources: point_cloud_sensor
+#obstacle_range: 2.5
+#raytrace_range: 3.0
+#point_cloud_sensor: { sensor_frame: d435i_link,
+# data_type: PointCloud2,
+# topic: /points_filtered,
+# marking: true,
+# clearing: true,
+# expected_update_rate: 1.0
+# max_obstacle_height: 0.75
+# min_obstacle_height: 0.05 }
\ No newline at end of file
diff --git a/test/full_coverage_path_planner/param/global_costmap_params.yaml b/test/full_coverage_path_planner/param/global_costmap_params.yaml
new file mode 100644
index 0000000..e9a0668
--- /dev/null
+++ b/test/full_coverage_path_planner/param/global_costmap_params.yaml
@@ -0,0 +1,7 @@
+global_costmap:
+ global_frame: map
+ robot_base_frame: base_link
+ update_frequency: 5.0
+ publish_frequency: 1.0
+ static_map: true
+ always_send_full_costmap: true
\ No newline at end of file
diff --git a/test/full_coverage_path_planner/param/local_costmap_params.yaml b/test/full_coverage_path_planner/param/local_costmap_params.yaml
index 5147ed1..821db1b 100644
--- a/test/full_coverage_path_planner/param/local_costmap_params.yaml
+++ b/test/full_coverage_path_planner/param/local_costmap_params.yaml
@@ -1,10 +1,10 @@
local_costmap:
global_frame: odom
robot_base_frame: base_link
- update_frequency: 10.0
+ update_frequency: 5.0
publish_frequency: 5.0
width: 5.0
height: 5.0
resolution: 0.05
static_map: false
- rolling_window: true
+ rolling_window: true
\ No newline at end of file
diff --git a/test/full_coverage_path_planner/param/planners.yaml b/test/full_coverage_path_planner/param/planners.yaml
index a59da1f..d47b710 100644
--- a/test/full_coverage_path_planner/param/planners.yaml
+++ b/test/full_coverage_path_planner/param/planners.yaml
@@ -1,3 +1,3 @@
planners:
- - name: 'SpiralSTC'
- type: 'full_coverage_path_planner/SpiralSTC'
+ - name: 'BoustrophedonSTC'
+ type: 'full_coverage_path_planner/BoustrophedonSTC'
diff --git a/test/full_coverage_path_planner/test_full_coverage_path_planner.launch b/test/full_coverage_path_planner/test_full_coverage_path_planner.launch
index ffa9c89..91d81c2 100644
--- a/test/full_coverage_path_planner/test_full_coverage_path_planner.launch
+++ b/test/full_coverage_path_planner/test_full_coverage_path_planner.launch
@@ -1,34 +1,39 @@
-
+
-
+
+
+
+
-
-
+
+
+
-
+
-
+
+
@@ -49,7 +54,7 @@
-
+
diff --git a/test/full_coverage_path_planner/test_full_coverage_path_planner_plugin.launch b/test/full_coverage_path_planner/test_full_coverage_path_planner_plugin.launch
index 97d0d9d..d61efd5 100644
--- a/test/full_coverage_path_planner/test_full_coverage_path_planner_plugin.launch
+++ b/test/full_coverage_path_planner/test_full_coverage_path_planner_plugin.launch
@@ -1,7 +1,7 @@
-
+
@@ -11,13 +11,13 @@
-
-
+
+
-
+
diff --git a/test/src/test_spiral_stc.cpp b/test/src/test_boustrophedon_stc.cpp
similarity index 89%
rename from test/src/test_spiral_stc.cpp
rename to test/src/test_boustrophedon_stc.cpp
index 8335255..5d23a07 100644
--- a/test/src/test_spiral_stc.cpp
+++ b/test/src/test_boustrophedon_stc.cpp
@@ -24,7 +24,7 @@
#include
#include
-#include
+#include
#include
cv::Mat drawMap(std::vector > const& grid);
@@ -35,15 +35,15 @@ cv::Mat drawPath(const cv::Mat &mapImg,
std::list &path);
/*
- * On a map with nothing on it, spiral_stc should cover all the nodes of the map
+ * On a map with nothing on it, boustrophedon_stc should cover all the nodes of the map
*/
-TEST(TestSpiralStc, testFillEmptyMap)
+TEST(TestBoustrophedonStc, testFillEmptyMap)
{
std::vector > grid = makeTestGrid(4, 4, false);
Point_t start = {0, 0};
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -54,7 +54,7 @@ TEST(TestSpiralStc, testFillEmptyMap)
/*
* On a map with a single obstacle, all the other nodes should still be visited.
*/
-TEST(TestSpiralStc, testFillMapWithOneObstacle)
+TEST(TestBoustrophedonStc, testFillMapWithOneObstacle)
{
/*
* [s 0 0 0]
@@ -67,7 +67,7 @@ TEST(TestSpiralStc, testFillMapWithOneObstacle)
Point_t start = {0, 0};
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -82,7 +82,7 @@ TEST(TestSpiralStc, testFillMapWithOneObstacle)
/*
* In a map with 2 obstacles, still the complete map should be covered except for those 2 obstacles
*/
-TEST(TestSpiralStc, testFillMapWith2Obstacles)
+TEST(TestBoustrophedonStc, testFillMapWith2Obstacles)
{
/*
* [s 0 0 0]
@@ -96,7 +96,7 @@ TEST(TestSpiralStc, testFillMapWith2Obstacles)
Point_t start = {0, 0};
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -111,7 +111,7 @@ TEST(TestSpiralStc, testFillMapWith2Obstacles)
/*
* On a 4x4 map where the opposite right half of the map is blocked, we can cover only the 4x2 reachable nodes
*/
-TEST(TestSpiralStc, testFillMapWithHalfBlocked)
+TEST(TestBoustrophedonStc, testFillMapWithHalfBlocked)
{
/*
* [s 0 1 0]
@@ -127,7 +127,7 @@ TEST(TestSpiralStc, testFillMapWithHalfBlocked)
Point_t start = {0, 0};
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -141,9 +141,9 @@ TEST(TestSpiralStc, testFillMapWithHalfBlocked)
/*
* On a map with a wall almost blocking off a half of the map, but leaving a gap to the other side,
- * spiral_stc should still cover all reachable nodes
+ * boustrophedon_stc should still cover all reachable nodes
*/
-TEST(TestSpiralStc, testFillMapWithWall)
+TEST(TestBoustrophedonStc, testFillMapWithWall)
{
/*
* [s 0 1 0]
@@ -158,7 +158,7 @@ TEST(TestSpiralStc, testFillMapWithWall)
Point_t start = {0, 0};
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -173,7 +173,7 @@ TEST(TestSpiralStc, testFillMapWithWall)
/*
* This test case features a very short dead-end
*/
-TEST(TestSpiralStc, testDeadEnd1)
+TEST(TestBoustrophedonStc, testDeadEnd1)
{
/*
* [0 0 1 0]
@@ -189,7 +189,7 @@ TEST(TestSpiralStc, testDeadEnd1)
Point_t start = {1, 2};
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -208,10 +208,10 @@ TEST(TestSpiralStc, testDeadEnd1)
/*
* This test case is an extension of testDeadEnd1, where the top row is also covered as an obstacle.
* The top row is covered but the obstacle from testDeadEnd1 is shifted downwards
- * in an attempt to see if SpiralSTC also fails when a dead-end is not on the edge of the map
+ * in an attempt to see if BoustrophedonSTC also fails when a dead-end is not on the edge of the map
* (but below a row of obstacles)
*/
-TEST(TestSpiralStc, testDeadEnd1WithTopRow)
+TEST(TestBoustrophedonStc, testDeadEnd1WithTopRow)
{
/*
* [1 1 1 1]
@@ -233,7 +233,7 @@ TEST(TestSpiralStc, testDeadEnd1WithTopRow)
Point_t start = {1, 3};
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -252,7 +252,7 @@ TEST(TestSpiralStc, testDeadEnd1WithTopRow)
/*
* This test case features a very short dead-end
*/
-TEST(TestSpiralStc, testDeadEnd2)
+TEST(TestBoustrophedonStc, testDeadEnd2)
{
/*
* [1 0 0 0]
@@ -268,7 +268,7 @@ TEST(TestSpiralStc, testDeadEnd2)
Point_t start = {3, 0};
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -287,7 +287,7 @@ TEST(TestSpiralStc, testDeadEnd2)
/*
* This test case features a very short dead-end
*/
-TEST(TestSpiralStc, testDeadEnd3)
+TEST(TestBoustrophedonStc, testDeadEnd3)
{
/*
* [0 0 0 0 0 0 1 0 0]
@@ -309,7 +309,7 @@ TEST(TestSpiralStc, testDeadEnd3)
Point_t start = {5, 2};
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -328,7 +328,7 @@ TEST(TestSpiralStc, testDeadEnd3)
/*
* This test case features a very short dead-end
*/
-TEST(TestSpiralStc, testDeadEnd3WithTopRow)
+TEST(TestBoustrophedonStc, testDeadEnd3WithTopRow)
{
/*
* [1 1 1 1 1 1 1 1 1]
@@ -359,7 +359,7 @@ TEST(TestSpiralStc, testDeadEnd3WithTopRow)
Point_t start = {5, 3}; // NOLINT
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);
@@ -496,7 +496,7 @@ Point_t findStart(std::vector > const& grid)
5. On each coordinate in path, fill pixel at that coordinate in pathImg
6. pathImg and floodfilledImg should be identical
*/
-TEST(TestSpiralStc, testRandomMap)
+TEST(TestBoustrophedonStc, testRandomMap)
{
// Seed pseudorandom sequence to create *reproducible test
unsigned int seed = 12345;
@@ -515,7 +515,7 @@ TEST(TestSpiralStc, testRandomMap)
cv::Mat mapImg = drawMap(grid);
Point_t start = findStart(grid);
int multiple_pass_counter, visited_counter;
- std::list path = full_coverage_path_planner::SpiralSTC::spiral_stc(grid,
+ std::list path = full_coverage_path_planner::BoustrophedonSTC::boustrophedon_stc(grid,
start,
multiple_pass_counter,
visited_counter);