Skip to content

Commit 7acf0c4

Browse files
authored
Merging #33
2 parents 153b324 + ad01d3e commit 7acf0c4

File tree

7 files changed

+97
-39
lines changed

7 files changed

+97
-39
lines changed

.github/workflows/build.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ jobs:
3838
file: Dockerfile.tester
3939
load: true
4040
push: true
41-
tags: ghcr.io/yadunund/bpc/estimator-tester:latest
41+
tags: ghcr.io/opencv/bpc/estimator-tester:latest

Dockerfile.estimator

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,6 @@ FROM underlay AS overlay
3737
ARG SERVICE_PACKAGE=ibpc_pose_estimator_py
3838
ARG SERVICE_EXECUTABLE_NAME=ibpc_pose_estimator
3939

40-
# TODO(Yadunund): Remove this step after next Jazzy sync.
41-
RUN apt update \
42-
&& sudo apt install curl -y \
43-
&& curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg \
44-
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2-testing/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
45-
4640
RUN apt-get update \
4741
&& apt install -y ros-jazzy-rmw-zenoh-cpp \
4842
&& rm -rf /var/lib/apt/lists/*
@@ -85,4 +79,3 @@ ENV MODEL_DIR=/opt/ros/underlay/install/models
8579

8680
CMD exec /opt/ros/overlay/install/lib/${SERVICE_PACKAGE}/${SERVICE_EXECUTABLE_NAME} \
8781
--ros-args -p model_dir:=${MODEL_DIR}
88-

Dockerfile.tester

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ RUN . /opt/ros/jazzy/setup.sh \
2222

2323
FROM underlay AS overlay
2424

25-
# TODO(Yadunund): Remove this step after next Jazzy sync.
26-
RUN apt update \
27-
&& sudo apt install curl -y \
28-
&& curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg \
29-
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2-testing/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
30-
3125
RUN apt-get update \
3226
&& apt install -y ros-jazzy-rmw-zenoh-cpp \
3327
&& rm -rf /var/lib/apt/lists/*
@@ -48,6 +42,8 @@ RUN . /opt/ros/jazzy/setup.sh \
4842
FROM base
4943

5044
ARG DATASET_NAME
45+
ARG OUTPUT_DIR=/submission
46+
ARG OUTPUT_FILENAME=submission.csv
5147
ARG SERVICE_PACKAGE=ibpc_tester
5248
ARG SERVICE_EXECUTABLE_NAME=ibpc_tester
5349
ARG SPLIT_TYPE=val
@@ -58,7 +54,7 @@ RUN apt update \
5854
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2-testing/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
5955

6056
RUN apt-get update \
61-
&& apt install -y ros-jazzy-rmw-zenoh-cpp python3-imageio python3-png python3-pip python3-scipy \
57+
&& apt install -y ros-jazzy-rmw-zenoh-cpp python3-imageio python3-pandas python3-png python3-pip python3-scipy \
6258
&& rm -rf /var/lib/apt/lists/*
6359

6460
# TODO remove deprecated pytz usage
@@ -72,9 +68,11 @@ RUN sed --in-place \
7268
/ros_entrypoint.sh
7369

7470
ENV DATASET_NAME=${DATASET_NAME}
71+
ENV OUTPUT_DIR=${OUTPUT_DIR}
72+
ENV OUTPUT_FILENAME=${OUTPUT_FILENAME}
7573
ENV SERVICE_PACKAGE=${SERVICE_PACKAGE}
7674
ENV SERVICE_EXECUTABLE_NAME=${SERVICE_EXECUTABLE_NAME}
7775
ENV SPLIT_TYPE=${SPLIT_TYPE}
7876

7977
CMD exec /opt/ros/overlay/install/lib/${SERVICE_PACKAGE}/${SERVICE_EXECUTABLE_NAME} \
80-
--ros-args -p dataset_name:=${DATASET_NAME} -p split_type:=${SPLIT_TYPE}
78+
--ros-args -p dataset_name:=${DATASET_NAME} -p split_type:=${SPLIT_TYPE} -p output_dir:=${OUTPUT_DIR} -p output_filename:=${OUTPUT_FILENAME}

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Perception Challenge For Bin-Picking
22

3-
[![build](https://github.com/Yadunund/bpc/actions/workflows/build.yaml/badge.svg?branch=main)](https://github.com/Yadunund/bpc/actions/workflows/build.yaml)
4-
[![style](https://github.com/Yadunund/bpc/actions/workflows/style.yaml/badge.svg?branch=main)](https://github.com/Yadunund/bpc/actions/workflows/style.yaml)
3+
[![build](https://github.com/opencv/bpc/actions/workflows/build.yaml/badge.svg?branch=main)](https://github.com/opencv/bpc/actions/workflows/build.yaml)
4+
[![style](https://github.com/opencv/bpc/actions/workflows/style.yaml/badge.svg?branch=main)](https://github.com/opencv/bpc/actions/workflows/style.yaml)
55

66
For more details on the challenge, [click here](https://bpc.opencv.org/).
77

@@ -20,7 +20,7 @@ This repository contains the ROS interfaces, sample submission code and evaluati
2020
- **ROS Interface:**
2121
The API for the challenge is a ROS service, [GetPoseEstimates](ibpc_interfaces/srv/GetPoseEstimates.srv), over `/get_pose_estimates`. Participants implement the service callback on a dedicated ROS node (commonly referred to as the PoseEstimatorNode) which processes the input data (images and metadata) and returns pose estimation results.
2222

23-
In addition, we provide the [ibpc_py tool](https://github.com/Yadunund/bpc/tree/main/ibpc_py) which facilitates downloading the challenge data and performing various related tasks. Please refer to its README for further details.
23+
In addition, we provide the [ibpc_py tool](https://github.com/opencv/bpc/tree/main/ibpc_py) which facilitates downloading the challenge data and performing various related tasks. Please refer to its README for further details.
2424

2525
## Design
2626

@@ -62,7 +62,7 @@ Participants are expected to modify the estimator code to implement their soluti
6262
```bash
6363
mkdir -p ~/ws_bpc/src
6464
cd ~/ws_bpc/src
65-
git clone https://github.com/Yadunund/bpc.git
65+
git clone https://github.com/opencv/bpc.git
6666
```
6767

6868
## Build
@@ -91,7 +91,7 @@ docker buildx build -t ibpc:tester \
9191
### Start the Zenoh router
9292

9393
```bash
94-
docker run --init --rm --net host eclipse/zenoh:1.1.1 --no-multicast-scouting
94+
docker run --init --rm --net host eclipse/zenoh:1.2.1 --no-multicast-scouting
9595
```
9696

9797
### Run the pose estimator
@@ -102,15 +102,15 @@ rocker --nvidia --cuda run --network=host ibpc:pose_estimator
102102

103103
### Run the tester
104104

105-
> Note: Substitute the <PATH_TO_DATASET> with the directory that contains the [ipd](https://huggingface.co/datasets/bop-benchmark/ipd/tree/main) dataset.
105+
> Note: Substitute the <PATH_TO_DATASET> with the directory that contains the [ipd](https://huggingface.co/datasets/bop-benchmark/ipd/tree/main) dataset. Similarly, substitute <PATH_TO_OUTPUT_DIR> with the directory that should contain the results from the pose estimator. By default, the results will be saved as a `submission.csv` file but this filename can be updated by setting the `OUTPUT_FILENAME` environment variable.
106106
107107
```bash
108-
docker run --network=host -e BOP_PATH=/opt/ros/underlay/install/datasets -e SPLIT_TYPE=val -v<PATH_TO_DATASET>:/opt/ros/underlay/install/datasets -it ibpc:tester
108+
docker run --network=host -e BOP_PATH=/opt/ros/underlay/install/datasets -e SPLIT_TYPE=val -v<PATH_TO_DATASET>:/opt/ros/underlay/install/datasets -v<PATH_TO_OUTPUT_DIR>:/submission -it ibpc:tester
109109
```
110110

111111
## Baseline Solution
112112

113-
We provide a simple baseline solution as a reference for implementing the solution in `ibpc_pose_estimator_py`. Please refer to the [baseline_solution](https://github.com/Yadunund/bpc/tree/baseline_solution) branch and follow the instructions there.
113+
We provide a simple baseline solution as a reference for implementing the solution in `ibpc_pose_estimator_py`. Please refer to the [baseline_solution](https://github.com/opencv/bpc/tree/baseline_solution) branch and follow the instructions there.
114114

115115
## Next Steps
116116

ibpc_py/src/ibpc/ibpc.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from rocker.core import DockerImageGenerator
1010
from rocker.core import get_rocker_version
1111
from rocker.core import RockerExtensionManager
12+
from rocker.core import OPERATIONS_DRY_RUN
13+
from rocker.core import OPERATIONS_INTERACTIVE
1214
from rocker.core import OPERATIONS_NON_INTERACTIVE
1315

1416
from io import BytesIO
@@ -142,9 +144,10 @@ def main():
142144
test_parser.add_argument("estimator_image")
143145
test_parser.add_argument("dataset")
144146
test_parser.add_argument("--dataset_directory", action="store", default=".")
147+
test_parser.add_argument("--result_directory", action="store", default=".")
145148
test_parser.add_argument("--debug-inside", action="store_true")
146149
test_parser.add_argument(
147-
"--tester-image", default="ghcr.io/yadunund/bpc/estimator-tester:latest"
150+
"--tester-image", default="ghcr.io/opencv/bpc/estimator-tester:latest"
148151
)
149152

150153
fetch_parser = sub_parsers.add_parser("fetch")
@@ -163,12 +166,6 @@ def main():
163166
print("Fetch complete")
164167
return
165168

166-
# Confirm dataset directory is absolute
167-
args_dict["dataset_directory"] = os.path.abspath(args_dict["dataset_directory"])
168-
169-
active_extensions = extension_manager.get_active_extensions(args_dict)
170-
print("Active extensions %s" % [e.get_name() for e in active_extensions])
171-
172169
tester_args = {
173170
"network": "host",
174171
"extension_blacklist": {},
@@ -179,7 +176,10 @@ def main():
179176
],
180177
"console_output_file": "ibpc_test_output.log",
181178
"volume": [
182-
[f"{args_dict['dataset_directory']}:/opt/ros/underlay/install/datasets"]
179+
[
180+
f"{args_dict['dataset_directory']}:/opt/ros/underlay/install/datasets",
181+
f"{args_dict['result_directory']}:/submission",
182+
]
183183
],
184184
}
185185
print("Buiding tester env")
@@ -197,14 +197,14 @@ def main():
197197
"network": "host",
198198
"extension_blacklist": {},
199199
"console_output_file": "ibpc_zenoh_output.log",
200-
"operating_mode": OPERATIONS_NON_INTERACTIVE,
200+
"mode": OPERATIONS_NON_INTERACTIVE,
201201
"volume": [],
202202
}
203-
zenoh_extensions = extension_manager.get_active_extensions(tester_args)
203+
zenoh_extensions = extension_manager.get_active_extensions(zenoh_args)
204204

205205
print("Buiding zenoh env")
206206
dig_zenoh = DockerImageGenerator(
207-
zenoh_extensions, zenoh_args, "eclipse/zenoh:1.1.1"
207+
zenoh_extensions, zenoh_args, "eclipse/zenoh:1.2.1"
208208
)
209209
exit_code = dig_zenoh.build(**zenoh_args)
210210
if exit_code != 0:
@@ -222,6 +222,15 @@ def run_instance(dig_instance, args):
222222
)
223223
tester_thread.start()
224224

225+
args_dict["network"] = "host"
226+
args_dict["extension_blacklist"] = ({},)
227+
228+
# Confirm dataset directory is absolute
229+
args_dict["dataset_directory"] = os.path.abspath(args_dict["dataset_directory"])
230+
231+
active_extensions = extension_manager.get_active_extensions(args_dict)
232+
print("Active extensions %s" % [e.get_name() for e in active_extensions])
233+
225234
dig = DockerImageGenerator(
226235
active_extensions, args_dict, args_dict["estimator_image"]
227236
)
@@ -232,7 +241,8 @@ def run_instance(dig_instance, args):
232241
return exit_code
233242

234243
if args.debug_inside:
235-
args_dict["command"] = "bash"
244+
args_dict["command"] = "/bin/bash"
245+
args_dict["mode"] = OPERATIONS_INTERACTIVE
236246

237247
result = dig.run(**args_dict)
238248
# TODO clean up threads here

ibpc_tester/ibpc_tester/ibpc_tester.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import numpy as np
66
from pathlib import Path
77
import sys
8+
import pandas as pd
89

910
import rclpy
1011
from rclpy.node import Node
@@ -138,6 +139,24 @@ def _load_camera_params(self, path, camera_name, img_id):
138139
self.t = self.camera_params["cam_t_w2c"]
139140

140141

142+
def pose_msg_to_rt(pose_msg):
143+
# Convert quaternion to rotation matrix
144+
r = Rotation.from_quat(
145+
[
146+
pose_msg.orientation.x,
147+
pose_msg.orientation.y,
148+
pose_msg.orientation.z,
149+
pose_msg.orientation.w,
150+
]
151+
)
152+
R = r.as_matrix().flatten().tolist()
153+
154+
# Get translation
155+
t = [pose_msg.position.x, pose_msg.position.y, pose_msg.position.z]
156+
157+
return R, t
158+
159+
141160
def main(argv=sys.argv):
142161
rclpy.init(args=argv)
143162
args_without_ros = rclpy.utilities.remove_ros_args(argv)
@@ -156,6 +175,22 @@ def main(argv=sys.argv):
156175
node.get_logger().info(
157176
f"Loading from dataset {dataset_name} with split_type {split_type}."
158177
)
178+
output_dir = Path(
179+
node.declare_parameter("output_dir", "/submission")
180+
.get_parameter_value()
181+
.string_value
182+
)
183+
output_filename = (
184+
node.declare_parameter("output_filename", "submission.csv")
185+
.get_parameter_value()
186+
.string_value
187+
)
188+
try:
189+
output_filepath = (output_dir / output_filename).resolve()
190+
except Exception as e:
191+
print(f"Error creating filepath: {e}")
192+
output_filepath = output_filename
193+
node.get_logger().info(f"Submission results will be written to {output_filepath}.")
159194

160195
debug_cam_1 = None
161196
debug_cam_2 = None
@@ -180,7 +215,10 @@ def main(argv=sys.argv):
180215
node.get_logger().info(
181216
"/get_pose_estimates service not available, waiting again..."
182217
)
183-
results = {}
218+
219+
# Create list to store results
220+
results = []
221+
184222
# Get pose estimates for every image in every scene.
185223
for scene_id in test_split["scene_ids"]:
186224
scene_dir = Path(test_split["split_path"]) / "{scene_id:06d}".format(
@@ -211,14 +249,32 @@ def main(argv=sys.argv):
211249
)
212250
future = client.call_async(request)
213251
rclpy.spin_until_future_complete(node, future)
252+
214253
if future.result() is not None:
215254
node.get_logger().info(f"Got results: {future.result().pose_estimates}")
255+
# Process results and add to results list
256+
for pose_estimate in future.result().pose_estimates:
257+
R, t = pose_msg_to_rt(pose_estimate.pose)
258+
results.append(
259+
{
260+
"scene_id": scene_id,
261+
"im_id": img_id,
262+
"obj_id": pose_estimate.obj_id,
263+
"score": pose_estimate.score,
264+
"R": R,
265+
"t": t,
266+
"time": -1,
267+
}
268+
)
216269
else:
217270
node.get_logger().error(
218271
"Exception while calling service: %r" % future.exception()
219272
)
220-
# todo(Yadunund): Remove break after dataset is fixed.
221-
break
273+
274+
# Convert results to DataFrame and save
275+
df = pd.DataFrame(results)
276+
df.to_csv(output_filepath, index=False)
277+
node.get_logger().info(f"Results saved to {output_filepath}")
222278

223279
node.destroy_node()
224280
rclpy.try_shutdown()

ibpc_tester/package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<exec_depend>ibpc_interfaces</exec_depend>
1212

1313
<exec_depend>rclpy</exec_depend>
14+
<exec_depend>python3-pandas</exec_depend>
1415

1516
<test_depend>ament_copyright</test_depend>
1617
<test_depend>ament_flake8</test_depend>

0 commit comments

Comments
 (0)