diff --git a/ibpc_py/README.md b/ibpc_py/README.md new file mode 100644 index 00000000..1fa0ded8 --- /dev/null +++ b/ibpc_py/README.md @@ -0,0 +1,38 @@ +# Industrial Bin Picking Challenge (IBPC) + +This is the python entrypoint for the Industrial Bin Picking Challenge + +## Usage + +Get a dataset +`bpc fetch lm` + + +Run tests against a dataset +`bpc test <Pose Estimator Image Name> <datasetname> ` + +`bpc test ibpc:pose_estimator lm` + + +## Prerequisites + + +### Install the package: + +In a virtualenv +`pip install ibpc` + +Temporary before rocker release of https://github.com/osrf/rocker/pull/317/ +`pip uninstall rocker && pip install git+http://github.com/osrf/rocker.git@console_to_file` + + +### Nvidia Docker (optoinal) +Make sure nvidia_docker is installed if you want cuda. + +## Release instructions + +``` +rm -rf dist/* +python3 -m build --sdist . +twine upload dist/* +``` \ No newline at end of file diff --git a/ibpc_py/setup.py b/ibpc_py/setup.py new file mode 100644 index 00000000..08654a56 --- /dev/null +++ b/ibpc_py/setup.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import os +import setuptools + +with open("README.md", "r") as fh: + long_description = fh.read() + + +setuptools.setup( + name="ibpc", + version="0.0.2", + packages=["ibpc"], + package_dir={"": "src"}, + # package_data={'ibpc': ['templates/*.em']}, + author="Tully Foote", + author_email="tullyfoote@intrinsic.ai", + description="An entrypoint for the Industrial Bin Picking Challenge", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://bpc.opencv.org/", + license="Apache 2.0", + install_requires=[ + "empy", + "rocker>=0.2.13", + ], + install_package_data=True, + zip_safe=False, + entry_points={ + "console_scripts": [ + "bpc = ibpc.ibpc:main", + ], + }, +) diff --git a/ibpc_py/src/ibpc/__init__.py b/ibpc_py/src/ibpc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ibpc.py b/ibpc_py/src/ibpc/ibpc.py similarity index 50% rename from ibpc.py rename to ibpc_py/src/ibpc/ibpc.py index 4c0475c1..f3943dd0 100644 --- a/ibpc.py +++ b/ibpc_py/src/ibpc/ibpc.py @@ -8,26 +8,78 @@ from rocker.core import RockerExtensionManager from rocker.core import OPERATIONS_NON_INTERACTIVE +from io import BytesIO +from urllib.request import urlopen +import urllib.request +from zipfile import ZipFile + + +def get_bop_template(modelname): + return f"https://huggingface.co/datasets/bop-benchmark/datasets/resolve/main/{modelname}/{modelname}" + +def get_ipb_template(modelname): + return f"https://huggingface.co/datasets/bop-benchmark/{modelname}/resolve/main/{modelname}" + +bop_suffixes = [ + "_base.zip", + "_models.zip", + "_test_all.zip", + "_train_pbr.zip", +] + +ipb_suffixes = [s for s in bop_suffixes] +ipb_suffixes.append('_val.zip') +ipb_suffixes.append('_test_all.z01') + +available_datasets = { + "ipb": (get_ipb_template("ipb"), ipb_suffixes), + "lm": (get_bop_template("lm"), bop_suffixes), + } + +def fetch_dataset(dataset, output_path): + (url_base, suffixes) = available_datasets[dataset] + for suffix in suffixes: + + url = url_base + suffix + print(f"Downloading from url: {url}") + with urlopen(url) as zipurlfile: + with ZipFile(BytesIO(zipurlfile.read())) as zfile: + zfile.extractall(output_path) + def main(): - parser = argparse.ArgumentParser( + main_parser = argparse.ArgumentParser( description="The entry point for the Bin Picking Challenge", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) - parser.add_argument("test_image") - parser.add_argument("dataset_directory") - parser.add_argument( + main_parser.add_argument( "-v", "--version", action="version", version="%(prog)s " + get_rocker_version() ) - parser.add_argument("--debug-inside", action="store_true") + + sub_parsers = main_parser.add_subparsers(title="test", dest="subparser_name") + test_parser = sub_parsers.add_parser("test") + + test_parser.add_argument("estimator_image") + test_parser.add_argument("dataset") + test_parser.add_argument("--dataset_directory", action="store", default=".") + test_parser.add_argument("--debug-inside", action="store_true") + + fetch_parser = sub_parsers.add_parser("fetch") + fetch_parser.add_argument("dataset", choices=available_datasets.keys()) + fetch_parser.add_argument("--dataset-path", default=".") extension_manager = RockerExtensionManager() default_args = {"cuda": True, "network": "host"} - extension_manager.extend_cli_parser(parser, default_args) + # extension_manager.extend_cli_parser(test_parser, default_args) - args = parser.parse_args() + args = main_parser.parse_args() args_dict = vars(args) + if args.subparser_name == "fetch": + print(f"Fetching dataset {args_dict['dataset']} to {args_dict['dataset_path']}") + fetch_dataset(args_dict["dataset"], args_dict["dataset_path"]) + print("Fetch complete") + return # Confirm dataset directory is absolute args_dict["dataset_directory"] = os.path.abspath(args_dict["dataset_directory"]) @@ -39,10 +91,13 @@ def main(): "network": "host", "extension_blacklist": {}, "operating_mode": OPERATIONS_NON_INTERACTIVE, - "env": [[f"BOP_PATH:/opt/ros/underlay/install/datasets"]], + "env": [ + [f"BOP_PATH:/opt/ros/underlay/install/datasets/{args_dict['dataset']}"], + [f"DATASET_NAME:{args_dict['dataset']}"], + ], "console_output_file": "ibpc_test_output.log", "volume": [ - [f"{args_dict['dataset_directory']}:/opt/ros/underlay/install/datasets/lm"] + [f"{args_dict['dataset_directory']}:/opt/ros/underlay/install/datasets"] ], } print("Buiding tester env") @@ -59,11 +114,13 @@ def main(): "extension_blacklist": {}, "console_output_file": "ibpc_zenoh_output.log", "operating_mode": OPERATIONS_NON_INTERACTIVE, + "volume": [], } + zenoh_extensions = extension_manager.get_active_extensions(tester_args) print("Buiding zenoh env") dig_zenoh = DockerImageGenerator( - tester_extensions, tester_args, "eclipse/zenoh:1.1.1" + zenoh_extensions, zenoh_args, "eclipse/zenoh:1.1.1" ) exit_code = dig_zenoh.build(**zenoh_args) if exit_code != 0: @@ -76,22 +133,14 @@ def run_instance(dig_instance, args): tester_thread = threading.Thread(target=run_instance, args=(dig_zenoh, zenoh_args)) tester_thread.start() - # TODO Redirect stdout - import time - - time.sleep(3) - tester_thread = threading.Thread( target=run_instance, args=(dig_tester, tester_args) ) tester_thread.start() - # TODO Redirect stdout - import time - - time.sleep(3) - - dig = DockerImageGenerator(active_extensions, args_dict, args_dict["test_image"]) + dig = DockerImageGenerator( + active_extensions, args_dict, args_dict["estimator_image"] + ) exit_code = dig.build(**vars(args)) if exit_code != 0: @@ -104,7 +153,3 @@ def run_instance(dig_instance, args): result = dig.run(**args_dict) # TODO clean up threads here return result - - -if __name__ == "__main__": - main()