Skip to content

Commit

Permalink
Merge pull request #132 from methylDragon/ch3/author-namespaced-thumb…
Browse files Browse the repository at this point in the history
…nails

Support Author-namedspaced Thumbnails and Revamp building_map_generator
  • Loading branch information
aaronchongth committed May 28, 2020
2 parents 9bf5d1e + 9ab2d3d commit 0f01ad3
Show file tree
Hide file tree
Showing 27 changed files with 231 additions and 112 deletions.
50 changes: 50 additions & 0 deletions building_map_tools/building_map_generator/_init_argparse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import argparse

# Init overall parser and subparser
parser = argparse.ArgumentParser(
prog="building_map_generator",
description="Generate .world files, map models, and navigation maps"
"for running in Gazebo or Ignition!"
)
subparsers = parser.add_subparsers(help="Commands:", dest="command")

# Init shared parser
sim_parser = argparse.ArgumentParser(add_help=False)
sim_parser.add_argument("INPUT", type=str,
help="Input building.yaml file to process")
sim_parser.add_argument("OUTPUT_WORLD", type=str,
help="Name of the .world file to output")
sim_parser.add_argument("OUTPUT_MODEL_DIR", type=str,
help="Path to output the map model files")
sim_parser.add_argument("-o", "--options", type=str, nargs='*', default=[],
help="Generator options")

# Create subparsers for Gazebo, Ignition, and Nav generation
gazebo_parser = subparsers.add_parser(
'gazebo',
help='Generate .world file and map model.sdf for Gazebo',
parents=[sim_parser]
)
gazebo_parser.add_argument("-n", "--no_download", default=False,
const=True, action="store_const",
help="Do not download missing models from Fuel")
gazebo_parser.add_argument("-m", "--model_path", type=str,
help="Gazebo model path to check for models")
gazebo_parser.add_argument("-c", "--cache", type=str,
help="Path to pit_crew model cache")


ignition_parser = subparsers.add_parser(
'ignition',
help='Generate .world file and map model.sdf for Ignition',
parents=[sim_parser]
)

nav_parser = subparsers.add_parser(
'nav',
help='Generate nav map .yaml file',
)
nav_parser.add_argument("INPUT", type=str,
help="Input building.yaml file to process")
nav_parser.add_argument("OUTPUT_DIR", type=str,
help="Path to output the nav .yaml files")
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3

from building_map.generator import Generator
from building_map_generator._init_argparse import parser

import pit_crew
import logging
import sys

handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(pit_crew.PitCrewFormatter())
logger = logging.getLogger()
logger.addHandler(handler)
logger.setLevel(logging.INFO)


def main():
args = parser.parse_args()
g = Generator()

if args.command == "gazebo":
# Construct model set
model_set = set()

if not args.no_download:
building = g.parse_editor_yaml(args.INPUT)

for _, level in building.levels.items():
for model in level.models:
model_set.add(model.model_name)

missing_models = pit_crew.get_missing_models(
model_set,
model_path=args.model_path,
cache_file_path=args.cache
)

for downloadable_model in missing_models['downloadable']:
model_name, author_name = downloadable_model

# TODO: For now it just picks the first author
# When model authors are put into the thumbnails, then we can
# use that instead
logger.info("\nDownloading %s by %s from Fuel"
% (model_name, author_name[0]))

pit_crew.download_model(model_name, author_name[0],
download_path=args.model_path)

logger.warning("\nUnavailable models (not in local or Fuel): %s"
% missing_models['missing'])

g.generate_gazebo_sdf(
args.INPUT,
args.OUTPUT_WORLD,
args.OUTPUT_MODEL_DIR,
args.options
)

if args.command == "ignition":
g.generate_ignition_sdf(
args.INPUT,
args.OUTPUT_WORLD,
args.OUTPUT_MODEL_DIR,
args.options
)

if args.command == "nav":
g.generate_nav(args.INPUT, args.OUTPUT_DIR)

if __name__ == "__main__":
main()
20 changes: 0 additions & 20 deletions building_map_tools/building_map_generators/building_map_gazebo.py

This file was deleted.

This file was deleted.

12 changes: 0 additions & 12 deletions building_map_tools/building_map_generators/building_map_nav.py

This file was deleted.

11 changes: 4 additions & 7 deletions building_map_tools/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
'building_map',
'building_map.doors',
'building_map_server',
'building_map_generators',
'building_map_generator',
'pit_crew'],
py_modules=[],
data_files=[
Expand All @@ -23,7 +23,7 @@
),
(
'share/' + package_name + '/textures',
glob('building_map_generators/textures/*.png')
glob('building_map_generator/textures/*.png')
),
],
install_requires=['setuptools', 'shapely', 'pyyaml'],
Expand All @@ -47,11 +47,8 @@
'console_scripts': [
'building_map_server = '
'building_map_server.building_map_server:main',
'building_map_gazebo = '
'building_map_generators.building_map_gazebo:main',
'building_map_ignition = '
'building_map_generators.building_map_ignition:main',
'building_map_nav = building_map_generators.building_map_nav:main'
'building_map_generator = '
'building_map_generator.building_map_generator:main',
],
},
)
3 changes: 2 additions & 1 deletion test_maps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ foreach(path ${traffic_editor_paths})
set(output_model_dir ${output_dir}/models)

# first, generate the world
message("BUILDING WORLDFILE WITH COMMAND: ros2 run building_map_tools building_map_generator gazebo ${map_path} ${output_world_path} ${output_model_dir}")
add_custom_command(
OUTPUT ${output_world_path}
COMMAND ros2 run building_map_tools building_map_gazebo ${map_path} ${output_world_path} ${output_model_dir}
COMMAND ros2 run building_map_tools building_map_generator gazebo ${map_path} ${output_world_path} ${output_model_dir}
DEPENDS ${map_path}
)

Expand Down
1 change: 1 addition & 0 deletions traffic_editor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ ExternalProject_Add(thumbnails_repo

add_dependencies(traffic-editor thumbnails_repo)


install(
TARGETS traffic-editor
LIBRARY DESTINATION lib
Expand Down
12 changes: 6 additions & 6 deletions traffic_editor/thumbnail_generator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This is the pipeline for generating thumbnails to be used in `traffic_editor`.
* ROS Melodic
* Gazebo-9

Install all the other required packages,
Install all the other required packages, **and be sure to build all packages in the `traffic_editor` package**

```bash
sudo apt install \
Expand Down Expand Up @@ -39,7 +39,7 @@ Create a green screen world in `gazebo`, and start spawning models listed in you
./scripts/start_gazebo_screen.sh green

# start the spawning and photo-taking script in a second terminal
./scripts/top_view_generator.py -m test/model_list.yaml -o images/green
./scripts/top_view_generator.py test/model_list.yaml images/green
```

The orthogonal views of the models with a green screen will have been saved in the folder `images/green/`. Next, do the same with a white screen,
Expand All @@ -49,15 +49,15 @@ The orthogonal views of the models with a green screen will have been saved in t
./scripts/start_gazebo_screen.sh white

# in a second terminal
./scripts/top_view_generator.py -m test/model_list.yaml -o images/white
./scripts/top_view_generator.py test/model_list.yaml images/white
```

Similarly, the folder `images/white/` will have been populated when the script finishes.

The contours of the models are then extracted from the green-screened images using OpenCV to generate a transparency mask, used for cropping the white-background images, so that it stays centered and is as small as possible. This can be done by calling,

```bash
./scripts/crop.py -m test/model_list.yaml -g images/green -w images/white -o images/cropped
./scripts/crop.py test/model_list.yaml -o images/cropped -g images/green -w images/white
```

The generated thumbnails in `images/cropped` can then be added to `traffic_editor/thumbnails/images/`, while the model names need to be updated to `traffic_editor/thumbnails/model_list.yaml`.
Expand All @@ -67,13 +67,13 @@ The generated thumbnails in `images/cropped` can then be added to `traffic_edito
A new model list `.yaml` file can be generated using the utility script, where an optional blacklisted model names can be added, to avoid creating moving models or agents,

```bash
./scripts/generate_model_list.py -d MODEL_DIR -b test/model_blacklist.yaml -o test/output_model_list.yaml
./scripts/generate_model_list.py output_model_list.yaml -d MODEL_DIR -b test/model_blacklist.yaml
```

In the event that merging multiple model lists is required, a different utility script can be used,

```bash
./scripts/merge_model_lists.py -s test/model_list.yaml -d test/copied_model_list.yaml
./scripts/merge_model_lists.py test/merged_model_list.yaml -s test/extra_model_list.yaml
```

# Credits
Expand Down
52 changes: 39 additions & 13 deletions traffic_editor/thumbnail_generator/scripts/crop.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,30 +77,56 @@ def crop(green_img, white_img):
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
'-m', '--model-list', default='../test/model_list.yaml',
help='Path of model_list.yaml')
'model_list', default='../test/model_list.yaml',
help='Path of model_list.yaml'
)
parser.add_argument(
'-g', '--green-img-dir', default='../images/green/',
help='Directory filled with green screened model images')
'-o', '--output_dir',
default='../images/cropped/',
help='Directory where the cropped output images will be saved'
)
parser.add_argument(
'-w', '--white-img-dir', default='../images/white/',
help='Directory f illed with white screened model images')
'-g', '--green-img-dir', default='../images/green/',
help='Directory filled with green screened model images'
)
parser.add_argument(
'-o', '--output-dir', default='../images/cropped/',
help='Directory where the cropped output images will be saved')
'-w', '--white-img-dir', default='../images/white/',
help='Directory filled with white screened model images'
)
args = parser.parse_args(sys.argv[1:])

with open(args.model_list) as f:
y = yaml.load(f)

dirs = [os.path.expanduser(args.output_dir),
os.path.expanduser(args.green_img_dir),
os.path.expanduser(args.white_img_dir)]

# Make dirs if they dont exist
for dir in dirs:
try:
os.makedirs(dir)
print("Made diretory: {}".format(dir))
except Exception:
pass

for model_name in y['models']:
green_img = cv2.imread(
os.path.join(args.green_img_dir, '{}.png'.format(model_name)))
white_img = cv2.imread(
os.path.join(args.white_img_dir, '{}.png'.format(model_name)))
green_img = cv2.imread(os.path.join(
os.path.expanduser(args.green_img_dir),
'{}.png'.format(model_name)
)
)
white_img = cv2.imread(os.path.join(
os.path.expanduser(args.white_img_dir),
'{}.png'.format(model_name)
)
)

output_filepath = os.path.join(
args.output_dir, '{}.png'.format(model_name))
os.path.expanduser(args.output_dir),
'{}.png'.format(model_name)
)

print('generating {}'.format(output_filepath))

white_img_cropped = crop(green_img, white_img)
Expand Down
Loading

0 comments on commit 0f01ad3

Please sign in to comment.