|
K-FSW ec10f94
Modular flight software on Zephyr, for small satellites
|
k-ground runs Linux ground nodes built from the same application and services as KFSW-Linux. A node file sets each role's name, address, peer and build options.
| Role | CSP address | Use |
|---|---|---|
kfsw-gnd-uhf | 16 | Opens the UHF radio for the ground network |
kfsw-gnd-uhf-bench | 16 | The same, routed to flight node 2 on the radio bench |
kfsw-gnd-can | 16 | Reaches a flight node over a SocketCAN interface |
kfsw-ops | 19 | Operator shell; doesn't open the radio |
These are the reference settings. CSP v2 addresses are 14 bits, so the launcher accepts ground nodes from 16 to 16383 and peers from 1 to 16383.
The node file sets the role, name, prompt, address, peer, radio and build directory. Use status for node identity and uhf status for radio settings:
A normal Linux image keeps the kfsw:~$ prompt and Role: flight.
| Layer | Contents | Loaded by |
|---|---|---|
Workspace .venv | Python, west and Zephyr tools | Your shell; K-FSW scripts activate it themselves |
ground-station/nodes/*.env | Role, CSP address, peer and routes | tools/k-ground |
| Holybro bench file | Serial paths and radio settings of one host | Sourced before a hardware test |
From the workspace root:
socat is needed for the local CSP/KISS links (sudo apt install socat). See Getting started for the workspace setup.
The launcher uses k-fsw/ground-station and writes to build/k-ground by default. To use other directories in the current shell:
Keep USB device paths out of the node files and put them in the bench file.
A node file is a shell environment file:
KFSW_CSP_ROUTES sets a route table, for example ‘'2/14 KISS’. tools/k-groundchecks it and writes it toCONFIG_KFSW_CSP_ROUTE_TABLE; without it the node uses0/0 -> KISS direct.KFSW_EXTRA_KCONFIGand KFSW_EXTRA_OVERLAYadd Kconfig lines and a devicetree overlay, which is how kfsw-gnd-canenables CAN.KFSW_RADIO_UHF=holybro` selects the radio module.
To copy the reference configuration into your workspace:
The launcher uses ./ground-station when it exists, or KGROUND_STATION_DIR. init doesn't overwrite an existing directory.
Start the UHF gateway and the operator shell in two terminals:
run connects the KISS PTYs of the two peers through a local socket:
k-ground demo starts both and opens the operator shell. k-ground test checks both identities, prompts and ping directions:
Ground nodes include the file transfer service. From the operator shell:
The same CRC on both nodes and on the returned copy means the file came back unchanged. The gateway can list its own files without a connection:
tests/k-ground-ftp-smoke.sh runs this sequence, including a missing file.
Yamcs stores housekeeping samples and has a telemetry browser and archive. Its configuration is the ground-station/yamcs submodule.
Nodes answer housekeeping requests, so the bridge polls them:
The bridge talks CSP over KISS, pulls samples and sends each one to Yamcs on UDP port 10015. Point it at a Linux node's uart_1 PTY, or at the Holybro serial device to reach a flight node over the radio.
A report can also send its latest sample periodically:
Beacons use the same frame format as polled samples. Receive them without polling:
CONFIG_KFSW_HK_BEACON_FLOOR_MS (5000 ms) return -ERANGE.CONFIG_KFSW_HK_BEACON_BUFFER_RESERVE CSP buffers are free; check hk show and hk_beacons_skipped in table 33.Beacons are sent to their own port (KFSW_HK_BEACON_PORT) so they never reach a request handler. With persistence enabled, beacon settings are saved with the report.
Yamcs needs Java 17; Maven comes through ./mvnw.
It prints Yamcs started and serves http://localhost:8090. The instance is kfsw. Keep it running while recording.
Check the mission database before connecting hardware. In another terminal, from k-fsw/ground-station/yamcs:
It sends a recorded housekeeping frame to Yamcs and reads the values back; CI runs it on every push. Expect MDB CHECK RESULT: PASS.
Then set up a report on the node:
hk show prints the collections, failures, missing values and stored samples. Set the clock first, otherwise samples have a zero timestamp and the bridge uses the host time.
Start the bridge on the node's link:
The bridge prints each sample. With --yamcs none it prints the frames as hex and sends nothing.
| Yamcs page | What to check |
|---|---|
| Links | hk-udp shows OK, receiving on 10015; valid datagrams go up, invalid stays at zero |
| Telemetry, Packets | One packet per sample in the nucleo_temperature container |
| Telemetry, Parameters | /kfsw/nucleo_temperature_temp_mcu in degrees, marked ACQUIRED |
| Archive | The stored history |
INVALID instead of ACQUIRED means the value is outside its valid range, for example the reserved value sent when the sensor can't be read. Check temp_valid and temp_failures.
The same data is available from the Yamcs API:
If nothing arrives, look at the frames with --yamcs none, check that hk show counts collections, and then check Links for invalid datagrams.
Yamcs only records telemetry. Housekeeping is configured with K-FSW commands; hk_define, hk_period and hk_clear work over CSP/KISS or CAN:
Housekeeping frames carry the values in report order, without names. hk-report.py generates the node command and the Yamcs XTCE database from one YAML file:
hk-report.py check compares the file with a node's param list, which catches a parameter that moved.
Each UDP datagram has a 12-byte header followed by the frame from the node:
The bridge sends one datagram per sample, preserving its timestamp.
tests/hk-yamcs-smoke.sh checks that the bytes the bridge receives match what the node's shell prints for the same sample.
Only one process opens each physical interface. A serial bridge connects the kfsw-gnd-uhf KISS PTY to the Holybro device; other ground roles reach the gateway over CSP. See the Holybro fixture below for the bridge command.
kfsw-comms has the UART, KISS and CSP code. kfsw-modules has the radio-uhf module and its holybro-sik implementation, which reports the expected radio settings and adds encryption. Table 50 has the radio identity, status and encryption settings. TX power, network ID and air rate are not writable because the module doesn't use SiK command mode.
raw-nucleo-smoke.sh flashes a raw test peer on the NUCLEO and exchanges numbered messages over the radio.csp-kiss-smoke.sh builds ground node 16 and NUCLEO node 2 at 57600 baud, bridges the ground PTY to the USB radio, and checks the interfaces, routes, ping in both directions and the counters.Radio settings and commands are in tests/hil/radio-uhf/holybro/README.md.
From k-fsw, capture accepted HK samples to a new JSONL file:
Each version-1 record contains the source node, host receipt time in milliseconds, and original HK bytes. Replay opens no serial device and sends the saved samples in file order without delays. The Yamcs envelope uses the original sample time, or the saved receipt time when the node's clock was unset. An invalid or truncated record stops replay; earlier records may already have been sent.
Distinct reports with the same sequence number are kept. Exact duplicate samples from the same node are suppressed for up to 60 seconds, within a 1024-entry window. A changed timestamp or value makes a sample distinct. There is no boot identifier on the wire, so a byte-identical sample after a reset cannot be distinguished until it leaves that window. Captures contain samples accepted after this filtering, not every raw frame on the link.
Polling counts only matching replies towards --count; unrelated beacons can still be captured. An incomplete --once poll exits unsuccessfully and retains any accepted samples. Continuous polling reports the timeout and retries after --interval. Passive listening stays active between receive windows.
The bridge checks framing, CRCs, HK version, flags and size bounds. It cannot verify each value's width without the report definition; keep the matching report YAML with a capture. JSONL files grow with accepted samples, so stop or rotate captures between runs. Live serial access needs PySerial; offline replay uses only Python's standard library.