Bringing up the house
From the course repository, start the house simulation, Zenoh router, and ROS 2 bridge:demo-world-house service launches the AWS RoboMaker residential environment in Gazebo together with Nav2. The environment is derived from the open-source small-house assets and contains 68 models whose names begin with aws_robomaker_residential_*. These include beds, chairs, sofas, coffee tables, air conditioners, carpets, curtains, chandeliers, night stands, wardrobes, and desk portraits. The TurtleBot begins near the entrance. A precomputed occupancy grid with a resolution of 5 cm per pixel is provided at tb_worlds/maps/house_world_map.yaml. The Gazebo worlds page describes the environment, its models, and the procedure for adding models.
All Compose services use host networking. Run only one world service at a time; otherwise, the Gazebo instances contend for the same ports and prevent the Nav2 stack from operating correctly. Traverse the environment by teleoperation or with Nav2 waypoints, and record a systematic room-by-room route. The evaluation includes spatial coverage, so the route must extend beyond the entrance area.
The remaining Compose services transport simulator data to persistent storage. zenoh-router provides the message bus and in-memory storage. zenoh-bridge runs zenoh-bridge-ros2dds and forwards camera, depth, odometry, and detection messages. The GPU-enabled detector service contains the reference YOLOv8 and CLIP pipeline. embedding-ingest subscribes to Zenoh and writes embeddings to vector, a PostgreSQL database with pgvector exposed on port 5436. A second PostgreSQL service, age, provides Apache AGE on port 5435.
Task 1: Detector node
Zenoh decouples the perception pipeline from the ROS 2 installation. The detector runs outside the ROS 2 container as a standard Python process and does not importrclpy. It can therefore process robot data on a GPU host without a local ROS installation. The pipeline uses the following Zenoh keys:
The bridge forwards the raw Common Data Representation (CDR) payload from DDS without re-encoding it. Define the required ROS message types as
IdlStruct dataclasses and deserialize each Zenoh payload with pycdr2. The following abbreviated definition illustrates the required structure:
open_clip ViT-B-32 model and the laion2b_s34b_b79k weights. L2-normalize the resulting 512-dimensional embeddings so that their dot product is equal to cosine similarity. CLIP embeddings are used in place of YOLOv8 backbone features because they are more suitable for associating an object across changes in viewpoint. The detection and embedding pipeline describes these stages in more detail.
Study object_detector.py in the reference repository and explain its data flow in the report. The submitted implementation must demonstrate independent work; an unchanged copy of the reference file does not satisfy this requirement.
YOLOv8 was trained on photographs, whereas the simulated environment is rendered from AWS furniture meshes. In this environment, the most consistently detected classes are chair, couch, bed, tv, potted plant, dining table, vase, book, clock, refrigerator, sink, toilet, microwave, and oven. Many other COCO classes are not represented. Quantify this domain and class-coverage limitation with per-class measurements. Additional COCO objects, such as a cup, bottle, or laptop, may be placed on a kitchen counter by following the model-placement procedure on the Gazebo worlds page.
Task 2: From bounding box to map coordinates
Subscribe to the depth and odometry streams in addition to the color stream. For each accepted color keyframe, select the depth image and odometry sample with the nearest timestamps. Reject the keyframe if either timestamp differs from the color timestamp by more than 200 ms. Arrival order does not provide synchronization because transport and inference delays can reorder messages. Gazebo publishes depth images as 32-bit floating-point values in meters. For each detection, reduce the bounding box to a documented central fraction, collect the finite positive depth samples in that region, and use their median as the object depth. A single center pixel may lie between chair slats or legs and measure the wall behind the object. The median over an interior region is less sensitive to such gaps, object boundaries, and isolated invalid samples. Reject a detection when the interior region contains too few valid samples. Let be the center of the detection box and let be its median depth. The simulated Intel RealSense D435i produces images at pixels with Back-project the detection into the camera optical frame: The optical axes are -forward, -right, and -down. ROS body axes are -forward, -left, and -up, giving the fixed optical-to-body conversion The camera transform from the URDF has translation and no rotation. Compose the full transform in this order: Here is the optical-to-body rotation, the fixedbase_link to camera transform, and the map to base_link transform. Implement the chain with homogeneous coordinates and construct from the synchronized robot pose. Check the odometry message frame before treating that pose as a map pose. When it is expressed in an odometry frame, apply the corresponding map-to-odometry transform first and document how you obtained it.
An incorrect optical-frame conversion may produce a map that appears plausible but is mirrored or rotated by 90 degrees. Test the complete transform chain against a hand-computed result. The test must pass a known robot pose, bounding-box pixel, and depth through the implementation and compare the resulting map coordinate with the expected value using a stated tolerance. Select a pixel away from the image center so that the test exercises every axis conversion.
Task 3: Semantic object database
Create the pgvector extension and use these two tables:range_m denotes horizontal or three-dimensional distance and must define the zero direction and positive sign convention for bearing_rad.
Each row in semantic_objects represents the current estimate of one physical object. The corresponding rows in object_observations preserve the measurements used to form that estimate. This separation supports indexed retrieval of every pose from which an object was observed without requiring a scan of the raw detector output. The same database supplies the semantic graph layer, in which objects and spatial relations are represented as graph entities.
Task 4: Deduplication
Associate each new detection only with stored objects that have the sameclass_name and whose fused map positions lie within a selected spatial radius. If the candidate set is empty, create a semantic object and its first observation. If it contains one object, merge the detection with that object. If it contains multiple objects, select the candidate with the highest CLIP cosine similarity. Insert a new observation row for every accepted detection.
Select the association radius using measurements of depth noise, transform error, bounding-box variation, and viewpoint change. Document both the selected value and the measurements used to justify it.
On a merge, update the fused position with a running average:
Update the mean embedding by the same rule, L2-normalize it again, increment observation_count, update last_seen_ns, and insert the new evidence row. In pgvector, <=> is cosine distance. For normalized vectors, it equals one minus their dot product, so the smallest distance identifies the most similar candidate.
A group of four dining chairs illustrates the limitation of spatial-radius association. Although the chairs are distinct objects, several may fall within a radius large enough to accommodate the position error obtained when one chair is viewed from opposite sides. A smaller radius tends to produce duplicate records, whereas a larger radius tends to produce false merges. Measure how the selected radius and the embedding-based tie-break rule affect both outcomes.
Task 5: Querying the database
Implement and demonstrate the following parameterized queries. Do not interpolate values into SQL. Find the nearest instance of a requested class to a map point:Evaluation
Use the world SDF to establish ground-truth instance counts for every detectable class. Count distinct physical instances separately, including instances that use similar mesh assets or model names. Define instance precision as the number of correctly matched stored objects divided by the total number of stored objects. Define instance recall as the number of correctly matched stored objects divided by the number of ground-truth objects. The duplicate rate is the number of stored objects divided by the number of ground-truth objects. Its ideal value is1.0; values above 1.0 indicate duplicate records, while values below 1.0 may indicate missed objects or false merges. The detection rate is the fraction of relevant keyframes that contain at least one correct detection of the class, where a relevant keyframe is one in which an instance of that class is visible. Also report false merges, in which one stored record contains observations from multiple physical objects, and misses, in which a ground-truth object has no stored record. Interpret these measures using the observation histories and estimated map positions.
The chair row is an example. Add one row for each remaining class.
Include a map plot of the fused object positions, with each point labeled by class and object identifier. Overlay the traversal route or the accepted robot poses to distinguish incomplete spatial coverage from detector failures. Discuss classes that are absent from the environment, rarely visible, or consistently missed by the detector.
Deliverables
Submit:- The detector source code, including Zenoh subscriptions, CDR message definitions, keyframe gating, YOLOv8 inference, and batched CLIP embedding.
- The depth synchronization and map back-projection implementation.
- The transform-chain unit test and its hand-computed expected result.
- The SQL schema and database-ingest code.
- The deduplication implementation with its documented radius and similarity rule.
- Executable versions of the four required database queries.
- A database export containing semantic objects and their observations.
- A map plot showing object estimates, identifiers, and coverage.
- A report containing the route, per-class evaluation, duplicate-rate analysis, failure cases, and design choices.
- A short README with commands needed to run your implementation against the compose services.

