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:
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/venvwith 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:
Verify hardware connectivity:
Running Tests¶
Locally on the Raspberry Pi:
Or with explicit environment variables:
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_scriptregardless 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:
- Test-level:
SafeRotatorfixture clamps positions to configured limits (az 0-450, el 0-180 for G-5500) and waits for movement completion - CI-level:
after_scriptunconditionally parks the rotator at (0, 0) - 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) |