mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-04-14 10:07:39 +08:00
manifest: add label_pretty and firmware_category fields
Add human-readable labels and firmware classification to the build manifest so ground stations like QGC can display friendly names and filter builds by category. New fields: - label_pretty: human-readable variant name (e.g. "Multicopter") - firmware_category: auto-detected classification - "vehicle" for multicopter, fixedwing, vtol, rover, uuv, spacecraft - "peripheral" for CAN sensor nodes (GPS, flow, mag, etc.) - "bootloader" for bootloader/canbootloader - "dev" for everything else (default, zenoh, mavlink-dev, etc.) Peripheral detection uses ROMFSROOT="cannode" which is shared by all ~18 CAN sensor boards across ARK, Holybro, CUAV, Freefly, Matek, NXP. A build-time warning fires when an unrecognized label falls through to "dev", so new vehicle types are not silently hidden from end users. Boards can override via CONFIG_BOARD_FIRMWARE_CATEGORY in .px4board. CONFIG_BOARD_LABEL_PRETTY set on all px4/fmu-v6x variants as Phase 1. Signed-off-by: Ramon Roche <mrpollo@gmail.com>
This commit is contained in:
parent
68c391328a
commit
63f059fd47
24
Kconfig
24
Kconfig
@ -54,6 +54,30 @@ menu "Toolchain"
|
||||
string "Architecture"
|
||||
default ""
|
||||
|
||||
config BOARD_LABEL_PRETTY
|
||||
string "Human-readable label for this build variant"
|
||||
default ""
|
||||
help
|
||||
A short display name for this build variant (e.g. "Multicopter",
|
||||
"Rover"). Used by ground stations like QGC to show a user-friendly
|
||||
name instead of raw target strings. Must be set in every .px4board
|
||||
variant file because non-base variants inherit from default.
|
||||
|
||||
config BOARD_FIRMWARE_CATEGORY
|
||||
string "Firmware category override (vehicle, peripheral, dev, bootloader)"
|
||||
default ""
|
||||
help
|
||||
Override the auto-detected firmware category. Normally inferred
|
||||
from the build label and board config: vehicle types (multicopter,
|
||||
fixedwing, etc.) map to "vehicle", bootloader/canbootloader map to
|
||||
"bootloader", CAN peripheral boards (ROMFSROOT=cannode) map to
|
||||
"peripheral", and everything else maps to "dev". Set this only
|
||||
when the auto-detection is wrong for a particular board variant.
|
||||
IMPORTANT: If you add a new vehicle type with a label not yet in
|
||||
_VEHICLE_LABELS (in gen_board_manifest_from_defconfig.py), either
|
||||
add it there or set this to "vehicle" — otherwise the build will
|
||||
be hidden from end-users in QGC.
|
||||
|
||||
config BOARD_LTO
|
||||
bool "(EXPERIMENTAL) Link Time Optimization (LTO)"
|
||||
default n
|
||||
|
||||
@ -2,6 +2,13 @@
|
||||
import argparse, json, os, re, sys
|
||||
from typing import Dict
|
||||
|
||||
_VEHICLE_LABELS = frozenset({
|
||||
"multicopter", "fixedwing", "vtol", "rover", "uuv", "spacecraft",
|
||||
})
|
||||
_BOOTLOADER_LABELS = frozenset({
|
||||
"bootloader", "canbootloader",
|
||||
})
|
||||
|
||||
def parse_defconfig(path: str) -> Dict[str, str]:
|
||||
d: Dict[str, str] = {}
|
||||
if not path or not os.path.exists(path):
|
||||
@ -36,6 +43,38 @@ def detect_chip(defcfg: Dict[str,str]) -> str:
|
||||
s = defcfg.get("CONFIG_ARCH_CHIP", "")
|
||||
return s.lower().replace("_", "") if s else ""
|
||||
|
||||
def detect_firmware_category(target: str, defcfg: Dict[str, str]) -> str:
|
||||
"""Infer firmware_category from the build label and defconfig.
|
||||
|
||||
Detection order:
|
||||
1. bootloader / canbootloader labels → "bootloader"
|
||||
2. Known vehicle labels → "vehicle"
|
||||
3. ROMFSROOT == "cannode" (CAN peripheral boards) → "peripheral"
|
||||
4. Everything else → "dev"
|
||||
|
||||
If you are adding a NEW vehicle type (e.g. "balloon"), you must EITHER:
|
||||
1. Add the label to _VEHICLE_LABELS in this file, OR
|
||||
2. Set CONFIG_BOARD_FIRMWARE_CATEGORY="vehicle" in the .px4board file
|
||||
Otherwise the build will be classified as "dev" and hidden from
|
||||
end-users in ground stations like QGroundControl.
|
||||
"""
|
||||
label = target.rsplit("_", 1)[-1].lower() if target else ""
|
||||
if label in _BOOTLOADER_LABELS:
|
||||
return "bootloader"
|
||||
if label in _VEHICLE_LABELS:
|
||||
return "vehicle"
|
||||
# CAN peripheral boards (sensors, GPS, flow, etc.) use cannode ROMFS
|
||||
romfsroot = defcfg.get("CONFIG_BOARD_ROMFSROOT", "")
|
||||
if romfsroot == "cannode":
|
||||
return "peripheral"
|
||||
if label not in ("default", ""):
|
||||
print(f"WARNING: label '{label}' (target '{target}') is not a known "
|
||||
f"vehicle type — defaulting firmware_category to 'dev'. "
|
||||
f"If this is a vehicle type, add it to _VEHICLE_LABELS in "
|
||||
f"{__file__} or set CONFIG_BOARD_FIRMWARE_CATEGORY in the "
|
||||
f".px4board file.", file=sys.stderr)
|
||||
return "dev"
|
||||
|
||||
def pick(preferred: str, fallback_key: str, defcfg: Dict[str, str]) -> str:
|
||||
return preferred if preferred else defcfg.get(fallback_key, "")
|
||||
|
||||
@ -51,6 +90,8 @@ def main():
|
||||
ap.add_argument("--chip", default="")
|
||||
ap.add_argument("--vid", default="")
|
||||
ap.add_argument("--pid", default="")
|
||||
ap.add_argument("--label-pretty", default="")
|
||||
ap.add_argument("--firmware-category", default="")
|
||||
ap.add_argument("--out", help="Write to file instead of stdout")
|
||||
args = ap.parse_args()
|
||||
|
||||
@ -64,10 +105,16 @@ def main():
|
||||
chip = args.chip or detect_chip(defcfg)
|
||||
vid = norm_hex(pick(args.vid, "CONFIG_CDCACM_VENDORID", defcfg))
|
||||
pid = norm_hex(pick(args.pid, "CONFIG_CDCACM_PRODUCTID", defcfg))
|
||||
label_pretty = pick(args.label_pretty, "CONFIG_BOARD_LABEL_PRETTY", defcfg)
|
||||
firmware_cat = pick(args.firmware_category,"CONFIG_BOARD_FIRMWARE_CATEGORY",defcfg)
|
||||
if not firmware_cat:
|
||||
firmware_cat = detect_firmware_category(target, defcfg)
|
||||
|
||||
manifest = {
|
||||
"name": name,
|
||||
"target": target,
|
||||
"label_pretty": label_pretty,
|
||||
"firmware_category": firmware_cat,
|
||||
"manufacturer": manufacturer,
|
||||
"hardware": {
|
||||
"architecture": arch,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
|
||||
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
|
||||
CONFIG_BOARD_LABEL_PRETTY="Bootloader"
|
||||
CONFIG_BOARD_ROMFSROOT=""
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
|
||||
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
|
||||
CONFIG_BOARD_LABEL_PRETTY="Default"
|
||||
CONFIG_BOARD_ETHERNET=y
|
||||
CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS0"
|
||||
CONFIG_BOARD_SERIAL_GPS2="/dev/ttyS7"
|
||||
|
||||
@ -1 +1,2 @@
|
||||
CONFIG_BOARD_LABEL_PRETTY="Flash Analysis"
|
||||
CONFIG_BOARD_LINKER_PREFIX="flash-analysis"
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
CONFIG_BOARD_LABEL_PRETTY="MAVLink Dev"
|
||||
CONFIG_MAVLINK_DIALECT="development"
|
||||
CONFIG_MODULES_UXRCE_DDS_CLIENT=n
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
CONFIG_BOARD_LABEL_PRETTY="Multicopter"
|
||||
CONFIG_COMMON_DIFFERENTIAL_PRESSURE=n
|
||||
CONFIG_MODE_NAVIGATOR_VTOL_TAKEOFF=n
|
||||
CONFIG_MODULES_AIRSPEED_SELECTOR=n
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
|
||||
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
|
||||
CONFIG_BOARD_LABEL_PRETTY="Performance Test"
|
||||
CONFIG_BOARD_ETHERNET=y
|
||||
CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS0"
|
||||
CONFIG_BOARD_SERIAL_GPS2="/dev/ttyS7"
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
CONFIG_BOARD_LABEL_PRETTY="Rover"
|
||||
CONFIG_MODULES_AIRSPEED_SELECTOR=n
|
||||
CONFIG_MODULES_FLIGHT_MODE_MANAGER=n
|
||||
CONFIG_MODULES_FW_ATT_CONTROL=n
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
CONFIG_BOARD_LABEL_PRETTY="Spacecraft"
|
||||
CONFIG_BOARD_PWM_FREQ=100000
|
||||
CONFIG_MODULES_AIRSPEED_SELECTOR=n
|
||||
CONFIG_MODULES_FLIGHT_MODE_MANAGER=n
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
CONFIG_BOARD_LABEL_PRETTY="UUV"
|
||||
CONFIG_MODULES_AIRSPEED_SELECTOR=n
|
||||
CONFIG_MODULES_FLIGHT_MODE_MANAGER=n
|
||||
CONFIG_MODULES_FW_ATT_CONTROL=n
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
CONFIG_BOARD_LABEL_PRETTY="Zenoh"
|
||||
# CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE is not set
|
||||
CONFIG_DRIVERS_UAVCAN=n
|
||||
CONFIG_MODULES_UXRCE_DDS_CLIENT=n
|
||||
|
||||
@ -481,6 +481,7 @@
|
||||
- [PX4 Board Configuration (kconfig)](hardware/porting_guide_config.md)
|
||||
- [NuttX Board Porting Guide](hardware/porting_guide_nuttx.md)
|
||||
- [Board Firmware Packaging (.deb)](hardware/board_packaging.md)
|
||||
- [Firmware Manifest & Metadata](hardware/firmware_manifest.md)
|
||||
- [Serial Port Mapping](hardware/serial_port_mapping.md)
|
||||
- [Airframes](dev_airframes/index.md)
|
||||
- [Adding a New Airframe](dev_airframes/adding_a_new_frame.md)
|
||||
|
||||
@ -478,6 +478,7 @@
|
||||
- [Flight Controller Porting Guide](/hardware/porting_guide.md)
|
||||
- [PX4 Board Configuration (kconfig)](/hardware/porting_guide_config.md)
|
||||
- [NuttX Board Porting Guide](/hardware/porting_guide_nuttx.md)
|
||||
- [Firmware Manifest & Metadata](/hardware/firmware_manifest.md)
|
||||
- [Serial Port Mapping](/hardware/serial_port_mapping.md)
|
||||
- [Airframes](/dev_airframes/index.md)
|
||||
- [Adding a New Airframe](/dev_airframes/adding_a_new_frame.md)
|
||||
|
||||
@ -78,6 +78,15 @@ If _QGroundControl_ installs the FMUv2 target (see console during installation),
|
||||
|
||||
You can update it by following the instructions in [Bootloader update > FMUv2 Bootloader Update](../advanced_config/bootloader_update.md#fmuv2-bootloader-update).
|
||||
|
||||
## Firmware Variants
|
||||
|
||||
PX4 boards may provide multiple firmware variants for different vehicle types (multicopter, fixed-wing, rover, etc.).
|
||||
QGroundControl shows vehicle firmware by default.
|
||||
CAN peripheral firmware (for sensor nodes like GPS, optical flow, magnetometer, etc.) is shown in a separate section.
|
||||
Developer builds (such as `default` or `zenoh`) are available in advanced mode.
|
||||
|
||||
For technical details on how firmware variants are classified and discovered, see [Firmware Manifest & Metadata](../hardware/firmware_manifest.md).
|
||||
|
||||
## Further Information
|
||||
|
||||
- [QGroundControl User Guide > Firmware](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/setup_view/firmware.html).
|
||||
|
||||
@ -113,6 +113,9 @@ Contact PX4 board maintainers at [boards@px4.io](mailto:boards@px4.io) and reque
|
||||
2. The assignment of REV and VER ID resistor values.
|
||||
3. If the board supports USB: Either request the assignment of a USB VID and PID or provide the USB VID and PID.
|
||||
|
||||
4. Set `CONFIG_BOARD_LABEL_PRETTY` in all `.px4board` variant files so that ground stations can display a human-readable name for each build variant.
|
||||
See [Firmware Manifest & Metadata](firmware_manifest.md) for details on firmware categories and how QGC discovers firmware.
|
||||
|
||||
Integrate the board according to the board porting release process described in the [porting guide](../hardware/porting_guide.md)
|
||||
|
||||
:::warning
|
||||
|
||||
110
docs/en/hardware/firmware_manifest.md
Normal file
110
docs/en/hardware/firmware_manifest.md
Normal file
@ -0,0 +1,110 @@
|
||||
# Firmware Manifest & Metadata
|
||||
|
||||
Each PX4 NuttX build produces a **manifest** — a JSON metadata object that describes the firmware target, board hardware, and build variant.
|
||||
This manifest is embedded in the `.px4` firmware file and aggregated into a unified release manifest consumed by ground stations like QGroundControl for firmware discovery and selection.
|
||||
|
||||
## Manifest Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "px4_fmu-v6x",
|
||||
"target": "px4_fmu-v6x_multicopter",
|
||||
"label_pretty": "Multicopter",
|
||||
"firmware_category": "vehicle",
|
||||
"manufacturer": "Holybro",
|
||||
"hardware": {
|
||||
"architecture": "cortex-m7",
|
||||
"vendor_id": "0x1234",
|
||||
"product_id": "0x5678",
|
||||
"chip": "stm32h753ii",
|
||||
"productstr": "Pixhawk 6X"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Field Descriptions
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `name` | string | Board name without variant label (e.g. `px4_fmu-v6x`) |
|
||||
| `target` | string | Full build target including variant (e.g. `px4_fmu-v6x_multicopter`) |
|
||||
| `label_pretty` | string | Human-readable variant name shown in ground stations (e.g. "Multicopter") |
|
||||
| `firmware_category` | string | Build classification: `vehicle`, `peripheral`, `dev`, or `bootloader` |
|
||||
| `manufacturer` | string | Board manufacturer name |
|
||||
| `hardware` | object | Hardware details (architecture, USB IDs, chip, product string) |
|
||||
|
||||
## Firmware Categories
|
||||
|
||||
The `firmware_category` field classifies each build for ground station filtering:
|
||||
|
||||
| Value | Description | Examples | Ground Station Behavior |
|
||||
|-------|-------------|----------|------------------------|
|
||||
| `vehicle` | Production firmware for a vehicle type | multicopter, fixedwing, vtol, rover, uuv, spacecraft | Shown to users (primary) |
|
||||
| `peripheral` | Firmware for CAN sensor nodes and peripherals | ark/can-gps, holybro/can-gps-v1, ark/can-flow, ark/mag | Shown in a dedicated peripheral/sensor section |
|
||||
| `dev` | Developer/engineering builds | default, zenoh, mavlink-dev, flash-analysis, performance-test | Hidden by default, advanced mode only |
|
||||
| `bootloader` | Bootloader binaries | bootloader, canbootloader | Never shown to end users |
|
||||
|
||||
### Auto-Detection
|
||||
|
||||
The firmware category is automatically inferred from the build label (the last segment of the target string after the final `_`):
|
||||
|
||||
- Labels `multicopter`, `fixedwing`, `vtol`, `rover`, `uuv`, `spacecraft` → `vehicle`
|
||||
- Labels `bootloader`, `canbootloader` → `bootloader`
|
||||
- Boards with `CONFIG_BOARD_ROMFSROOT="cannode"` (CAN sensor peripherals) → `peripheral`
|
||||
- Everything else (`default`, `zenoh`, `mavlink-dev`, etc.) → `dev`
|
||||
|
||||
The known vehicle labels are maintained in `_VEHICLE_LABELS` in `Tools/manifest/gen_board_manifest_from_defconfig.py`.
|
||||
Peripheral detection uses the `cannode` ROMFS root, which is shared by all CAN sensor boards (ARK, Holybro, CUAV, Freefly, Matek, NXP, etc.).
|
||||
A build-time warning is emitted to stderr when an unrecognized label (other than `default`) falls through to `dev`, so that new vehicle types are not silently hidden from end users.
|
||||
|
||||
### Adding a New Vehicle Type
|
||||
|
||||
If you are adding a new vehicle type (e.g. `balloon`), you must do **one** of the following — otherwise the build is silently classified as `dev` and hidden from end users in QGroundControl:
|
||||
|
||||
1. **Add the label to `_VEHICLE_LABELS`** in `Tools/manifest/gen_board_manifest_from_defconfig.py` — this is the preferred approach when the vehicle type applies across multiple boards.
|
||||
2. **Set `CONFIG_BOARD_FIRMWARE_CATEGORY="vehicle"`** in the `.px4board` file — use this for one-off overrides or when a board variant doesn't follow the standard naming.
|
||||
|
||||
### Overriding Auto-Detection
|
||||
|
||||
If a board variant needs a non-standard classification for any reason, set `CONFIG_BOARD_FIRMWARE_CATEGORY` in the `.px4board` file:
|
||||
|
||||
```
|
||||
CONFIG_BOARD_FIRMWARE_CATEGORY="vehicle"
|
||||
```
|
||||
|
||||
This override takes precedence over auto-detection.
|
||||
|
||||
## Pretty Labels (`label_pretty`)
|
||||
|
||||
The `label_pretty` field provides a human-readable name for each build variant.
|
||||
Ground stations display this instead of raw target strings like `px4_fmu-v6x_default`.
|
||||
|
||||
### Setting `label_pretty`
|
||||
|
||||
Set `CONFIG_BOARD_LABEL_PRETTY` in each `.px4board` file:
|
||||
|
||||
```
|
||||
CONFIG_BOARD_LABEL_PRETTY="Multicopter"
|
||||
```
|
||||
|
||||
### Kconfig Inheritance Caveat
|
||||
|
||||
Non-base variants (e.g. `multicopter.px4board`, `rover.px4board`) are merged on top of `default.px4board`.
|
||||
If `default.px4board` sets `CONFIG_BOARD_LABEL_PRETTY="Default"` and a variant file does not override it, the variant inherits the "Default" label — which is incorrect.
|
||||
|
||||
**Every variant file must set its own `CONFIG_BOARD_LABEL_PRETTY`.**
|
||||
|
||||
See [PX4 Board Configuration > Kconfig Label Inheritance](porting_guide_config.md#px4-kconfig-label-inheritance) for more details on how variant configs inherit from defaults.
|
||||
|
||||
## Build Pipeline
|
||||
|
||||
The manifest flows through three stages:
|
||||
|
||||
1. **`gen_board_manifest_from_defconfig.py`** — Generates per-build `manifest.json` from CMake variables and defconfig values, including auto-detection of `firmware_category`
|
||||
2. **`px_mkfw.py`** — Bundles the manifest into the `.px4` firmware file
|
||||
3. **`update_firmware_manifest.py`** — Aggregates individual `.px4` manifests into a unified release manifest for ground station consumption
|
||||
|
||||
## Backward Compatibility
|
||||
|
||||
- Old `.px4` files without `label_pretty` / `firmware_category`: ground stations fall back to raw label and filename matching (existing behavior)
|
||||
- These are additive fields — no `format_version` bump is needed
|
||||
@ -45,6 +45,30 @@ When changing the `cyphal.px4board` it only stores the delta of the Kconfig keys
|
||||
When modifying a Kconfig key in `default.px4board` it will be modified in all derivative configurations of the same board that had the same config as well.
|
||||
:::
|
||||
|
||||
## Board Metadata Fields
|
||||
|
||||
PX4 board files can include metadata used by ground stations for firmware discovery and display.
|
||||
|
||||
### `CONFIG_BOARD_LABEL_PRETTY`
|
||||
|
||||
A human-readable name for the build variant (e.g. `"Multicopter"`, `"Rover"`).
|
||||
Ground stations like QGroundControl display this instead of raw target strings.
|
||||
|
||||
```
|
||||
CONFIG_BOARD_LABEL_PRETTY="Multicopter"
|
||||
```
|
||||
|
||||
::: warning
|
||||
Due to [Kconfig label inheritance](#px4-kconfig-label-inheritance), every variant file must set its own `CONFIG_BOARD_LABEL_PRETTY`.
|
||||
If omitted, a variant inherits the value from `default.px4board`, which is typically wrong.
|
||||
:::
|
||||
|
||||
### `CONFIG_BOARD_FIRMWARE_CATEGORY`
|
||||
|
||||
Optional override for the auto-detected firmware category (`vehicle`, `peripheral`, `dev`, or `bootloader`).
|
||||
Normally this is inferred from the build label and does not need to be set.
|
||||
See [Firmware Manifest & Metadata](firmware_manifest.md) for details on the auto-detection rules and when to use this override.
|
||||
|
||||
## PX4 Menuconfig Setup
|
||||
|
||||
The [menuconfig](https://pypi.org/project/kconfiglib/#menuconfig-interfaces) tool is used to modify the PX4 board configuration, adding/removing modules, drivers, and other features.
|
||||
|
||||
@ -439,6 +439,8 @@ if (TARGET parameters_xml AND TARGET airframes_xml)
|
||||
--chip "${CONFIG_ARCH_CHIP}"
|
||||
--vid "${CONFIG_CDCACM_VENDORID}"
|
||||
--pid "${CONFIG_CDCACM_PRODUCTID}"
|
||||
--label-pretty "${CONFIG_BOARD_LABEL_PRETTY}"
|
||||
--firmware-category "${CONFIG_BOARD_FIRMWARE_CATEGORY}"
|
||||
--out ${MANIFEST_JSON}
|
||||
DEPENDS
|
||||
${PX4_SOURCE_DIR}/Tools/manifest/gen_board_manifest_from_defconfig.py
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user