Skip to content

HIL Testing

Hardware-in-the-Loop Testing

TALOS supports full end-to-end testing with real ground station hardware. A dedicated Raspberry Pi test station runs the TALOS agent alongside actual rotator and SDR hardware, validating the complete data path from MQTT commands through Hamlib daemons to physical hardware movement and RF tuning.


Hardware Requirements

Component Model Purpose
Single Board Computer Raspberry Pi 4/5 (64-bit) Test station host
SDR Ettus USRP B200mini RF reception and frequency tuning
Rotator Controller Yaesu G-5500 Antenna azimuth/elevation control
USB-Serial Adapter FTDI/CP2102/PL2303 G-5500 serial interface
Antenna VHF/UHF capable Signal reception (optional for tuning tests)

Provisioning

The ops/rpi/provision.sh script performs idempotent setup on a fresh Raspberry Pi OS Bookworm (64-bit) installation:

sudo bash ops/rpi/provision.sh

This installs:

  • hamlib-utils -- rotctld and rigctld daemons
  • uhd-host -- USRP Hardware Driver and firmware
  • soapysdr-tools -- SoapySDR framework for rigctld backend
  • Python venv at /opt/talos/venv with test dependencies
  • systemd services for rotctld, rigctld, and a test Mosquitto broker
  • udev rules for stable USB device paths

Configuration

Edit /opt/talos/hardware.env with your site-specific parameters:

# Yaesu G-5500 via GS-232A protocol
ROTATOR_MODEL=601
ROTATOR_DEVICE=/dev/ttyUSB0
ROTATOR_SPEED=9600
ROTCTLD_PORT=4533

# USRP B200mini via SoapySDR
RIG_MODEL=2513
RIG_DEVICE="driver=uhd,type=b200"
RIGCTLD_PORT=4532

# Safety limits
AZ_MAX=450
EL_MAX=180

Start the hardware daemons:

sudo systemctl start talos-rotctld talos-rigctld talos-mosquitto-test

Verify hardware connectivity:

# Rotator
rotctl -m 601 -r /dev/ttyUSB0 -s 9600 p

# USRP
uhd_usrp_probe --args=type=b200

Running Tests

Locally on the Raspberry Pi:

make test-hil

Or with explicit environment variables:

TALOS_HIL=1 pytest tests/test_integration/test_hil.py -v --tb=short -x

Tests are gated by TALOS_HIL=1 and skip automatically without it.


Test Architecture

Tests are in tests/test_integration/test_hil.py with shared fixtures in tests/test_integration/conftest_hil.py. They are organized in progressive complexity:

Class Tests Validates
TestHardwareHealth 3 Daemon connectivity, USRP detection
TestRotatorMovement 4 Physical movement, sweep, elevation range, park
TestSdrTuning 3 VHF/UHF tuning, frequency change speed
TestAgentIntegration 5 MQTT-to-hardware bridge, config push, telemetry
TestFullPassSimulation 2 Complete ISS pass arc, session lifecycle

The SafeRotator fixture wraps all rotctld commands with:

  • Position clamping to configured hardware limits
  • Movement wait with polling and configurable timeout
  • Automatic park (az=0, el=0) on fixture teardown

CI Integration

A GitLab Runner with shell executor runs on the Raspberry Pi, tagged hil. The test-hil CI job:

  • Runs on every MR and default branch push
  • Configured with allow_failure: true (advisory, does not block merges or deployments)
  • Parks the rotator in after_script regardless of test outcome
  • Has a 10-minute job timeout with 120-second per-test timeout

Register the runner:

sudo gitlab-runner register \
  --url https://gitlab.com \
  --executor shell \
  --tag-list 'hil,arm64,rpi' \
  --run-untagged=false

Runner config.toml should set concurrent = 1 to prevent parallel access to shared hardware.


Safety

Three layers of protection prevent hardware damage:

  1. Test-level: SafeRotator fixture clamps positions to configured limits (az 0-450, el 0-180 for G-5500) and waits for movement completion
  2. CI-level: after_script unconditionally parks the rotator at (0, 0)
  3. OS-level: systemd services auto-restart on daemon crash

Troubleshooting

Issue Check
USRP not detected uhd_usrp_probe --args=type=b200 -- ensure UHD firmware is downloaded via uhd_images_downloader
Serial permission denied Verify udev rules: ls -la /dev/ttyUSB* -- user must be in dialout group
rotctld won't start Check serial device: dmesg \| grep tty -- verify USB-serial adapter connected
rigctld connection refused Verify SoapySDR module: SoapySDRUtil --find -- USRP must appear in output
MQTT broker unreachable Check test broker: systemctl status talos-mosquitto-test
Tests skip unexpectedly Ensure TALOS_HIL=1 is set in the environment
Rotator moves erratically Check serial baud rate matches G-5500 setting (default 9600)