Fields2Cover: coverage path planning for agricultural robots, with a Python face
Robust and efficient coverage paths for autonomous agricultural vehicles. A modular and extensible Coverage Path Planning library
At a glance
- What is it?
- Fields2Cover is a BSD-3 licensed C++17 library with SWIG Python bindings that turns a field boundary and a robot model into headlands, swaths, an optimised route and a drivable path with feasible turns. Its real value for many teams is the comparison framework, since it lets different coverage algorithms be run against the same field and the same vehicle.
- Who is it for?
- Fields2Cover suits a robotics team building an autonomous agricultural vehicle that needs a coverage plan rather than a point-to-point path, and it suits a research group that wants several coverage algorithms compared on identical inputs without writing each one from scratch. It does not suit a team that needs a production service or a stable API today, because the project states the API is still evolving and expects occasional breaking changes between releases.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 31 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A coverage plan is not a path between two points
Fields2Cover solves the Coverage Path Planning problem for agriculture. Given a field and a vehicle it computes a complete coverage path, which the README breaks into four outputs: headlands, swaths, an optimised route, and a drivable path with feasible turns. That is a different problem from the one most robotics libraries address. A point-to-point planner finds a shortest feasible line between two poses. A coverage planner has to visit every part of a field exactly once, or close to it, without leaving the boundary, with a vehicle that has a minimum turning radius and cannot spin on the spot. The library's stated audience is agricultural robotics, and the vehicle model is part of the input, not an afterthought. That is why the API takes a robot with width, length and turning constraints rather than a start and a goal.
The pipeline is four swappable modules, not one monolithic call
The core features list describes headland generation, swath generation, route planning and path planning as interchangeable modules, or as a single call to planCovPath. The distinction matters for anyone building on it. The one-call form is what you want in production: give it a field and a robot, get a path. The module form is what you want in research, because you can replace one stage and hold the rest fixed. That is the actual claim of the project, a common, extensible framework so that researchers do not have to re-implement every algorithm they want to compare against. The repository layout backs this up, with include and src at the top level, a separate tutorials directory, a tests directory, and swig for the Python binding generation. If you only ever call planCovPath, you are using perhaps a fifth of what the library was built to offer.
Non-convex fields need decomposition, not a cleverer planner
Handling non-convex fields and obstacles is done with trapezoidal and boustrophedon decomposition. This is the part of coverage planning that has no shortcut. A field with a river through it, or an orchard with tree rows inside a polygon, is not convex, and the classic boustrophedon pattern of parallel back-and-forth passes assumes it is. Decomposition breaks the region into convex sub-regions that each admit the simple pattern, and the sub-regions are then stitched together into a route. Trapezoidal decomposition splits the region with non-crossing chords, while boustrophedon decomposition produces trapezoidal cells oriented to the vehicle's working direction. The practical consequence for a user is that the interesting geometry is handled for you, but the output is a plan with cells and transitions between them, not a single smooth path, and you still have to decide how the vehicle moves between cells.
Turns are solved as Dubins or Reeds-Shepp curves, and that choice shows in the output
Kinematically feasible turns use Dubins and Reeds-Shepp curves, with or without continuous curvature. The distinction between the two is a real engineering choice rather than a detail. A Dubins path is the shortest curve connecting two poses for a vehicle that can only move forward, so it never includes a reverse segment. A Reeds-Shepp path allows forward and reverse motion and is therefore shorter, but it introduces cusps where the vehicle stops and reverses, which take time and are awkward to execute on real soil. Offering both, and offering the continuous-curvature variant, means you can pick a turn model that matches the machine rather than accepting one compromise. The other side of the coin is that the turning model interacts with the route optimiser, so a plan that looks reasonable on paper can still be unexecutable if the vehicle's real steering behaviour differs from the model you picked.
Route optimisation is delegated to OR-tools, with classic patterns available
Route optimisation uses OR-tools, and the library also offers classic patterns such as boustrophedon, snake and spiral. Delegating the combinatorial part to a mature solver is a sensible division of labour. The field decomposition gives you cells, and the cells give you an ordering problem, and ordering problems of this size are where a general solver earns its keep rather than a hand-rolled greedy heuristic. The alternative in this library is to skip the solver and pick a classical pattern directly, which is faster and gives the regular coverage you get from a straightforward back-and-forth. OR-tools is also the reason the C++ install needs the OR-tools package separately, and it is worth noting that the optimisation step is where most of the parameter choices live, since the objective the solver optimises determines which of several valid orders you end up with.
Installing means installing GDAL, GEOS and OR-tools first
The dependency list is the first thing to sort out, because Fields2Cover builds on GDAL, GEOS and OR-tools, and those need to be installed first. On Ubuntu the README gives the system packages directly:
sudo apt install build-essential libgdal-dev libgeos-dev libeigen3-dev libboost-dev \
libtbb-dev libtinyxml2-dev nlohmann-json3-dev libpython3-dev gnuplotand for macOS:
brew install gdal geos or-tools tinyxml2 eigen tbb boost gnuplotFor Python the install is one command:
pip install fields2coverbut the README is explicit that the package is built from source on your machine, so those system dependencies must already be there. For C++ you clone the repository and build with CMake, and the find_package snippet shows how the library attaches to a target:
find_package(Fields2Cover REQUIRED)
target_link_libraries(<your_target> Fields2Cover)There is also a ROS 2 route, through opennav_coverage, a Nav2-compatible coverage task server built on the library, which is the shortest route if you are already running ROS.
A first plan takes a field file, a robot and one function call
The Python quick start is small enough to read in full. You import the package, load a field from a GML file, construct a robot with four numbers, plan the coverage path, and plot the result:
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()The C++ version mirrors it with the same sequence, using f2c::Parser::importFieldGml, an F2CRobot constructed the same way, f2c::planCovPath, and the same three Visualizer calls. Two things are worth noticing. The plotting calls are how you check your work, since a coverage plan is a shape and an error in the shape is obvious visually and hard to see in numbers. And the plot of the field cells is separate from the plot of the path, which lets you see whether the decomposition did something sensible before worrying about the turns.
The API is still evolving, and the licence is BSD-3 over a stack of dependencies
The README states plainly that the API is still evolving, so expect occasional breaking changes between releases. The release history shows why that matters. Version 1.2.0 and 1.2.1 were both published on 2023-11-14, and then nothing tagged until v2.1.0 on 2026-09-03, with the last push on 2026-09-22. That is a long gap between a 1.x line and a 2.x line, and the documentation site carries a dedicated migration guide from version 1 to version 2. So the code you find in examples written against 1.x is likely to need work, and the project is honest about that rather than pretending compatibility. The repository backs this up with a CHANGELOG.md, a CITATION.cff, and a RELEASING.md, so the history of what changed is documented rather than reconstructed from commit messages. Fields2Cover is released under the BSD-3 licence, and the licence field in the Python package metadata matches that. The more relevant licensing question for an adopter is the dependency stack, which the README credits explicitly: GDAL, OR-tools, steering_functions, nlohmann/json, tinyxml2, CubicSplineClass and matplotplusplus. Those carry their own terms, and the Docker image in the repository is built on a GDAL base image, which means the container you ship inherits GDAL's licensing as well as Fields2Cover's. The BSD-3 grant is permissive, though it does carry minimal obligations such as keeping the copyright notice, even for a proprietary product that merely links the library, but the aggregate of the stack is what a legal review would want to see. This is a note on where the terms sit rather than legal advice. On funding, the project states it is partly financed by the Dutch Research Council, and the citing guidance asks users to reference the IEEE Robotics and Automation Letters paper when using Fields2Cover for research.
Editorial conclusion
Fields2Cover suits a robotics team building an autonomous agricultural vehicle that needs a coverage plan rather than a point-to-point path, and it suits a research group that wants several coverage algorithms compared on identical inputs without writing each one from scratch. It does not suit a team that needs a production service or a stable API today, because the project states the API is still evolving and expects occasional breaking changes between releases. Before you build on it, read the migration guide from version 1 to version 2, since v2.1.0 followed a long gap from the 1.2.x line, and install the GDAL, GEOS and OR-tools dependencies first, because the Python wheels are compiled on your machine rather than shipped ready made.
Frequently asked questions
How do I install Fields2Cover for Python?
Install GDAL, GEOS and OR-tools first, then run pip install fields2cover. The README notes the package is built from source on your machine, so the system dependencies have to be present before the install will work.
What does Fields2Cover need to plan a coverage path?
A field and a robot model. In the quick start the field is loaded from a GML file with the parser and the robot is constructed with four values, then f2c.planCovPath returns the path, which you can plot with the Visualizer.
How does Fields2Cover handle fields that are not convex?
It uses trapezoidal and boustrophedon decomposition, so non-convex fields and obstacles are broken into sub-regions that each admit a regular coverage pattern, with the regions stitched into a route.
Is the Fields2Cover API stable?
No. The README states the API is still evolving and expects occasional breaking changes between releases, and the documentation site carries a migration guide for version 1 to version 2 after the long gap to v2.1.0.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/fields2cover-fields2cover)Was this useful?