How jon-bon-jono/vip_mmwave_hpe_demo works
1. Overall shape
- This is a ROS 2 Jazzy workspace organized as three real runtime layers plus one future ML placeholder:
- vip_hpe_msgs for shared message definitions
- vip_hpe_core for ROS-free preprocessing and constants
- vip_hpe_runtime for ROS nodes, launch/session orchestration, replay, and visualization
- ml/ as a future training framework, intentionally ignored by colcon
2. Primary runtime data flow
- The default demo is a replay pipeline, not live sensor capture.
- Data flows from prerecorded pickle data into ROS topics, then through preprocessing, then to visualization:
- radar point-cloud replay publishes vip_hpe_msgs/RadarFrame on /radar/points
- pose emulation subscribes to /radar/points, preprocesses the point cloud, and publishes vip_hpe_msgs/PersonPose3DArray on /pose/people
- the animated plot node subscribes to both topics and renders the result
3. Session/launch orchestration
- vip_hpe_runtime/launch/session.launch.py starts a full session from YAML under src/vip_hpe_runtime/config/sessions/.
- The session config defines workspace root, topics, source selection, pose mode, preprocessing config, and sinks.
- This is the main composition boundary: the launch layer wires together nodes based on config rather than hardcoding the graph.
4. Runtime nodes
- radar_replay_node replays radar frames from a pickle file.
- pose_gt_inference_emulator_node is the key bridge node: it makes replayed radar look like a future inference path by converting RadarFrame to NumPy, building a preprocessor from YAML, and publishing matching ground-truth pose.
- animated_plot_node is a visualization sink using Matplotlib 3D.
- pose_gt_replay_node and live_model_inference_node exist as additional runtime modes/placeholders in the same node family.
5. Replay subsystem
- vip_hpe_runtime/replay/living_lab.py parses the UNSW Living Lab pickle dataset used by the demo.
- replay_base.py likely provides shared playback behavior for replay-style nodes.
- This subsystem isolates dataset parsing and timed replay from ROS publishing and from pose preprocessing.
6. ROS adapters and message boundary
- vip_hpe_runtime/adapters/ros_conversions.py is the translation layer between ROS message types and internal Python/NumPy representations.
- Custom messages in vip_hpe_msgs/msg/ define the runtime contract:
- RadarFrame, RadarPoint
- Joint3D, PersonPose3D, PersonPose3DArray
- This package is the cross-package interface used by runtime nodes and any future live inference implementation.
7. Shared preprocessing core
- vip_hpe_core is explicitly the non-ROS, non-PyTorch shared domain layer.
- Its main modules are:
- preprocessing/base.py for the preprocessor interface
- preprocessing/config.py for YAML-driven construction
- preprocessing/registry.py for name-to-class lookup
- preprocessing/model_input.py for the model-facing data container
- The dummy preprocessor config in src/vip_hpe_core/config/preprocessing/dummy_pointcloud.yaml is the current example implementation.
8. Dependency boundary
- vip_hpe_core must stay free of ROS, rclpy, vip_hpe_msgs, PyTorch, Ultralytics, ONNX Runtime, and Matplotlib.
- vip_hpe_runtime is allowed to depend on ROS and on vip_hpe_core.
- ml/ is the intended home for future PyTorch training code and should reuse vip_hpe_core rather than duplicating preprocessing logic.
- This separation is the key architectural constraint in the repo.
9. Constants and sensor/domain presets
- vip_hpe_core/constants/ contains sensor- or environment-specific constants such as iwr6843.py, kinect.py, and living_lab.py.
- These files suggest the project is meant to normalize differences between radar hardware, Kinect-derived ground truth, and the Living Lab dataset.
- They act as shared reference data for preprocessing and replay without tying the core to any particular runtime node.
10. Configuration-driven behavior
- Runtime behavior is mostly configured through YAML, not code changes.
- The default session config points to the dummy point-cloud preprocessor YAML, and pose mode replay_gt_synced demonstrates the future inference contract.
- The topic names are part of the config contract and are meant to stay stable as the system evolves from replay/emulation to live inference.
11. Testing and CI
- Tests are split by layer:
- tests/core for ROS-free preprocessing and architecture boundaries
- tests/runtime for replay/runtime parsing and node-adjacent logic
- tests/ml as a placeholder
- The existence of a dependency-boundary test is important architecturally: it enforces the split between shared core logic and ROS runtime.
- GitHub Actions runs pytest for the core package.
12. What a diagram should emphasize
- Show data/ll_replay/07_SW.pickle feeding the replay node.
- Show a ROS topic bus with /radar/points and /pose/people as the central data channels.
- Place vip_hpe_core off to the side as a pure preprocessing library used by runtime and future ML.
- Place vip_hpe_msgs as the shared schema boundary between producers, consumers, and future live inference.
Main entry points: pose_gt_inference_emulator_node.py Pose emulator · radar_replay_node.py Radar replay · builders.py Builders · config.py Preproc config
Components 27
vip_hpe_runtime
ROS 2 nodes, launch/session wiring, replay, and visualization
- Session launch · Starts a full demo session from YAML config
src/vip_hpe_runtime/launch/session.launch.py - Replay session · Defines workspace root, topics, source selection, pose mode, preprocessing config, and sinks
src/vip_hpe_runtime/config/sessions/replay_pc_gt_pose_visualize.yaml - Launch config · Parses and validates session settings before node creation
src/vip_hpe_runtime/vip_hpe_runtime/launching/config.py - Builders · Constructs runtime nodes and wiring from config
src/vip_hpe_runtime/vip_hpe_runtime/launching/builders.py - Validation · Checks that session composition is internally consistent
src/vip_hpe_runtime/vip_hpe_runtime/launching/validation.py - Radar replay · Replays prerecorded radar frames into ROS topics
src/vip_hpe_runtime/vip_hpe_runtime/nodes/radar_replay_node.py - Pose emulator · Bridges replayed radar into preprocessing and publishes ground-truth pose
src/vip_hpe_runtime/vip_hpe_runtime/nodes/pose_gt_inference_emulator_node.py - Pose replay · Alternative pose replay mode in the same runtime family
src/vip_hpe_runtime/vip_hpe_runtime/nodes/pose_gt_replay_node.py - Live inference · Placeholder node for future online model inference
src/vip_hpe_runtime/vip_hpe_runtime/nodes/live_model_inference_node.py - Animated plot · Subscribes to radar and pose topics and renders the 3D result
src/vip_hpe_runtime/vip_hpe_runtime/nodes/animated_plot_node.py - Replay base · Shared playback behavior for replay-style runtime nodes
src/vip_hpe_runtime/vip_hpe_runtime/nodes/replay_base.py - Living Lab parser · Loads the UNSW Living Lab pickle dataset used by the demo
src/vip_hpe_runtime/vip_hpe_runtime/replay/living_lab.py - ROS conversions · Translates between ROS messages and internal Python/NumPy representations
src/vip_hpe_runtime/vip_hpe_runtime/adapters/ros_conversions.py
vip_hpe_core
ROS-free preprocessing and shared constants
- Preproc config · Builds preprocessors from YAML definitions
src/vip_hpe_core/vip_hpe_core/preprocessing/config.py - Preprocessor API · ROS-free preprocessor contract
src/vip_hpe_core/vip_hpe_core/preprocessing/base.py - Registry · Resolves preprocessor names to implementations
src/vip_hpe_core/vip_hpe_core/preprocessing/registry.py - Model input · Shared model-facing input container
src/vip_hpe_core/vip_hpe_core/preprocessing/model_input.py - Dummy preproc · Current example point-cloud preprocessing setup
src/vip_hpe_core/config/preprocessing/dummy_pointcloud.yaml - IWR6843 · Radar-hardware preset and normalization constants
src/vip_hpe_core/vip_hpe_core/constants/iwr6843.py - Kinect · Kinect-derived ground-truth preset and normalization constants
src/vip_hpe_core/vip_hpe_core/constants/kinect.py - Living Lab · Shared constants for the Living Lab dataset and replay
src/vip_hpe_core/vip_hpe_core/constants/living_lab.py
vip_hpe_msgs
Cross-package ROS message contract
- RadarFrame · Radar frame contract carried on /radar/points
src/vip_hpe_msgs/msg/RadarFrame.msg - RadarPoint · Single radar point representation
src/vip_hpe_msgs/msg/RadarPoint.msg - PersonPose3D · Single 3D person pose representation
src/vip_hpe_msgs/msg/PersonPose3D.msg - PoseArray · Array of person pose messages carried on /pose/people
src/vip_hpe_msgs/msg/PersonPose3DArray.msg - Joint3D · Single joint used inside pose messages
src/vip_hpe_msgs/msg/Joint3D.msg
ml
Future training workspace, currently ignored by colcon
- vip_hpe_ml · Placeholder package for future training code
ml/vip_hpe_ml/__init__.py
Connections 29
- Session launch → Replay session: loads · Launch entrypoint reads the session definition
- Session launch → Launch config: parses · Launch layer turns YAML into a structured config
- Launch config → Validation: validates · Checks composition and topic wiring
- Launch config → Builders: builds · Validated config is used to instantiate nodes
- Builders → Radar replay: creates · Session composition includes the radar replay node
- Builders → Pose emulator: creates · Session composition includes the pose emulator node
- Builders → Animated plot: creates · Session composition includes the visualization node
- Radar replay → Living Lab parser: reads · Replay node consumes the Living Lab pickle dataset
- Radar replay → Replay base: extends · Replay node shares timed playback behavior
- Pose emulator → Replay base: extends · Bridge node reuses replay-style runtime behavior
- Pose emulator → ROS conversions: converts · Translates ROS radar messages into internal arrays and back
- Pose emulator → Preproc config: builds · Constructs the preprocessor from YAML
- Preproc config → Preprocessor API: instantiates · YAML-driven config produces a preprocessor implementation
- Preproc config → Registry: resolves · Registry maps config names to concrete preprocessors
- Preprocessor API → Model input: produces · Preprocessors emit the shared model-facing input structure
- Dummy preproc → Preproc config: example for · Current demo configuration points at the dummy point-cloud setup
- Radar replay → RadarFrame: publishes · Replayed radar frames are emitted as ROS messages
- Pose emulator → RadarFrame: subscribes · Pose emulator consumes radar frames from the bus
- Pose emulator → PoseArray: publishes · Bridge node emits synchronized pose output
- Animated plot → RadarFrame: subscribes · Visualization reads radar frames from the topic bus
- Animated plot → PoseArray: subscribes · Visualization reads pose output from the topic bus
- RadarFrame → RadarPoint: contains · Radar frame wraps individual radar points
- PoseArray → PersonPose3D: contains · Pose array wraps per-person pose messages
- PersonPose3D → Joint3D: contains · Person pose is composed of 3D joints
- Pose emulator → IWR6843: uses · Preprocessing may rely on radar hardware constants
- Pose emulator → Kinect: uses · Ground-truth pose alignment may rely on Kinect constants
- Radar replay → Living Lab: uses · Replay behavior uses Living Lab dataset constants
- vip_hpe_ml → Preprocessor API: reuses · Future training code is expected to share preprocessing logic
- vip_hpe_ml → Model input: consumes · Training code should consume the shared model input contract