This is a package to procedurally generate randomized fields with rows of plants for Gazebo.
ROS Distro | Gazebo version | Branch | Build status |
---|---|---|---|
Rolling | Gazebo | ros2-gz |
|
Rolling | Gazebo Classic | ros2 |
|
Iron | Gazebo | ros2-gz |
|
Iron | Gazebo Classic | ros2 |
|
Humble | Ignition Gazebo | ros2-ign |
|
Humble | Gazebo Classic | ros2 |
|
Noetic | Gazebo Classic | main |
Clone this repository and build the workspace. Additional you'll need the following packages:
rosdep install virtual_maize_field
This package has been tested on ROS 2 Humble, Iron and Rolling.
This package includes a script (virtual_maize_field/generate_world.py
) that can generate randomized agricultural worlds. All parameters are optional and have default values. All comma separated arguments can be scaler as well.
You can call the script using
ros2 run virtual_maize_field generate_world
The resulting file will be placed in $ROS_HOME/virtual_maize_field/generated.world
.
You can use this script by one of the defined config files or specifying the parameters below:
Click to show all possible arguments
usage: generate_world [-h] [--row_length ROW_LENGTH]
[--rows_curve_budget ROWS_CURVE_BUDGET]
[--row_width ROW_WIDTH] [--rows_count ROWS_COUNT]
[--row_segments [ROW_SEGMENTS [ROW_SEGMENTS ...]]]
[--row_segment_straight_length_min ROW_SEGMENT_STRAIGHT_LENGTH_MIN]
[--row_segment_straight_length_max ROW_SEGMENT_STRAIGHT_LENGTH_MAX]
[--row_segment_sincurved_offset_min ROW_SEGMENT_SINCURVED_OFFSET_MIN]
[--row_segment_sincurved_offset_max ROW_SEGMENT_SINCURVED_OFFSET_MAX]
[--row_segment_sincurved_length_min ROW_SEGMENT_SINCURVED_LENGTH_MIN]
[--row_segment_sincurved_length_max ROW_SEGMENT_SINCURVED_LENGTH_MAX]
[--row_segment_curved_radius_min ROW_SEGMENT_CURVED_RADIUS_MIN]
[--row_segment_curved_radius_max ROW_SEGMENT_CURVED_RADIUS_MAX]
[--row_segment_curved_arc_measure_min ROW_SEGMENT_CURVED_ARC_MEASURE_MIN]
[--row_segment_curved_arc_measure_max ROW_SEGMENT_CURVED_ARC_MEASURE_MAX]
[--row_segment_island_radius_min ROW_SEGMENT_ISLAND_RADIUS_MIN]
[--row_segment_island_radius_max ROW_SEGMENT_ISLAND_RADIUS_MAX]
[--ground_resolution GROUND_RESOLUTION]
[--ground_elevation_max GROUND_ELEVATION_MAX]
[--ground_headland GROUND_HEADLAND]
[--ground_ditch_depth GROUND_DITCH_DEPTH]
[--plant_spacing_min PLANT_SPACING_MIN]
[--plant_spacing_max PLANT_SPACING_MAX]
[--plant_height_min PLANT_HEIGHT_MIN]
[--plant_height_max PLANT_HEIGHT_MAX]
[--plant_radius PLANT_RADIUS]
[--plant_radius_noise PLANT_RADIUS_NOISE]
[--plant_placement_error_max PLANT_PLACEMENT_ERROR_MAX]
[--plant_mass PLANT_MASS]
[--hole_prob [HOLE_PROB [HOLE_PROB ...]]]
[--hole_size_max [HOLE_SIZE_MAX [HOLE_SIZE_MAX ...]]]
[--crop_types [CROP_TYPES [CROP_TYPES ...]]]
[--litters LITTERS]
[--litter_types [LITTER_TYPES [LITTER_TYPES ...]]]
[--weeds WEEDS]
[--weed_types [WEED_TYPES [WEED_TYPES ...]]]
[--ghost_objects GHOST_OBJECTS]
[--location_markers LOCATION_MARKERS]
[--load_from_file LOAD_FROM_FILE] [--seed SEED]
[--show_map]
[{fre21_task_2_mini,fre21_task_2_fast,fre21_task_1_mini,fre22_task_mapping_mini,fre22_task_navigation,fre21_task_3_fast,fre22_task_mapping,fre21_task_4_fast,fre21_task_2,fre21_task_3_mini,fre22_task_mapping_fast,fre21_task_1,fre21_task_3,fre22_task_navigation_fast,fre21_task_1_fast,fre21_task_4,fre22_task_navigation_mini,fre21_task_4_mini}]
Generate a virtual maize field world for Gazebo.
positional arguments:
{fre21_task_2_mini,fre21_task_2_fast,fre21_task_1_mini,fre22_task_mapping_mini,fre22_task_navigation,fre21_task_3_fast,fre22_task_mapping,fre21_task_4_fast,fre21_task_2,fre21_task_3_mini,fre22_task_mapping_fast,fre21_task_1,fre21_task_3,fre22_task_navigation_fast,fre21_task_1_fast,fre21_task_4,fre22_task_navigation_mini,fre21_task_4_mini}
Config file name in the config folder
optional arguments:
-h, --help show this help message and exit
--row_length ROW_LENGTH
default_value: 12.0
--rows_curve_budget ROWS_CURVE_BUDGET
default_value: 1.5707963267948966
--row_width ROW_WIDTH
default_value: 0.75
--rows_count ROWS_COUNT
default_value: 6
--row_segments [ROW_SEGMENTS [ROW_SEGMENTS ...]]
default_value: ['straight', 'curved']
--row_segment_straight_length_min ROW_SEGMENT_STRAIGHT_LENGTH_MIN
default_value: 0.5
--row_segment_straight_length_max ROW_SEGMENT_STRAIGHT_LENGTH_MAX
default_value: 1
--row_segment_sincurved_offset_min ROW_SEGMENT_SINCURVED_OFFSET_MIN
default_value: 0.5
--row_segment_sincurved_offset_max ROW_SEGMENT_SINCURVED_OFFSET_MAX
default_value: 1.5
--row_segment_sincurved_length_min ROW_SEGMENT_SINCURVED_LENGTH_MIN
default_value: 3
--row_segment_sincurved_length_max ROW_SEGMENT_SINCURVED_LENGTH_MAX
default_value: 5
--row_segment_curved_radius_min ROW_SEGMENT_CURVED_RADIUS_MIN
default_value: 3.0
--row_segment_curved_radius_max ROW_SEGMENT_CURVED_RADIUS_MAX
default_value: 10.0
--row_segment_curved_arc_measure_min ROW_SEGMENT_CURVED_ARC_MEASURE_MIN
default_value: 0.3
--row_segment_curved_arc_measure_max ROW_SEGMENT_CURVED_ARC_MEASURE_MAX
default_value: 1.0
--row_segment_island_radius_min ROW_SEGMENT_ISLAND_RADIUS_MIN
default_value: 1.0
--row_segment_island_radius_max ROW_SEGMENT_ISLAND_RADIUS_MAX
default_value: 3.0
--ground_resolution GROUND_RESOLUTION
default_value: 0.02
--ground_elevation_max GROUND_ELEVATION_MAX
default_value: 0.2
--ground_headland GROUND_HEADLAND
default_value: 2.0
--ground_ditch_depth GROUND_DITCH_DEPTH
default_value: 0.3
--plant_spacing_min PLANT_SPACING_MIN
default_value: 0.13
--plant_spacing_max PLANT_SPACING_MAX
default_value: 0.19
--plant_height_min PLANT_HEIGHT_MIN
default_value: 0.3
--plant_height_max PLANT_HEIGHT_MAX
default_value: 0.6
--plant_radius PLANT_RADIUS
default_value: 0.3
--plant_radius_noise PLANT_RADIUS_NOISE
default_value: 0.05
--plant_placement_error_max PLANT_PLACEMENT_ERROR_MAX
default_value: 0.02
--plant_mass PLANT_MASS
default_value: 0.3
--hole_prob [HOLE_PROB [HOLE_PROB ...]]
default_value: [0.06, 0.06, 0.04, 0.04, 0.0, 0.0]
--hole_size_max [HOLE_SIZE_MAX [HOLE_SIZE_MAX ...]]
default_value: [7, 5, 5, 3, 0, 0]
--crop_types [CROP_TYPES [CROP_TYPES ...]]
default_value: ['maize_01', 'maize_02']
--litters LITTERS default_value: 0
--litter_types [LITTER_TYPES [LITTER_TYPES ...]]
default_value: ['ale', 'beer', 'coke_can',
'retro_pepsi_can']
--weeds WEEDS default_value: 0
--weed_types [WEED_TYPES [WEED_TYPES ...]]
default_value: ['nettle', 'unknown_weed', 'dandelion']
--ghost_objects GHOST_OBJECTS
default_value: False
--location_markers LOCATION_MARKERS
default_value: False
--load_from_file LOAD_FROM_FILE
default_value: None
--seed SEED default_value: -1
--show_map Show map after generation.
In the config folder, config files to generate sample worlds are located. The parameters are chosen to match the task description
Worlds for the Field Robot Event 2022:
Name | Description |
---|---|
fre22_task_navigation | Task navigation, curved rows that get more difficult (eg. have more and larger holes) to the left |
fre22_task_mapping | Task mapping, field with random holes, bottles and weeds spread throughout the field. The cans, bottles and weeds have no collision box and are static. This world needs dandelion models which were only distributed among competitors of the Field Robot Event 2022. They are not uploaded to Github because they cannot be open-sourced. If you don't have access to these models, check out the fre21_task_3 worlds. |
Worlds for the Field Robot Event 2021:
Name | Description |
---|---|
fre21_task_1 | Task 1, curved rows without holes |
fre21_task_2 | Task 2, straight rows with holes |
fre21_task_3 | Task 3, similar crop rows as in task_2 but with cans, bottles and weeds spread throughout the field. The cans, bottles and weeds have no collision box and are static. |
fre21_task_4 | Task 4, similar crop rows as in task_2 but with cans, bottles and weeds spread throughout the field. The cans, bottles and weeds have a collision box and can be picked up. |
You can use these config files when generating worlds, e.g.:
ros2 run virtual_maize_field generate_world fre22_task_navigation_mini
The launch file to launch the worlds is called simulation.launch
. You can launch the launch file by running ros2 launch virtual_maize_field simulation.launch.py
. By default the launch file will launch generated_world.world
. You can launch any world by using the world_name
arg. e.g. ros2 launch virtual_maize_field simulation.launch.py world_name:=simple_row_level_1.world
. The generated world will be saved in $ROS_HOME/virtual_maize_field
(usually, this will be ~/.ros/virtual_maize_field
).
To add your own robot in the world, use the generated robot_spawner.launch.py
. This launches your robot at the correct position in the generated world. Your launch file to launch your robot should look like (replace <<robot_name>>
with your robot name):
from __future__ import annotations
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from virtual_maize_field import get_spawner_launch_file
def generate_launch_description() -> LaunchDescription:
robot_spawner_launch = IncludeLaunchDescription(
PythonLaunchDescriptionSource([get_spawner_launch_file()]),
launch_arguments={"robot_name": "<<robot_name>>"}.items(),
)
return LaunchDescription([robot_spawner_launch])
Use the function get_driving_pattern_file()
to get the path of the generated driving pattern and get_markers_file
to get the path of the generated markers:
from __future__ import annotations
from csv import reader
from pathlib import Path
from virtual_maize_field import get_driving_pattern_file, get_markers_file
def read_driving_pattern() -> None:
driving_pattern = Path(get_driving_pattern_file()).read_text("utf-8")
print(f"The driving pattern is {driving_pattern}")
def read_markers_file() -> None:
with open(get_markers_file(), "r") as f:
reader = csv.reader(f)
# Skip header
next(reader)
for row in reader:
print(f"Position {row[2]}: x={float(row[0]):.3f} y={float(row[1]):.3f}")
Virtual Maize Field is copyright (C) 2021 Farm Technology Group of Wageningen University & Research and Kamaro Engineering e.V. and licensed under .
Name | Path | Copyright | License |
---|---|---|---|
Maize 01 | models/maize_01/ |
2021 Kamaro Engineering e.V. | |
Maize 02 | models/maize_02/ |
2021 Kamaro Engineering e.V. | |
Stone 01 | models/stone_01/ |
2020 Andrea Spognetta | |
Stone 02 | models/stone_02/ |
2014 Sascha Henrichs | |
Ale | models/ale/ |
2017 elouisetrewartha | |
Beer | models/beer/ |
? Maurice Fallon | ? |
Coke Can | models/coke_can/ |
? John Hsu | ? |
Nettle | models/nettle/ |
2019 LadyIReyna | |
Retro Pepsi Can | models/retro_pepsi_can/ |
2018 FWTeastwood | |
Unknown Weed | models/unknown_weed/ |
2016 aaron_nerlich |
Name | Path | Copyright | License |
---|---|---|---|
grass | Media/models/materials/textures/ |
2018 CC0Textures.com |