|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged fields2cover at Robotics Stack Exchange
|
fields2cover package from fields2cover repofields2cover |
ROS Distro
|
Package Summary
| Version | 2.1.0 |
| License | BSD-3 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/Fields2Cover/fields2cover.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-03 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Gonzalo Mier
Authors
Robust and efficient coverage paths for autonomous agricultural vehicles
Documentation • Installation • Quick Start • Tutorials • API • Paper
Fields2Cover is an open-source C++ library with Python bindings that solves the Coverage Path Planning problem for agriculture: given a field and a vehicle, it computes a complete coverage path — headlands, swaths, an optimized route, and a drivable path with feasible turns. It also provides a common, extensible framework to implement and compare coverage path planning algorithms, so researchers don’t have to re-implement every algorithm they want to compare against. The API is still evolving, so expect occasional breaking changes between releases.
Core features
-
Modular pipeline: headland generation, swath generation, route planning and path planning as interchangeable modules — or a single call to
planCovPath. - Non-convex fields and obstacles, handled by trapezoidal and boustrophedon decomposition.
- Route optimization with OR-tools, plus classic patterns like boustrophedon, snake and spiral.
- Kinematically feasible turns using Dubins and Reeds-Shepp curves, with or without continuous curvature.
- C++17 core, Python bindings, and a ROS 2 integration via opennav_coverage.
Quick Start
Fields2Cover builds on GDAL, GEOS and OR-tools, which need to be installed first (details in the installation guide):
# Ubuntu
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplot
# plus OR-tools for C++: https://developers.google.com/optimization/install/cpp
# macOS
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplot
C++
#include "fields2cover.h"
int main() {
F2CField field = f2c::Parser::importFieldGml("data/test1.xml");
F2CRobot robot(2.0, 6.0, 0.5, 0.2);
F2CPath path = f2c::planCovPath(robot, field, false);
f2c::Visualizer::figure();
f2c::Visualizer::plot(field.getCellsAbsPosition());
f2c::Visualizer::plot(path);
f2c::Visualizer::show();
return 0;
}
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)
Python
pip install fields2cover
import fields2cover as f2c
field = f2c.Parser().importFieldGml("data/test1.xml")
robot = f2c.Robot(2.0, 6.0, 0.5, 0.2)
path = f2c.planCovPath(robot, field, False)
f2c.Visualizer.figure()
f2c.Visualizer.plot(field.getCellsAbsPosition())
f2c.Visualizer.plot(path)
f2c.Visualizer.show()
Installation
-
Python:
pip install fields2cover— the package is built from source on your machine, so the system dependencies above must be installed. - C++ / from source: clone this repository and build with CMake — full walkthrough in the installation guide.
- ROS 2: see opennav_coverage, a Nav2-compatible coverage task server built on Fields2Cover.
File truncated at 100 lines see the full file
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[2.1.0] - 2026-09-03
Added
-
f2c::hg::ReqHL, a headland generator that sizes each border on its own: a border the swaths run along is only entered, while a border they end on takes a whole turn. The difference is left to the mainland instead of being given up on every border. -
HeadlandGeneratorBase::generateHeadlandsoverloads taking a robot and the track angles, andmaxHLWidthRequired. -
F2CLinearRing::getParallelLine,bufferOutwards,bufferInwards,filterSelfIntersections,removePoint,getSegment,getLastSegment,segmentLengthandsegmentAng, to offset each segment of a ring by its own distance. -
Geometry::contains, the other side ofGeometry::within. -
f2c::hg::CorridorHL, a headland generator that opens a corridor where cells border each other instead of shrinking every border. Only the part of an edge a neighbour actually touches is cut, and the corridor comes out of the smaller cell so the larger neighbour keeps its shape; cells of the same size split it evenly. Edges facing the outer boundary or a void are left untouched. -
f2c::hg::CorridorHL::corridorShares, the rule that generator applies, on its own: for each pair of cells that share a border it reports the two perimeters, whether they count as the same size, how much of the corridor each cell gives, and the border they share. -
f2c::hg::CorridorShareMode, to split every corridor evenly (SYMMETRIC) instead of giving it all to the smaller cell (ASYMMETRIC, the default).CorridorHL::corridorSharestakes it as an argument, andCorridorHL::setShareMode/getShareModeset the modegenerateHeadlandsapplies. - Python module is built as a proper package with scikit-build-core (
pip install .); version is taken fromCMakeLists.txtand exposed asfields2cover.__version__. - Source distribution published to PyPI (
pip install fields2cover).
Fixed
-
f2c::hg::CorridorHLno longer opens a corridor where two cells only meet at a corner. The neighbour is buffered by a tolerance to find the shared border, which turned a single shared point into a few millimetres of “border” on every edge reaching it; in a field of cells meeting at one point that carved a disc out of the middle and made every slice a neighbour of every other. -
Cells::splitByLineno longer throwsstd::invalid_argumentwhen a split leaves a piece touching itself at a single point. Reinflating each split piece went throughCell::buffer, which only accepts a single polygon back; a positive buffer on a pinched piece can separate it into two. AMultiLineStringsplit also no longer silently keeps only the first line’s cut: reinflating after every individual line let GEOS collapse the next cut into a no-op, so every line is now buffered and cut in one pass instead of one after another. -
F2CCells::getCellBorder,getInteriorRingandaddRingno longer segfault on an empty polygon or an out-of-range index; they throwstd::out_of_rangelikegetGeometrydoes. -
NSwathModified::computeCostread the wrong neighbouring point for the first edge:(i - 1) % ring.size()wraps asize_ttoSIZE_MAX % n, which is not the previous vertex. The cost of a polygon now no longer depends on which vertex its ring starts from. -
generateBestSwathsno longer returns an angle that covers nothing. The objectives estimate the cost from the cell border alone, so a cell with a hairline spur could score best on an angle producing no swath at all and was silently left uncovered.
Changed
-
CorridorHL’s tolerances (the neighbour-buffer, spur, same-size and minimum-border thresholds) are private member variables instead of constants hidden in the .cpp file, visible directly on the class in the header. - The decomposition tutorial carves a corridor between cells instead of running the headland generator a second time, which also shrank the outer boundary.
-
cmake --installplaces the python module in the interpreter’s site-packages instead of callingsetup.py install. - Building the python module requires CMake >= 3.18 and Python >= 3.9.
[2.0.0] - 07-02-2024
- Route planner travelling through the headlands
[1.3.0] - 21-04-2023
- Add decomposition algorithms: trapezoidal, boustrophedon
[1.2.0] - 17-10-2022
Added
- Tests to do cover < 90% functions
Changes
- SG use the objective function as a parameter instead of a template.
- RP do not save the swaths and modify them using the functions provided
- PP do not save the robot and use the robot params with a param on the function.
Changes
- Objectives are split for each of the modules.
- Global objective renamed to SG objective.
- Path objective renamed to RP objective.
Added
- PP objective
- HL objective
[1.1.0]
Added
- On HL module: constant headland algorithm.
- On SG module: brute force algorithm.
- On RP module: Boustrophedon, custom, snake and spiral.
- On PP module: Dubins and Reeds-Sheep with/without continuous curvature.
- Objective functions are split between global and path cost functions.
Dependant Packages
| Name | Deps |
|---|---|
| fields2cover_ros |