Skip to content

Commit f694051

Browse files
committed
Rename Spiral to Boustrophedon and Updated README.md accordingly
1 parent 8a446b3 commit f694051

15 files changed

+112
-107
lines changed

CMakeLists.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ catkin_package(
3535
add_library(${PROJECT_NAME}
3636
src/common.cpp
3737
src/${PROJECT_NAME}.cpp
38-
src/spiral_stc.cpp
38+
src/boustrophedon_stc.cpp
3939
)
4040
add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
4141
target_link_libraries(${PROJECT_NAME}
@@ -65,13 +65,13 @@ catkin_install_python(
6565
if (CATKIN_ENABLE_TESTING)
6666
catkin_add_gtest(test_common test/src/test_common.cpp test/src/util.cpp src/common.cpp)
6767

68-
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)
69-
add_dependencies(test_spiral_stc ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
70-
target_link_libraries(test_spiral_stc ${catkin_LIBRARIES})
68+
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)
69+
add_dependencies(test_boustrophedon_stc ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
70+
target_link_libraries(test_boustrophedon_stc ${catkin_LIBRARIES})
7171

7272
find_package(OpenCV)
7373
include_directories(${OpenCV_INCLUDE_DIRS})
74-
target_link_libraries(test_spiral_stc ${OpenCV_LIBRARIES})
74+
target_link_libraries(test_boustrophedon_stc ${OpenCV_LIBRARIES})
7575

7676
add_rostest(test/${PROJECT_NAME}/test_${PROJECT_NAME}.test)
7777

README.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1-
# Full Coverage Path Planner (FCPP)
1+
# Boustrophedon Full Coverage Path Planner (Modified)
22

3+
## Acknowledgement
4+
5+
This package is a modification of the Full Coverage Path Planner package from Nobleo.
6+
7+
It is modified such that a Boustrophedon Pattern is used to plan the path rather than a Spiral algorithm in the original package.
8+
9+
Refer to the original package here: http://wiki.ros.org/full_coverage_path_planner
310
## Overview
411

5-
This package provides an implementation of a Full Coverage Path Planner (FCPP) using the Backtracking Spiral Algorithm (BSA), see [1].
12+
This package provides an implementation of a Full Coverage Path Planner (FCPP) using the Boustrophedon Pattern. see [1] and [2].
613

714
This packages acts as a global planner plugin to the Move Base package (http://wiki.ros.org/move_base).
815

9-
![BSA](doc/fcpp_robot_0_5m_plus_tool_0_2m.png)
16+
![BSA](doc/fcpp_modified_boustrophedon.png)
1017

1118
The user can configure robot radius and tool radius separately:
1219

@@ -15,17 +22,19 @@ The user can configure robot radius and tool radius separately:
1522

1623
**Keywords:** coverage path planning, move base
1724

18-
### License
25+
### Authors
1926

2027
Apache 2.0
2128

29+
**Package modified by Ethan Kim, ethanc.kim@uwaterloo.ca, MapaRobo Inc.**
30+
2231
**Author(s): Yury Brodskiy, Ferry Schoenmakers, Tim Clephas, Jerrel Unkel, Loy van Beek, Cesar lopez**
2332

2433
**Maintainer: Cesar Lopez, cesar.lopez@nobleo.nl**
2534

2635
**Affiliation: Nobleo Projects BV, Eindhoven, the Netherlands**
2736

28-
The Full Coverage Path Planner package has been tested under [ROS] Melodic and Ubuntu 18.04.
37+
The Modified package has been tested under [ROS] Noetic and Ubuntu 20.04.
2938

3039
## Installation
3140

@@ -57,8 +66,8 @@ All tests can be run using:
5766
#### test_common
5867
Unit test that checks the basic functions used by the repository
5968

60-
#### test_spiral_stc
61-
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.
69+
#### test_boustrophedon_stc
70+
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.
6271

6372
#### test_full_coverage_path_planner.test
6473
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
131140

132141

133142
## Plugins
134-
### full_coverage_path_planner/SpiralSTC
135-
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.
143+
### full_coverage_path_planner/BoustrophedonSTC
144+
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.
136145

137146
#### Parameters
138147

@@ -142,18 +151,10 @@ For use in move_base(\_flex) as "base_global_planner"="full_coverage_path_planne
142151

143152
## References
144153

145-
[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.
146-
147-
## Bugs & Feature Requests
148-
149-
Please report bugs and request features using the [Issue Tracker](https://github.com/nobleo/full_coverage_path_planner/issues).
150-
151-
152-
[ROS]: http://www.ros.org
153-
[rviz]: http://wiki.ros.org/rviz
154-
[MBF]: http://wiki.ros.org/move_base_flex
154+
[1] Choset, Howie, and Philippe Pignon. "Coverage path planning: The boustrophedon cellular decomposition." Field and service robotics. Springer, London, 1998.
155+
[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.
155156

156-
## Acknowledgments
157+
## Acknowledgments from Original Authors
157158

158159
<!--
159160
ROSIN acknowledgement from the ROSIN press kit

doc/fcpp_modified_boustrophedon.png

27.3 KB
Loading

fcpp_plugin.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<library path="lib/libfull_coverage_path_planner">
2-
<class name="full_coverage_path_planner/SpiralSTC" type="full_coverage_path_planner::SpiralSTC" base_class_type="nav_core::BaseGlobalPlanner">
2+
<class name="full_coverage_path_planner/BoustrophedonSTC" type="full_coverage_path_planner::BoustrophedonSTC" base_class_type="nav_core::BaseGlobalPlanner">
33
<description>
4-
Plans a path that covers all accessible points in a costmap by using Spiral-STC.
5-
Spiral-STC works by following the walls and spiraling inwards until it cannot go further.
6-
Then it uses A* to go back outside of the current spiral and then spirals again.
4+
Plans a path that covers all accessible points in a costmap by using Boustrophedon-STC (Spanning Tree Coverage).
5+
In essence, the robot moves forward until an obstacle or visited node is met, then turns right or left (making a boustrophedon pattern)
6+
When stuck while completing a boustrophedon pattern, use A* to get out again and start a new boustrophedon, until A* can't find a path to uncovered cells
77
</description>
88
</class>
99
</library>

include/full_coverage_path_planner/spiral_stc.h renamed to include/full_coverage_path_planner/boustrophedon_stc.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,34 @@
2020

2121
using std::string;
2222

23-
#ifndef FULL_COVERAGE_PATH_PLANNER_SPIRAL_STC_H
24-
#define FULL_COVERAGE_PATH_PLANNER_SPIRAL_STC_H
23+
#ifndef FULL_COVERAGE_PATH_PLANNER_BOUSTROPHEDON_STC_H
24+
#define FULL_COVERAGE_PATH_PLANNER_BOUSTROPHEDON_STC_H
2525

2626
#include "full_coverage_path_planner/full_coverage_path_planner.h"
2727
namespace full_coverage_path_planner
2828
{
29-
class SpiralSTC : public nav_core::BaseGlobalPlanner, private full_coverage_path_planner::FullCoveragePathPlanner
29+
class BoustrophedonSTC : public nav_core::BaseGlobalPlanner, private full_coverage_path_planner::FullCoveragePathPlanner
3030
{
3131
public:
3232
/**
33-
* Find a path that spirals inwards from init until an obstacle is seen in the grid
33+
* Find a path that does the boustrophedon pattern starting from init until a dead end is reached in the grid
3434
* @param grid 2D grid of bools. true == occupied/blocked/obstacle
3535
* @param init start position
36-
* @param visited all the nodes visited by the spiral
37-
* @return list of nodes that form the spiral
36+
* @param visited all the nodes visited by the boustrophedon pattern
37+
* @return list of nodes that form the boustrophedon pattern
3838
*/
39-
static std::list<gridNode_t> spiral(std::vector<std::vector<bool> > const &grid, std::list<gridNode_t> &init,
39+
static std::list<gridNode_t> boustrophedon(std::vector<std::vector<bool> > const &grid, std::list<gridNode_t> &init,
4040
std::vector<std::vector<bool> > &visited);
4141

4242
/**
43-
* Perform Spiral-STC (Spanning Tree Coverage) coverage path planning.
44-
* In essence, the robot moves forward until an obstacle or visited node is met, then turns right (making a spiral)
45-
* When stuck in the middle of the spiral, use A* to get out again and start a new spiral, until a* can't find a path to uncovered cells
43+
* Perform Boustrophedon-STC (Spanning Tree Coverage) coverage path planning.
44+
* In essence, the robot moves forward until an obstacle or visited node is met, then turns right or left (making a boustrophedon pattern)
45+
* When stuck in the middle of the boustrophedon, use A* to get out again and start a new boustrophedon, until a* can't find a path to uncovered cells
4646
* @param grid
4747
* @param init
4848
* @return
4949
*/
50-
static std::list<Point_t> spiral_stc(std::vector<std::vector<bool> > const &grid,
50+
static std::list<Point_t> boustrophedon_stc(std::vector<std::vector<bool> > const &grid,
5151
Point_t &init,
5252
int &multiple_pass_counter,
5353
int &visited_counter);
@@ -72,4 +72,4 @@ class SpiralSTC : public nav_core::BaseGlobalPlanner, private full_coverage_path
7272
};
7373

7474
} // namespace full_coverage_path_planner
75-
#endif // FULL_COVERAGE_PATH_PLANNER_SPIRAL_STC_H
75+
#endif // FULL_COVERAGE_PATH_PLANNER_BOUSTROPHEDON_STC_H

include/full_coverage_path_planner/full_coverage_path_planner.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class FullCoveragePathPlanner
7979
/**
8080
* Convert internal representation of a to a ROS path
8181
* @param start Start pose of robot
82-
* @param goalpoints Goal points from Spiral Algorithm
82+
* @param goalpoints Goal points from Boustrophedon Algorithm
8383
* @param plan Output plan variable
8484
*/
8585
void parsePointlist2Plan(const geometry_msgs::PoseStamped& start, std::list<Point_t> const& goalpoints,
@@ -130,14 +130,14 @@ class FullCoveragePathPlanner
130130
bool initialized_;
131131
geometry_msgs::PoseStamped previous_goal_;
132132

133-
struct spiral_cpp_metrics_type
133+
struct boustrophedon_cpp_metrics_type
134134
{
135135
int visited_counter;
136136
int multiple_pass_counter;
137137
int accessible_counter;
138138
double total_area_covered;
139139
};
140-
spiral_cpp_metrics_type spiral_cpp_metrics_;
140+
boustrophedon_cpp_metrics_type boustrophedon_cpp_metrics_;
141141
};
142142

143143

package.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
<?xml version="1.0"?>
22
<package format="2">
33
<name>full_coverage_path_planner</name>
4-
<version>0.6.4</version>
5-
<description>Full coverage path planning provides a move_base_flex plugin that can plan a path that will fully cover a given area</description>
4+
<version>0.6.5</version>
5+
<description>
6+
Full coverage path planning provides a move_base_flex plugin that can plan a path that will fully cover a given area.
7+
This package has been modified such that a boustophedon pattern is used rather than a spiral algorithm.
8+
</description>
69
<author email="cesar.lopez@nobleo.nl">Cesar Lopez</author>
710
<author email="ferry.schoenmakers@nobleo.nl">Ferry Schoenmakers</author>
811
<author email="tim.clephas@nobleo.nl">Tim Clephas</author>
912
<author email="jerrel.unkel@nobleo.nl">Jerrel Unkel</author>
1013
<author>Loy van Beek</author>
1114
<author>Yury Brodskiy</author>
15+
<author email="ethanc.kim@uwaterloo.ca">Ethan Kim</author>
1216
<maintainer email="cesar.lopez@nobleo.nl">Cesar Lopez</maintainer>
1317

1418
<license>Apache 2.0</license>

src/spiral_stc.cpp renamed to src/boustrophedon_stc.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
#include <string>
88
#include <vector>
99

10-
#include "full_coverage_path_planner/spiral_stc.h"
10+
#include "full_coverage_path_planner/boustrophedon_stc.h"
1111
#include <pluginlib/class_list_macros.h>
1212

1313
// register this planner as a BaseGlobalPlanner plugin
14-
PLUGINLIB_EXPORT_CLASS(full_coverage_path_planner::SpiralSTC, nav_core::BaseGlobalPlanner)
14+
PLUGINLIB_EXPORT_CLASS(full_coverage_path_planner::BoustrophedonSTC, nav_core::BaseGlobalPlanner)
1515

1616
int pattern_dir_ = point;
1717

1818
namespace full_coverage_path_planner
1919
{
20-
void SpiralSTC::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_ros)
20+
void BoustrophedonSTC::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_ros)
2121
{
2222
if (!initialized_)
2323
{
@@ -42,7 +42,7 @@ void SpiralSTC::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_r
4242
}
4343
}
4444

45-
std::list<gridNode_t> SpiralSTC::spiral(std::vector<std::vector<bool> > const& grid, std::list<gridNode_t>& init,
45+
std::list<gridNode_t> BoustrophedonSTC::boustrophedon(std::vector<std::vector<bool> > const& grid, std::list<gridNode_t>& init,
4646
std::vector<std::vector<bool> >& visited)
4747
{
4848
int dx, dy, x2, y2, i, nRows = grid.size(), nCols = grid[0].size();
@@ -74,7 +74,7 @@ std::list<gridNode_t> SpiralSTC::spiral(std::vector<std::vector<bool> > const& g
7474
dy = -1;
7575
break;
7676
default:
77-
ROS_ERROR("Full Coverage Path Planner: NO INITIAL ROBOT DIRECTION CALCULATED. This is a logic error that must be fixed by editing spiral_stc.cpp. Will travel east for now.");
77+
ROS_ERROR("Full Coverage Path Planner: NO INITIAL ROBOT DIRECTION CALCULATED. This is a logic error that must be fixed by editing boustrophedon_stc.cpp. Will travel east for now.");
7878
robot_dir = east;
7979
dx = +1;
8080
dy = 0;
@@ -195,7 +195,7 @@ std::list<gridNode_t> SpiralSTC::spiral(std::vector<std::vector<bool> > const& g
195195
return pathNodes;
196196
}
197197

198-
std::list<Point_t> SpiralSTC::spiral_stc(std::vector<std::vector<bool> > const& grid,
198+
std::list<Point_t> BoustrophedonSTC::boustrophedon_stc(std::vector<std::vector<bool> > const& grid,
199199
Point_t& init,
200200
int &multiple_pass_counter,
201201
int &visited_counter)
@@ -228,10 +228,10 @@ std::list<Point_t> SpiralSTC::spiral_stc(std::vector<std::vector<bool> > const&
228228
while (goals.size() != 0)
229229
{
230230
// boustrophedon pattern from current position
231-
pathNodes = spiral(grid, pathNodes, visited);
231+
pathNodes = boustrophedon(grid, pathNodes, visited);
232232
#ifdef DEBUG_PLOT
233-
ROS_INFO("Visited grid updated after spiral:");
234-
printGrid(grid, visited, pathNodes, SpiralStart, pathNodes.back());
233+
ROS_INFO("Visited grid updated after boustrophedon:");
234+
printGrid(grid, visited, pathNodes, PatternStart, pathNodes.back());
235235
#endif
236236

237237
for (it = pathNodes.begin(); it != pathNodes.end(); ++it)
@@ -273,7 +273,7 @@ std::list<Point_t> SpiralSTC::spiral_stc(std::vector<std::vector<bool> > const&
273273

274274
#ifdef DEBUG_PLOT
275275
ROS_INFO("Grid with path marked as visited is:");
276-
gridNode_t SpiralStart = pathNodes.back();
276+
gridNode_t PatternStart = pathNodes.back();
277277
printGrid(grid, visited, pathNodes, pathNodes.front(), pathNodes.back());
278278
#endif
279279

@@ -282,7 +282,7 @@ std::list<Point_t> SpiralSTC::spiral_stc(std::vector<std::vector<bool> > const&
282282
return fullPath;
283283
}
284284

285-
bool SpiralSTC::makePlan(const geometry_msgs::PoseStamped& start, const geometry_msgs::PoseStamped& goal,
285+
bool BoustrophedonSTC::makePlan(const geometry_msgs::PoseStamped& start, const geometry_msgs::PoseStamped& goal,
286286
std::vector<geometry_msgs::PoseStamped>& plan)
287287
{
288288
if (!initialized_)
@@ -328,22 +328,22 @@ bool SpiralSTC::makePlan(const geometry_msgs::PoseStamped& start, const geometry
328328
printGrid(grid, grid, printPath);
329329
#endif
330330

331-
std::list<Point_t> goalPoints = spiral_stc(grid,
331+
std::list<Point_t> goalPoints = boustrophedon_stc(grid,
332332
startPoint,
333-
spiral_cpp_metrics_.multiple_pass_counter,
334-
spiral_cpp_metrics_.visited_counter);
333+
boustrophedon_cpp_metrics_.multiple_pass_counter,
334+
boustrophedon_cpp_metrics_.visited_counter);
335335
ROS_INFO("naive cpp completed!");
336336
ROS_INFO("Converting path to plan");
337337

338338
parsePointlist2Plan(start, goalPoints, plan);
339339
// Print some metrics:
340-
spiral_cpp_metrics_.accessible_counter = spiral_cpp_metrics_.visited_counter
341-
- spiral_cpp_metrics_.multiple_pass_counter;
342-
spiral_cpp_metrics_.total_area_covered = (4.0 * tool_radius_ * tool_radius_) * spiral_cpp_metrics_.accessible_counter;
343-
ROS_INFO("Total visited: %d", spiral_cpp_metrics_.visited_counter);
344-
ROS_INFO("Total re-visited: %d", spiral_cpp_metrics_.multiple_pass_counter);
345-
ROS_INFO("Total accessible cells: %d", spiral_cpp_metrics_.accessible_counter);
346-
ROS_INFO("Total accessible area: %f", spiral_cpp_metrics_.total_area_covered);
340+
boustrophedon_cpp_metrics_.accessible_counter = boustrophedon_cpp_metrics_.visited_counter
341+
- boustrophedon_cpp_metrics_.multiple_pass_counter;
342+
boustrophedon_cpp_metrics_.total_area_covered = (4.0 * tool_radius_ * tool_radius_) * boustrophedon_cpp_metrics_.accessible_counter;
343+
ROS_INFO("Total visited: %d", boustrophedon_cpp_metrics_.visited_counter);
344+
ROS_INFO("Total re-visited: %d", boustrophedon_cpp_metrics_.multiple_pass_counter);
345+
ROS_INFO("Total accessible cells: %d", boustrophedon_cpp_metrics_.accessible_counter);
346+
ROS_INFO("Total accessible area: %f", boustrophedon_cpp_metrics_.total_area_covered);
347347

348348
// TODO(CesarLopez): Check if global path should be calculated repetitively or just kept
349349
// (also controlled by planner_frequency parameter in move_base namespace)

test/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ The full coverage path planner consists of several parts that are each tested se
55

66
The move_base_flex plugin consists of several parts, each unit-tested separately:
77
- test_common: tests common.h
8-
- test_spiral_stc: tests static functions of spiral_stc.h
8+
- test_boustrophedon_stc: tests static functions of boustrophedon_stc.h
99

1010
Besides unittests, there are also some launch files that both illustrate how to use the
11-
- SpiralSTC-plugin, in test/full_coverage_path_planner/test_full_coverage_path_planner.launch
11+
- BoustrophedonSTC-plugin, in test/full_coverage_path_planner/test_full_coverage_path_planner.launch
1212

1313
Note that the .launch-files do not do any automatic testing or verification of anything,
1414
they are there to make manual testing easier.

test/full_coverage_path_planner/fcpp.rviz

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Visualization Manager:
106106
Radius: 0.029999999329447746
107107
Shaft Diameter: 0.019999999552965164
108108
Shaft Length: 0.05000000074505806
109-
Topic: /move_base/SpiralSTC/plan
109+
Topic: /move_base/BoustrophedonSTC/plan
110110
Unreliable: false
111111
Value: true
112112
- Angle Tolerance: 0.10000000149011612

0 commit comments

Comments
 (0)