Input

Documentation for each input module in the main NUbots codebase
Updated 8 Nov 2026

Camera

Description

Subscribes directly to the Booster K1's camera topics using the Booster Robotics SDK (1.7) over DDS, and emits the frames as message::input::Image.

Usage

data/config/Camera.yaml contains the following information under cameras:

  • topic: the DDS topic carrying sensor_msgs/Image. This is the ROS 2 topic path prefixed with rt/, so ROS 2 topic /boostercamera/head/rgb becomes rt/boostercamera/head/rgb
  • name: name of the camera, used to differentiate between outputs
  • id: camera ID to differentiate between images

Topics are subscribed to once at startup. Changing topic in the config while running will not re-point the subscriptions; restart the binary instead.

Consumes

  • message::input::Sensors to buffer recent Hcw transforms

Emits

  • message::input::Image

Dependencies

FakeCamera

Description

Loads compressed images (JPEGs) and corresponding lens parameters (YAML files) from the specified folder and emits them as CompressedImage messages

Images are and lens files are expected to be named using a common theme (e.g. image000001.jpg and lens000001.yaml).

Usage

In the config file set image_folder to be the path to the folder containing the image and lens files, image_prefix to the portion of the filename that is common to all image files and lens_prefix to the portion of the filename that is common to all lens files.

image_folder: 'images'
image_prefix: 'image'
lens_prefix: 'lens'

All images are assumed to be JPEGs with either a .jpg or .jpeg extension. All lens files are assumed to be YAML files with a .yaml extension.

Lens files should contain the following information

projection: EQUISOLID # Either RECTILINEAR, EQUIDUSTANT, or EQUISOLID
focal_length: 420 # Un-normalised focal length in pixels
centre: [0, 0] # Distance between the camera centre axis and optical axis in pixels (measured from the centre of the image)
k: [0, 0] # Distortion coefficients
fov: 1.59286 # Field of view in radians
Hoc: # Camera to observation plane (world) homogeneous transformation
- [-0.308872, 0.945477, 0.103304, 0]
- [-0.84664, -0.223831, -0.482805, 0]
- [-0.433359, -0.236586, 0.869613, 0.9]
- [0, 0, 0, 1]

Emits

  • message::output::CompressedImage with a JPEG FOURCC code

Dependencies

  • Eigen
  • libjpeg-turbo

Game Controller

Description

Listens for RoboCup GameController UDP broadcast packets, converts them into NUClear messages, and maintains a canonical message::input::GameState.

The module also sends periodic reply packets back to the GameController.

Usage

Install module::input::GameController in the powerplant.

This module is configured by GameController.yaml and consumes:

  • message::support::GlobalConfig for team_id and player_id

At runtime it:

  • Listens for UDP broadcast packets on receive_port
  • Accepts only supported packet version 19
  • Optionally filters incoming packets by source IP using udp_filter_address
  • Tracks the sender address and sends reply packets to that address on send_port
  • Sends ALIVE reply packets every 2 seconds

Emits

  • message::input::GameState
  • message::input::GameState::Phase
  • message::input::GameState::Mode
  • message::input::GameState::TeamColour
  • message::input::GameEvents::Score
  • message::input::GameEvents::GoalScored
  • message::input::GameEvents::Penalisation
  • message::input::GameEvents::Unpenalisation
  • message::input::GameEvents::HalfTime
  • message::input::GameEvents::KickOffTeam
  • message::input::GameEvents::GamePhase
  • message::input::GameEvents::GameMode

Also sends UDP GameController reply packets via emit<Scope::UDP>(...).

Dependencies

  • NUClear UDP networking (for broadcast receive and unicast reply)

ImageDecompressor

Description

Decompresses images that are in JPEG format to raw images, using a variety of decompressors. It will use decompressors in order until it finds a free one to compress the image. In the event that no compressors are currently free it will drop the image.

Usage

Triggers on message::output::CompressedImage Configuration from ImageDecompressor.yaml

Emits

  • message::input::Image

Dependencies

  • TurboJPEG

NatNet

Description

Receives OptiTrack NatNet motion-capture packets and converts them into message::input::MotionCapture.

The module listens to NatNet data broadcasts, pings the discovered server, requests model definitions, and then parses frame packets into NUbots mocap messages.

In the Motive software, ensure the advanced streaming settings are set to the following:

Motive Streaming Settings

Broadcast Frame Data: On Local Interface: <motive_device_ip> # Set to the ip of the device running motive, sometimes toggling on/off needed

Marker Options

  • Labeled Markers: Off
  • Unlabeled Markers: Off
  • Asset Markers: Off

Rigid Body Options

  • Rigid Bodies: On
  • Skeletons: Off
  • Skeleton Coordinates: Global
  • Skeleton As Rigid Bodies: Off
  • Bone Naming Convention: Motive
  • Up Axis: Z Up

Miscellaneous

  • Remote Trigger: Off
  • Transmission Type: Multicast
  • Subject Prefix:
  • Visual3D Compatible: Off
  • Scale: 1

Networking

  • Command Port: 1510
  • Data Port: 1511
  • Multicast Interface: 239.255.42.99
  • Multicast as Broadcast: On
  • Socket Size: 1000000

Usage

Install module::input::NatNet and configure NatNet.yaml.

Default configuration values:

  • multicast_address: 239.255.42.99
  • command_port: 1510
  • data_port: 1511
  • dump_packets: false
  • max_delay_samples: 100

At runtime the module:

  • Binds UDP sockets for NatNet command and data traffic
  • Detects the active NatNet server from incoming broadcast packets
  • Sends a NatNet ping and reads the remote protocol version
  • Requests model definitions when needed
  • Estimates and logs network delay statistics

Consumes

  • extension::Configuration from NatNet.yaml
  • NUClear::UDP::Packet (NatNet command traffic)
  • NUClear::UDP::Packet via UDP::Broadcast on data_port (NatNet frame traffic)

Emits

  • message::input::MotionCapture

Dependencies

  • An OptiTrack motion capture system sending packets over the network using the NatNet protocol.

NUSimCamera

Description

Reads the camera image out of the shared-memory segment written by NUSim (the MuJoCo simulator's Camera module / SharedImageWriter) and emits it as message::input::Image. NUSimCamera reads NUSim's VERSION 2 lock-free seqlock layout.

Use this module in roles/nusim/*; use input::Camera in the on-robot roles.

Usage

data/config/NUSimCamera.yaml lists, under cameras:

  • segment: name of the Boost shared-memory segment NUSim writes
  • id: camera ID to differentiate between images
  • name: name of the camera, used to differentiate between outputs

Emits

  • message::input::Image

Dependencies

  • Boost
  • NUSim writing the camera shared-memory segment (SharedImageWriter, VERSION 2 seqlock)

Sensors

Description

Emits a message::input::Sensors message based on input from the K1's odometry and sensor data.

Usage

When installed, it subscribes to the head pose DDS topic at startup and reacts to incoming message::platform::RawSensors to build and emit a message::input::Sensors each tick along with the odometry from the K1. Button edge transitions are also detected and emitted as separate messages.

The head pose reader is also created once at startup; changing head_pose.topic in config after that requires a restart to take effect.

Consumes

  • message::platform::RawSensors to build the outgoing Sensors message, including servo, IMU, button, and LED state.
  • message::booster::BoosterOdometry, paired with RawSensors, for the robot's odometry-derived world pose.
  • message::booster::BoosterModeState to detect motion mode changes and reset the odometry zero offset.
  • message::localisation::ResetFieldLocalisation to reset the odometry zero offset after a localisation reset.

Emits

  • message::input::Sensors with filtered/converted sensor data and odometry.
  • message::input::ButtonLeftDown / ButtonLeftUp when the left button changes state.
  • message::input::ButtonMiddleDown / ButtonMiddleUp when the middle button changes state.

Dependencies

  • Eigen
  • Booster Robotics SDK

WhistleDetection

Description

Detects a referee whistle in real-time from the robot's microphone and emits a message::input::Whistle message when one is confirmed.

The algorithm mirrors the signal-processing front-end used by the NaoDevils AudioProcessing project (from which the labelled dataset was obtained):

  1. Capture mono audio via ALSA at 16 kHz.
  2. Accumulate samples into 1024-point windows with 50 % overlap (one new window every 32 ms).
  3. Apply a Hanning window and compute the one-sided power spectrum via a radix-2 Cooley-Tukey FFT.
  4. Compute the fraction of total spectral power that falls in the configurable whistle frequency band (default 2–4.5 kHz).
  5. Require confirm_frames consecutive windows above band_ratio_threshold before emitting, and enforce a cooldown_ms gap between successive events.

Usage

Add the module to a role file and tune WhistleDetection.yaml for the deployment environment (primarily band_ratio_threshold and min_band_energy, which depend on microphone gain and background noise level).

Consumes

Nothing — audio is read directly from the ALSA device.

Emits

  • message::input::Whistle — fired once per confirmed whistle with a timestamp and a confidence value in [0, 1].

Dependencies

  • ALSA (libasound) — already a project-wide utility dependency.
NUbots acknowledges the traditional custodians of the lands within our footprint areas: Awabakal, Darkinjung, Biripai, Worimi, Wonnarua, and Eora Nations. We acknowledge that our laboratory is situated on unceded Pambalong land. We pay respect to the wisdom of our Elders past and present.
Copyright © 2026 NUbots - CC-BY-4.0
Deploys by Netlify