Skip to content Link Search Menu Expand Document
ModalAI DOCS
Store

VRX Ground Unit Developer Guide

SDK, shell access, and configuration on the VRX ground unit.

Table of contents

  1. VOXL SDK Support
    1. SDK Versions
  2. VRX Software Reference
    1. voxl-vrx Service
    2. Configuration File Reference
      1. Wireless Reception
      2. Video Display
      3. Sharpening Filter
      4. OSD (VRX side)
      5. Decoder Performance
      6. Recording
      7. Telemetry & Network
      8. System
    3. Buttons: Scan and Record
    4. VRX SETTINGS Menu
    5. RF Occupancy Scanner
    6. Inspecting the Link
    7. What the RF Link Carries
  3. Use Cases
    1. Video Streaming over RF
      1. Using Multiple VRX to View Single VTX
      2. Viewing Multiple VTX from Single VRX
    2. Video Streaming over IP Networks
      1. Overview
      2. Block Diagrams
      3. VRX Software Configuration
      4. VTX Software Configuration
      5. Interface Options
        1. Ethernet Adapter
        2. Doodle Labs
        3. LTE
    3. Static IP from VRX with USB-to-Ethernet
    4. RTSP Stream From VRX
    5. SSH Access to VRX
    6. ADB Access to VRX
    7. voxl-joystick-server Setup
      1. USB Mode
      2. Joystick Configuration
        1. Mixes setup
        2. Joystick Axes and Switches/Buttons Setup
      3. Application Configuration
      4. Troubleshooting
        1. Joystick to VRX interface
        2. Joystick Network Connection to VTX/UAS
        3. Check For mamual control events From VRX
        4. Check For manual_control_setpoint Events from PX4
    8. AI Detection

VOXL SDK Support

SDK Versions

The VRX runs its own SDK image (5.4 kernel, Ubuntu 20 rootfs), separate from the image flashed on the drone. The SDK version numbers match, and the VRX and the drone must run the same SDK version.

SDK VersionFile NameLink
VRX 1.8.0ubun2.0-multi_SDK_1.8.0.tar.gzDownloads
VRX 1.6.6ubun2.0-multi_SDK_1.6.6.tar.gzDownloads
VRX 1.5.0ubun2.0-multi_SDK_1.5.0.tar.gzDownloads

Run the same SDK on the drone and the VRX. voxl-vtx 3.3 (SDK 1.8.0) requires voxl-osd 1.2.0 or newer on the drone, so a drone on SDK 1.8.0 needs a VRX on VRX SDK 1.8.0. Stinger ships with SDK 1.8.0.

VRX Software Reference

voxl-vrx Service

voxl-vrx receives the RF (or UDP) stream, FEC-decodes it, decodes the video, and renders it to the DisplayPort output with the OSD overlay. It runs as the systemd service voxl-vrx.service and restarts automatically.

Enable/configure it with voxl-configure-vrx:

voxl-configure-vrx --enable       # enable the service and load kernel modules
voxl-configure-vrx --list         # show the current configuration
voxl-configure-vrx --wizard       # interactive settings editor
voxl-configure-vrx --frequency 5805

Options (VRX SDK 1.8.0):

OptionMeaning
-l, --listShow the current configuration
-F, --frequencySet the frequency in MHz
-b, --bandwidthSet the bandwidth (20 or 40 MHz)
-e, --enableEnable voxl-vrx and load the kernel modules
-d, --disableDisable voxl-vrx
--blackout-modeSet blackout_mode
--osd-on-link-lossSet osd_on_link_loss (0, 1 or 2)
--link-loss-indicatorSet link_loss_indicator
-w, --wizardInteractive settings editor

Factory presets enable the service and restore a known-good configuration for each radio option:

PresetRadio
-f, --factory_enable_spark_lanSparkLAN modem (default RF setup)
-m, --factory_enable_mini_piniMini Pini modem
-L, --factory_enable_lteLTE
-I, --factory_enable_fiberFiber (UDP)
-D, --factory_enable_doodleDoodle Labs (UDP)
--factory_enable_dtcDTC (UDP)
--factory_enable_silvusSilvus (UDP), SDK 1.8.0+

Configuration File Reference

/etc/modalai/voxl-vrx.conf (JSON), written by voxl-configure-vrx (-f or any preset). frequency, bandwidth, and FEC settings must match the VTX. The tables below list the fields and the values voxl-configure-vrx writes in VRX SDK 1.8.0.

Wireless Reception

FieldDefaultMeaning
frequency5805Center frequency in MHz (must match VTX)
bandwidth2020 or 40 MHz (must match VTX)
card"wlan0"Radio interface (wlan0 SparkLAN, ath0 Mini Pini)
enable_pcaptrueReceive via RF
enable_fectrueForward error correction (must match VTX)
enable_stbctrueSpace-Time Block Coding
enable_lq_resptrueAnswer link-quality requests from the VTX (needed for adaptive link)

Video Display

FieldDefaultMeaning
encoding"h265""h264" or "h265"
stretch_to_screenfalseFill the screen (may distort aspect ratio)
splash_on_lost_linkfalseShow the splash screen when the link is lost
blackout_modefalseShow a black screen instead of splash/last frame when video is not live
osd_on_link_loss10 = no OSD on link loss, 1 = full OSD, 2 = minimal (loss %, RSSI, FPS, channel, temp)
link_loss_indicatortrueProof-of-life indicator when the OSD is suppressed during link loss
stream_timeout_ms100Time before declaring the stream lost
v_synctruePage-flip at vblank (tear-free). false renders straight to the scanned-out buffer, saving up to one frame (about 8 ms mean at 60 Hz) of latency at the cost of a possible tear line
display_width1280Requested display output width in pixels (0 = display’s preferred mode)
display_height720Requested display output height in pixels (0 = display’s preferred mode)
display_refresh_hz0Requested refresh rate (0 = highest available at that size)
headlessfalsePublish the reassembled H.264/H.265 stream on the vrx_encoded pipe without decoding or displaying it. SDK 1.8.0+

Sharpening Filter

An unsharp mask applied to the video before display:

FieldDefaultMeaning
sharpen_amount1.5Strength: 0.0 off, 0.5 subtle, 1.0-2.0 moderate, 3.0+ aggressive
sharpen_threshold0.0Noise gate: minimum edge contrast before sharpening applies

OSD (VRX side)

FieldDefaultMeaning
debug_osdfalseShow debug info on the OSD
ai_detection_enabletrueDraw AI detection boxes received from the VTX
ai_detection_show_labelstrueShow labels on detected objects

The OSD font, theme and which elements are shown are set from the VRX SETTINGS menu in SDK 1.8.0. The osd_font_size field used by older VRX SDKs was removed.

Decoder Performance

FieldDefaultMeaning
overheat_mitigation1Throttle on decode latency: -1 off, 0 or 1 use the latest sample, >1 number of samples averaged
decode_latency_threshold100Decode latency in ms that triggers throttling
display_damaged_framesfalseShow frames the decoder flags as corrupted
drop_all_bad_pframesfalseDrop P-frames until the next I-frame after the decoder flags corruption

Recording

FieldDefaultMeaning
record_videofalseStart recording at startup
allow_record_localfalseAllow recording to internal storage when no USB drive is present

Recordings go to /media/usb/vrx_videos/ when a USB drive is inserted (drives auto-mount at /media/usb), otherwise to /data/video/vrx_videos/ — but only if allow_record_local is true.

Telemetry & Network

FieldDefaultMeaning
gcs_ip"10.0.0.1"GCS/ATAK device IP to forward MAVLink to
telem_tx_ip"10.0.0.2"Local IP telemetry is transmitted from
mavlink_gcs_port14550MAVLink port to/from the GCS
en_mpeg_ts_rebroadcastfalseRebroadcast the encoded video as MPEG-TS over UDP to the GCS
mpeg_ts_rebroadcast_port8901MPEG-TS rebroadcast port
mavlink_upstream_ip""Optional upstream VRX that GCS MAVLink is forwarded through toward the VTX
mavlink_upstream_port-1Port for mavlink_upstream_ip (-1 = unused)
allow_mavlink_forward_while_armedfalseForward GCS MAVLink toward the VTX while the vehicle is armed

System

FieldDefaultMeaning
perf_modetruePerformance CPU governor while armed
enable_button_boardtrueEnable the physical buttons
battery_cell_count2VRX battery cell count for the voltage display
scan_dwell_time_ms500Dwell time per channel during a channel scan
spectrum_dwell_time_ms100Measurement time per channel in the RF occupancy scanner. SDK 1.8.0+
spectrum_settle_time_ms20Time discarded after each retune before measuring. SDK 1.8.0+
spectrum_timeout_ms10000Idle time before the scanner screen closes and video resumes. SDK 1.8.0+
debug_log"off"CSV debug logging: "off", "on", "arm"
ulog"off"Log MAVLink and VTX link stats to a ulog: "off", "on", "arm"

Buttons: Scan and Record

  • A single press of channel up/down steps one channel; a second press in the same direction starts a continuous channel scan (press again to stop). Scan dwell time per channel is scan_dwell_time_ms.
  • The record button toggles video recording (see Recording above for where files land).
  • Function plus up or down opens the RF occupancy scanner (VRX SDK 1.8.0+).

VRX SETTINGS Menu

VRX SDK 1.8.0 renders the OSD on the VRX with a Qt overlay, and the VRX has its own settings menu. Open the drone’s OSD menu with the sticks (vehicle disarmed, see voxl-osd) and select VRX SETTINGS. Stick input is then handed to the VRX: right stick up and down moves, left and right selects or adjusts. Backing out of the VRX menu returns to the drone menu. The menu footer shows the drone SDK (T-SDK) and VRX SDK (R-SDK) versions.

RowOptionsWhat it changes
OSDsubmenuFont, Theme (Day Green or Night Red), Opacity (25 to 100%), and on/off toggles for each OSD element: Video Stats, RF Stats, VTX CPU Stats, Crosshair, Attitude, Telemetry, MGRS, Compass Tape, Home Arrow, Warnings, Link Bar, VIO / Backtrack
DISPLAYsubmenuOSD on Link Loss (Off, Full, Minimal), Display on Link Loss (Last Frame, Splash, Blackout), Link Loss Indicator, VSync. Saved to osd_on_link_loss, splash_on_lost_link / blackout_mode, link_loss_indicator and v_sync
LQ Responseon / offenable_lq_resp. With two VRX units on one VTX, turn it off on the observer’s VRX so only the pilot’s VRX reports link quality to the adaptive link
Goggles Cells1S to 6Sbattery_cell_count, the VRX-side pack used for the goggles per-cell voltage. The drone’s pack is set with BAT CELLS in the drone’s ADVANCED menu

The VRX SETTINGS row needs voxl-osd 1.1.0 or newer on the drone. A VRX on SDK 1.8.0 needs voxl-osd 1.2.0 (SDK 1.8.0) on the drone.

RF Occupancy Scanner

VRX SDK 1.8.0 adds a spectrum scanner. Press function plus up or down on the VRX buttons to open it. The VRX sweeps every channel it can tune and shows a tile per channel, in frequency order, with the channel number, frequency, the percentage of time the channel was busy and the measured noise floor in dBm. Busy readings below 10% use the theme accent color (green in Day Green, red in Night Red), 10 to 35% is orange, and above that is red. Channels that cannot be measured show unavailable.

On the scanner screen up and down move between channels, record selects the highlighted channel and function exits. With no input for spectrum_timeout_ms (10 s by default) the scanner closes and video resumes. Measurement timing is set by spectrum_dwell_time_ms and spectrum_settle_time_ms.

voxl-inspect-vrx -n

prints live receive stats — bitrate, frame/decode/total latency, SNR, noise floor, and packet loss.

In SDK 1.8.0 the link is two-way. From the VTX to the VRX it carries:

  • the encoded video stream (H.264 or H.265) and its forward error correction
  • MAVLink telemetry forwarded from PX4 at mavlink_telem_rate_hz, which the VRX renders on the OSD and can forward to a GCS or ATAK device on its IP network (see Telemetry & Network)
  • the OSD data from voxl-osd
  • AI detection metadata drawn as bounding boxes on the VRX OSD (see AI Detection)

From the VRX back to the VTX it carries:

  • link-quality responses (SNR and packet loss) that drive the adaptive link, when enable_lq_resp is on
  • OSD menu navigation commands for the VRX SETTINGS menu and channel-change requests from the VRX command pipe
  • MAVLink from a GCS on the VRX’s network, forwarded toward the VTX. By default this stops while the vehicle is armed (allow_mavlink_forward_while_armed)

It is not a general-purpose data channel. There is no supported way to send custom companion-computer data (for example, application-generated observations as binary or JSON) between the drone and a ground station over the digital video link. RC stick and switch inputs to PX4 use the separate ELRS 915 MHz RC link.

If your application needs a bidirectional data path between the drone and a ground station, use an IP link: the VTX’s SoftAP mode or an external WiFi dongle in station mode, a USB-to-Ethernet adapter, or an LTE or mesh modem, as described under Video Streaming over IP Networks. Note that the VTX radio and the built-in WiFi share the same hardware, so RF video and built-in WiFi cannot run at the same time; see the VTX Software Guide.

SDK 1.6.0 and 1.6.1 were air to ground only. From SDK 1.6.3 the VRX also returns link-quality responses and GCS MAVLink. SDK 1.8.0 adds menu commands and channel-change requests.

Use Cases

Video Streaming over RF

This is how systems are configured by default and use the integrated RF path to stream video.

One VTX streaming to one VRX over RF

Using Multiple VRX to View Single VTX

Multiple VRXs can view the stream from the same VTX (assuming they share encryption keys) and are on the same channel.

One VTX viewed by multiple VRX units

Viewing Multiple VTX from Single VRX

Again assuming the VTXs and VRXs share the same encryption keys, we can stream from multiple VTXs to a VRX (or again multiple VRXs…).

For this use case, we need to first configure the VTXs to be on different channels. The procedure is as follows:

Setup:

  • Ensure VTXs/VRXs have same encryption key (or are all using the default)
  • Power on one VTX at a time
  • Change the frequency/channel of the VTX using the OSD menu (see this video at 223 seconds as to how to change frequencies/channels)
  • Power off the VTX
  • Set VRX back to default frequency/channel (5805/161)
  • Power on next VTX to setup (assuming its out of the box, default frequency is 5805), and change frequency again off the default. Repeat for N VTXs.

Usage:

  • All VTXs and VRX can be powered on now
  • Using the Channel Scan buttons, you can scan through the available streams from the VTXs

Multiple VTX units viewed from a single VRX

Video Streaming over IP Networks

Overview

Another use case the VTX/VRX system supports is streaming over IP networks.

The pilot can view the low latency video via goggles connected to Display Port output of the VRX.

Different modem types can be used, where we capture below USB-to-Ethernet, Doodle Labs, and LTE use cases.

If using LTE, both drone and VRX can be configured with VPN clients and can stream over through a network a VPN server facilitates. Tailscale VPN client ships in VOXL2 starting SDK 1.6.

Additionally, the voxl-joystick-server can be used to send RC over MAVLink to a drone for command and control, plugging a controller into a USB hub connected to the AUX USB port.

Block Diagrams

The block diagram below describes this architecture:

  • the VRX is connected to the internet via USB-to-Ethernet
  • the UAS/VTX is connected to the internet with LTE
  • both UAS/VTX are connected to the same IP network using a VPN
  • the VTX is configured to send UDP traffic to the VRX IP address(es) / port.
  • a user can view the video stream from the DisplayPort Out with an HDMI adapter to goggles/display

VRX UDP video streaming block diagram

VRX Software Configuration

To enable receiving video over UDP, edit /etc/modalai/voxl-vrx.conf. The --factory_enable_doodle, --factory_enable_dtc, --factory_enable_silvus and --factory_enable_fiber presets of voxl-configure-vrx set these fields for those radios.

NameTypeDefaultDescription
udpboolfalsetrue to receive over UDP
enable_pcapbooltrueRF receive. The UDP presets set it to false
udp_interface_ipstring""IP address of the local interface (the VRX)
udp_interface_rx_portinteger50000Port the VRX listens on. Must match the port in the VTX’s udp_receiver_configs
udp_interface_tx_portinteger-1Local port the VRX sends from (-1 = OS assigns)
udp_receiver_configsarray[]Where the VRX sends its return traffic (link quality, menu input, GCS MAVLink): the VTX’s IP and udp_interface_rx_port
└─ ipstring IP address of the VTX
└─ portinteger Port the VTX listens on (VTX default 50001)

For example, the VRX settings after the Doodle Labs preset:

    "udp": true,
    "enable_pcap": false,
    "udp_interface_ip": "10.223.0.101",
    "udp_interface_rx_port": 50000,
    "udp_receiver_configs": [
        {
            "ip": "10.223.0.100",
            "port": 50001
        }
    ],

VTX Software Configuration

To enable this use case on the UAS, edit /etc/modalai/voxl-vtx.conf, or use the matching voxl-configure-vtx preset (--factory_enable_doodle, --factory_enable_dtc, --factory_enable_silvus, --factory_enable_fiber). Receivers can also be managed with voxl-configure-vtx --add_udp_receiver <ip:port>, --remove_udp_receiver <ip:port> and --clear_udp_receivers.

NameTypeDefaultDescription
udpboolfalsetrue to transmit over UDP
enable_pcapbooltrueRF transmit. The UDP presets set it to false; leave it on to use RF and UDP together, for example with RF / IP fallback
udp_interface_ipstring""IP address of the local interface on the VTX/UAS
udp_interface_rx_portinteger50001Port the VTX listens on for VRX return traffic
udp_interface_tx_portinteger-1Local port the VTX sends from (-1 = OS assigns)
udp_receiver_configsarray[]List of VRX endpoints to send video to
└─ ipstring IP address of the VRX
└─ portinteger Port the VRX listens on (its udp_interface_rx_port, default 50000)

For example, the VTX settings after the Doodle Labs preset:

    "udp": true,
    "enable_pcap": false,
    "udp_interface_ip": "10.223.0.100",
    "udp_interface_rx_port": 50001,
    "udp_receiver_configs": [
        {
            "ip": "10.223.0.101",
            "port": 50000
        }
    ],

VRX SDK 1.6.1 and older used udp_ip and udp_port on the VRX and udp_transmitter_ip on the VTX. Those keys are not read by SDK 1.8.0.

Interface Options



Ethernet Adapter

The VRX’s AUX USB port can be used to add an Ethernet adapter (like the TUC-ETGH3).

When the VRX is connected to an IP network, we can send video over IP instead of RF.

VRX with USB-to-Ethernet adapter

When an Ethernet adapter is attached to AUX USB, it will by default get a static IP (see Static IP from VRX with USB-to-Ethernet below).

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.2  netmask 255.255.255.0  broadcast 10.0.0.255
        ether 00:30:1a:3b:86:9e  txqueuelen 1000  (Ethernet)
        RX packets 253  bytes 64410 (64.4 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 467  bytes 27898 (27.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Doodle Labs


The following shows how to configure a Doodle Labs modem setup to be used with the VRX system.

First follow VRX Software Configuration and VTX Software Configuration sections above.

MVC-RH01-M18 Doodle Labs wiring diagram

On the VRX, to setup the Doodle Lab modem connected over USB, you will need to:

  • ADB on to the VRX (see ADB Access to VRX below).
  • run voxl-configure-modem doodle-vrx

This will setup a new interface with default IP 10.223.0.101.

In this case it’s eth1, as we have a USB-to-Ethernet dongle on eth0.

eth1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 10.223.0.101  netmask 255.0.0.0  broadcast 10.255.255.255
        ether 78:2d:7e:14:f9:4d  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

You can interface with the Doodle Labs modem using the doodl-cli tool that ships in the SDK.

On VRX, for example to get the IP address of the Doodle,

voxl2:/$ doodle-cli -i
10.223.0.101
xxxx::138f:beb0:e79b:xxxx

For VTX/UAS side, for reference, the following could be done with a Doodle Labs enabled VOXL UAS:

  • ADB onto VTX/UAS
  • run:
voxl2:/$ voxl-configure-modem doodle

The VTX/UAS side should get an interface like:

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.223.0.100  netmask 255.0.0.0  broadcast 10.255.255.255
        ether 00:30:1a:3b:86:a6  txqueuelen 1000  (Ethernet)
        RX packets 1242  bytes 209966 (209.9 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2054  bytes 108812 (108.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

LTE


First follow VRX Software Configuration and VTX Software Configuration sections above.

Then follow the information on VOXL SDK LTE software setup

For hardware:

  • On VTX side - you could use LTE hotspot with Ethernet out and plug into the Ethernet port of the USB-hub option above.
  • On the VTX - instead of the VTX modem, we can use an IP based modem like the M0130 LTE modem/antennas/SIM card, e.g. similar to this.

Static IP from VRX with USB-to-Ethernet

Using a USB-to-Ethernet adapter (and sometimes a USB-C to USB-A adapter like in the setup below), you can easily get an IP connection with the VRX.

VRX Ethernet adapter connection close-up

Starting in SDK 1.6, the voxl-static-ip-watcher service will run by default on the VRX.

When you plug in a USB to Ethernet dongle to the AUX port, it enumerates as eth0, and will be assigned static IP 10.0.0.2 with default netmask 255.255.255.0

If you want to customize this, edit /etc/systemd/system/voxl-static-ip-watcher.service.

Environment=NETWORK_INTERFACE=eth0
Environment=STATIC_IP=10.0.0.2
Environment=DEBUG=0
Environment=NETMASK=255.255.255.0

RTSP Stream From VRX

The voxl-streamer services runs on the VRX by default and exposes an RTSP endpoint at rtsp://10.0.0.2:8900/live.

If the VTX is off, you should get a “black screen” for the feed.

SSH Access to VRX

After getting an IP connection following the previous setup, you can get an SSH connection.
NOTE: The static IP functionality is supported in SDK 1.6.X and newer

ssh root@10.0.0.2
(password: oelinux123)

ADB Access to VRX

To access the VRX via ADB, disconnect the USB-C to HDMI adapter from the VRX and connect your USB-C cable to the same USB-C port.

adb shell

See the Interfaces section of the VRX Ground Unit Quick Start Guide for more details.

voxl-joystick-server Setup

NOTE: voxl-joystick-server requires SDK 1.5.0+, recommend 1.6+

USB Mode

  • Connect USB C from USB HUB in VRX to RadioMaster Zorro and hold the power button to power on

Joystick server USB mode setup, step 1

  • Use the scroll wheel to set transmitter to “USB Joystick (HID)” mode. Press the scroll wheel to select mode

Joystick server USB mode setup, step 2

  • Confirm that edgeTX version is v.2.10+
  • Press “SYS” button, this will bring you to the “TOOLS” Page
  • Press “PAGE<” button to Navigate left to the “VERSION” Page
  • Confirm edgeTX version is >= v2.10 (ex: VERS: v2.10.6)
    • If you need to upgrade, instructions can be found here
    • How to get TX into DFU found here

Joystick server USB mode setup, step 3

Joystick Configuration

Mixes setup

  • Navigate to the Model Selection Menu
  • Navigate to the “MIXES” page
  • Assign CH1-4 to be axes: pitch, roll, thrust, and yaw

Radio mixes page, axes

  • Assign buttons/switches to CH9 or higher, these will be referenced in the Joystick Axes and Switches/Buttons Setup section below
  • Select each channel to be used and set the source as the physical button/switch you want to be linked to that channel

Radio mixes page, buttons

Joystick Axes and Switches/Buttons Setup

  • Navigate to the Model Selection Menu
  • Navigate to the “SETUP” page
  • Scroll all the way to the bottom until you see the “USB Joystick” section

Joystick axes and switches setup, step 1

  • In the “USB Joystick” section:
    • Set “Mode” to “Advanced”
    • Set “If.mode” to “Joystick”
    • Set “Circ. cut” to “None” (Pilot should verify this is what is desired)

Joystick axes and switches setup, step 2

  • Navigate down to “[Channel Settings]” and select enter to enter the menu
    • Setup X,Y,Z and rotations on channels (1-8) or whichever order you want them to be in if applicable
    • The channel(s) used for switches/buttons need to be on channel 9 or above
    • Navigate to a channel you want to assign a button/switch on your RC to, then click edit
    • Set “Mode” to “Btn”
    • Set “Positions” to either “2POS”, “3POS”, or whatever type is relevant depending on the physical switch it will be attached to
    • Set “Button no.” to be the button numbers that you want this switch to populate
      • For example, for a 2POS switch a user can set the button “0..1”, “1..2”, etc depending on which button numbers are already in use (A warning “!Button no. collision!” will appear if the range you are trying to use is already in use)

Joystick axes and switches setup, step 3 Joystick axes and switches setup, step 4

  • Repeat the steps above for all buttons you want to setup

Application Configuration

  • ADB or SSH onto the VRX
  • Run voxl-configure-joystick-server -w and then select “3” for “Settings”

Joystick server application configuration, step 1

  • Now assign the X, Y, Z, and R channels to roll, pitch, yaw, and throttle
  • Descriptions from mavlink manual_control header file:
    • X: X-axis, normalized to the range [-1000,1000]. Generally corresponds to forward(1000)-backward(-1000) movement on a joystick and the pitch of a vehicle.
    • Y: Y-axis, normalized to the range [-1000,1000]. Generally corresponds to left(-1000)-right(1000) movement on a joystick and the roll of a vehicle
    • Z: Z-axis, normalized to the range [-1000,1000]. Generally corresponds to a separate slider movement with maximum being 1000 and minimum being -1000 on a joystick and the thrust of a vehicle. Positive values are positive thrust, negative values are negative thrust.
    • R: R-axis, normalized to the range [-1000,1000]. Generally corresponds to a twisting of the joystick, with counter-clockwise being 1000 and clockwise being -1000, and the yaw of a vehicle.
    • Update Rate: Optionally increase the update rate

Joystick server application configuration, step 2

  • Now decide how you want to throttle to behave: Zero throttle at center stick or full range.
  • Set center_zero_throttle to true if you want the center stick position to be zero throttle. Otherwise, set center_zero_throttle false
  • Now provide the file path to your Joystick, the default config here should work, typically on VRX this will be /dev/input/event2. If the defauly path doesn’t work, you may need to watch this directory as you plug in your Joystick to determine which event is linked to your Joystick.
  • Now setup the network connection
    • Receiver: receiver_ip should be the IP address of the drone and receiver_port should remain as the default (14550) as this is the port that voxl-mavlink-server listens to on the drone.
    • Transmitter: transmitter_ip should be the IP address of this device (the VRX). transmitter_name should be the name of the network interface to be used for transmitting the data (likely wlan0, tailscale0, or wwan0)

Troubleshooting

Joystick to VRX interface

To see if the VRX is seeing the Joytick inputs:

  • adb on to VRX
  • stop the joystick service:
systemctl stop voxl-joystick-server
  • manually run with -d option for debug joystick events
voxl-joystick-server -d

Here is an example output:

voxl2:~$ voxl-joystick-server -d
Found 1 UDP Configurations
Joystick detected: OpenTX Radiomaster TX12 Joystick (/dev/input/event2)
WARNING: No kill switch button provided: -1. Valid options: 0-31.
PITCH: Y
ROLL:  X
YAW:   R
THROTTLE: Z
ARM BUTTON: 0
KILL BUTTON: -1
CENTER ZERO THROTTLE: FALSE
UPDATE RATE: 200Hz
INPUT DEVICE: /dev/input/event2
TX-IP:   10.223.0.101
[1] RX-IP:   10.223.0.100
[1] RX-PORT: 14550

[debug] Debug mode enabled
existing instance of voxl-joystick-server found, attempting to stop it
Device: OpenTX Radiomaster TX12 Joystick
UDPMultiForwarder: add forwarding to: 10.223.0.100:14550
UDPForwarder::configured for 10.223.0.100:14550 via 10.223.0.101
[debug] ev { time=1718656274.505133, type=3, code=0, value=1023 }
[debug] ev { time=1718656274.505133, type=3, code=1, value=825 }
[debug] ev { time=1718656274.505133, type=0, code=0, value=0 }
[debug] ev { time=1718656274.510144, type=3, code=0, value=1042 }
[debug] ev { time=1718656274.510144, type=3, code=1, value=791 }
[debug] ev { time=1718656274.510144, type=0, code=0, value=0 }

Joystick Network Connection to VTX/UAS

To see if the connection is being made from the VRX to the VTX/UAS, do the following:

  • adb shell onto VTX/UAS
  • manually run the following:
voxl-mavlink-server

When the VRX connects, you should see something like this (where these IPs may be different for your setup)

Added new UDP connection to 10.223.0.101
CONNECTED to GCS at 10.223.0.101

Check For mamual control events From VRX

To see the manual control events originating from the VTX, do the following:

voxl-inspect-mavlink mavlink_from_gcs

Here is an example output:

|   ID  |      Mavlink MSG Name       |Counter|  Hz  |
|-------|-----------------------------|-------|------|
|     0 | heartbeat                   |     7 |  1.0 |
|    69 | manual_control              |  1414 |196.1 |

Check For manual_control_setpoint Events from PX4

 px4-listener manual_control_setpoint

TOPIC: manual_control_setpoint
 manual_control_setpoint
    timestamp: 380219234 (0.003195 seconds ago)
    timestamp_sample: 380218414 (820 us before timestamp)
    roll: 0.99700
    pitch: -0.00100
    yaw: -0.00500
    throttle: -0.99800
    flaps: 0.00000
    aux1: 0.00000
    aux2: 0.00000
    aux3: 1010.00000
    aux4: 1000.00000
    aux5: 0.00000
    aux6: 0.00000
    valid: True
    data_source: 3
    sticks_moving: False

No events?

Make sure voxl-px4 is setup for EXTERNAL RC:

  • Check /etc/modalai/voxl-px4.conf
  • If wanting to use USB Joystick mode, set RC=EXTERNAL

Check that the PX4 param COM_RC_IN_MODE is set to 1:

voxl2:/$ px4-param show COM_RC_IN_MODE
Symbols: x = used, + = saved, * = unsaved
x + COM_RC_IN_MODE [249,531] : 1

If not, you can use:

px4 param set COM_RC_IN_MODE 1

AI Detection

For information on setting up AI object detection with real-time bounding box overlay on the video stream, see the AI Detection Setup Guide.