Commit 0abe85e0 authored by Johannes Barthel's avatar Johannes Barthel
Browse files

clean up unneeded files, normalize meshes, refactor names to be more generic

parent 52ccacc4
......@@ -5,68 +5,61 @@ Description
This package is written for `ROS melodic` and `ROS noetic`.
Additional you'll need the following packages:
```
sudo apt install ros-melodic-gazebo-ros-pkgs \
ros-melodic-robot-state-publisher \
ros-melodic-effort-controllers \
ros-melodic-joint-state-controller \
ros-melodic-position-controllers \
ros-melodic-diff-drive-controller \
ros-melodic-rqt-robot-steering
```bash
# melodic
sudo apt install ros-melodic-gazebo-ros-pkgs
# noetic
sudo apt install ros-noetic-gazebo-ros-pkgs \
ros-noetic-robot-state-publisher \
ros-noetic-effort-controllers \
ros-noetic-joint-state-controller \
ros-noetic-position-controllers \
ros-noetic-diff-drive-controller \
ros-noetic-rqt-robot-steerin
python3-jinja2
```
On melodic, you need a conda environment or venv of python3 that has the `jinja2` package installed.
## Generating pumkin worlds
This package includes a script (`scripts/generate_world.py`) that can generate randomized pumpkin worlds. All parameters are optional and have default values. You can call the script using
## Generating field worlds
This package includes a script (`scripts/generate_world.py`) that can generate randomized agricultural worlds. All parameters are optional and have default values. You can call the script using
```bash
conda activate # this script needs a python3 environment that has jinja installed (pip install Jinja2)
rosrun dschubba_gazebo generate_world.py --num_rows_left=1 --num_rows_right=1 --num_pumpkin_pairs=20 --max_angle_variation=0.3
rosrun kamaro_world generate_world.py --num_rows_left=2 --num_rows_right=2 --num_plant_pairs=20 --max_angle_variation=0.3 --types=maize_01,maize_02
```
The resulting file will be placed in `worlds/generated.world`.
```
usage: generate_world.py [-h] [--pumpkin_radius PUMPKIN_RADIUS]
usage: generate_world.py [-h] [--plant_radius PLANT_RADIUS]
[--row_width ROW_WIDTH]
[--pumpkin_offset PUMPKIN_OFFSET]
[--plant_offset PLANT_OFFSET]
[--max_angle_variation MAX_ANGLE_VARIATION]
[--num_pumpkin_pairs NUM_PUMPKIN_PAIRS]
[--num_plant_pairs NUM_PLANT_PAIRS]
[--num_rows_left NUM_ROWS_LEFT]
[--num_rows_right NUM_ROWS_RIGHT]
[--pumpkin_height PUMPKIN_HEIGHT]
[--pumpkin_mass PUMPKIN_MASS]
[--plant_height PLANT_HEIGHT]
[--plant_mass PLANT_MASS]
[--radius_noise_range RADIUS_NOISE_RANGE]
[--seed SEED]
[--types TYPES]
generate a world full of cylinders
optional arguments:
-h, --help show this help message and exit
--pumpkin_radius PUMPKIN_RADIUS
--plant_radius PLANT_RADIUS
default_value: 0.15
--row_width ROW_WIDTH
default_value: 0.7
--pumpkin_offset PUMPKIN_OFFSET
--plant_offset PLANT_OFFSET
default_value: 0.6
--max_angle_variation MAX_ANGLE_VARIATION
default_value: 0.08726646259971647
--num_pumpkin_pairs NUM_PUMPKIN_PAIRS
--num_plant_pairs NUM_PLANT_PAIRS
default_value: 5
--num_rows_left NUM_ROWS_LEFT
default_value: 2
--num_rows_right NUM_ROWS_RIGHT
default_value: 3
--pumpkin_height PUMPKIN_HEIGHT
--plant_height PLANT_HEIGHT
default_value: 0.3
--pumpkin_mass PUMPKIN_MASS
--plant_mass PLANT_MASS
default_value: 5.0
--radius_noise_range RADIUS_NOISE_RANGE
default_value: 0.05
--seed SEED default_value: None
--types TYPES default_value: pumpkin_01,pumpkin_02,pumpkin_03,cylinder,maize_01,maize_02,beans_01
```
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/bin/bash
exec python$ROS_PYTHON_VERSION - << EOF
import rospy
import tf
from tf.transformations import euler_from_quaternion
from std_msgs.msg import Float64
from math import pi, atan2, sqrt
rospy.init_node('distance_sim', log_level=rospy.DEBUG)
distance_pub = rospy.Publisher("distance", Float64, queue_size=1)
tf_listener = tf.TransformListener()
wheel_left = None
wheel_right = None
distance = 0
def get_angle(q):
signum = 1 if q[1] > 0 else -1
return signum * 2 * atan2(sqrt(q[0] ** 2 + q[1] ** 2 + q[2] ** 2), q[3])
rate = rospy.Rate(12) # Hz
while not rospy.is_shutdown():
try:
wheel_left_quat = tf_listener.lookupTransform("base_link", "wheel_front_left_link", rospy.Time(0))[1]
wheel_right_quat = tf_listener.lookupTransform("base_link", "wheel_front_right_link", rospy.Time(0))[1]
wheel_left_new = get_angle(wheel_left_quat)
wheel_right_new = get_angle(wheel_right_quat)
except Exception as e:
print("Failed to get transforms: ")
print(e)
rate.sleep()
continue
if wheel_left is not None:
d_left = (((wheel_left_new - wheel_left) + pi) % (2*pi) - pi) * 0.085
print(wheel_left_new, d_left)
d_right = (((wheel_right_new - wheel_right) + pi) % (2*pi) - pi) * 0.085
distance += (d_left + d_right) / 2
wheel_left = wheel_left_new
wheel_right = wheel_right_new
distance_pub.publish(Float64(distance))
rate.sleep()
EOF
......@@ -6,17 +6,17 @@ import rospkg
AVAILABLE_TYPES = ["pumpkin_01", "pumpkin_02", "pumpkin_03", "cylinder", "maize_01", "maize_02", "beans_01"]
class Pumpkin2DGenerator():
class Field2DGenerator():
def __init__(self,
pumpkin_radius = .15,
plant_radius = .15,
row_width = .7,
pumpkin_offset = .60,
plant_offset = .60,
max_angle_variation = np.deg2rad(5),
num_pumpkin_pairs = 5,
num_plant_pairs = 5,
num_rows_left = 2,
num_rows_right = 3,
pumpkin_height = 0.3,
pumpkin_mass = 5.0,
plant_height = 0.3,
plant_mass = 5.0,
radius_noise_range = 0.05,
seed = None,
types=",".join(AVAILABLE_TYPES)):
......@@ -33,11 +33,11 @@ class Pumpkin2DGenerator():
angles = []
self.pumpkins = []
for _ in range(self.num_pumpkin_pairs):
for _ in range(self.num_plant_pairs):
angle_variation = ((np.random.rand() * 2) - 1) * self.max_angle_variation
angles.append(angle_variation)
tx = self.pumpkin_offset
tx = self.plant_offset
ty = 0
T = np.matrix([
......@@ -77,7 +77,7 @@ class Pumpkin2DGenerator():
[0, 0, 1]])
LOCAL_pumpkins = LOCAL_T_WORLD * self.pumpkins
dist_pumpkin = np.linalg.norm(LOCAL_pumpkins[0:2], axis=0).min() - self.pumpkin_radius
dist_pumpkin = np.linalg.norm(LOCAL_pumpkins[0:2], axis=0).min() - self.plant_radius
return dist_pumpkin
def render_to_template(self, template):
......@@ -104,6 +104,6 @@ class Pumpkin2DGenerator():
coordinate["name"] = "{}_{:04d}".format(coordinate["type"], index)
coordinate["yaw"] = np.random.rand() * 2.0 * np.pi
return coordinate
coordinates = [into_dict(row,self.pumpkin_radius, self.pumpkin_height, self.pumpkin_mass, i) for i, row in enumerate(self.pumpkins.T[:,:-1])]
coordinates = [into_dict(row,self.plant_radius, self.plant_height, self.plant_mass, i) for i, row in enumerate(self.pumpkins.T[:,:-1])]
template = jinja2.Template(template)
return template.render(coordinates=coordinates, package_path=rospkg.RosPack().get_path('kamaro_world'))
\ No newline at end of file
#!/usr/bin/env python3
from pumpkin_2d_generator import Pumpkin2DGenerator
from field_2d_generator import Field2DGenerator
import rospkg
import argparse
import inspect
......@@ -8,7 +8,7 @@ import os
if __name__ == "__main__":
# get the possible arguments of the generator and default values
argspec = inspect.getfullargspec(Pumpkin2DGenerator.__init__)
argspec = inspect.getfullargspec(Field2DGenerator.__init__)
possible_kwargs = argspec.args[1:]
defaults = argspec.defaults
......@@ -21,11 +21,11 @@ if __name__ == "__main__":
# get a dict representation of the arguments and call our constructor with them as kwargs
args = vars(parser.parse_args())
args = {k:v for k,v in args.items() if v is not None}
pk = Pumpkin2DGenerator(**args)
pk = Field2DGenerator(**args)
# generate the template and write it to a file
pkg_path = rospkg.RosPack().get_path('kamaro_world')
template_path = os.path.join(pkg_path, "scripts/pumpkin.world.template")
template_path = os.path.join(pkg_path, "scripts/field.world.template")
template = open(template_path).read()
generated_sdf = pk.render_to_template(template)
out_path = os.path.join(pkg_path, "worlds/generated.world")
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment