|
| 1 | +# fc_doc_generator |
| 2 | + |
| 3 | +Auto-generates flight controller documentation sections for PX4-Autopilot |
| 4 | +from board source files (`boards/<vendor>/<board>/`). |
| 5 | + |
| 6 | +## What it does |
| 7 | + |
| 8 | +Parses PX4 board C/Kconfig source files and generates Markdown sections |
| 9 | +inserted into `docs/en/flight_controller/*.md` docs. Sections generated: |
| 10 | + |
| 11 | +- `## Specifications` — processor, sensors, interfaces |
| 12 | +- `## PWM Outputs` — timer groups, DShot/BDShot capability per output |
| 13 | +- `## Serial` — UART → /dev/ttyS* mapping with labels and flow control |
| 14 | +- `## Radio Control` — RC input protocols and ports |
| 15 | +- `## GPS & Compass` — GPS/safety connector info |
| 16 | +- `## Power` — power input ports and monitor type |
| 17 | +- `## Telemetry Radios` — TELEM port listing |
| 18 | +- `## SD Card` — presence/absence |
| 19 | + |
| 20 | +## File layout |
| 21 | + |
| 22 | +``` |
| 23 | +fc_doc_generator/ |
| 24 | +├── fc_doc_generator.py # Main script (~3700 lines) |
| 25 | +├── pytest.ini # testpaths = tests |
| 26 | +├── metadata/ # Per-board cached JSON (data + wizard overrides) |
| 27 | +│ ├── <vendor>_<board>_data.json # Parsed board data |
| 28 | +│ └── <vendor>_<board>_wizard.json # User-supplied wizard overrides |
| 29 | +└── tests/ |
| 30 | + ├── conftest.py # snapshot fixture + board_* path fixtures |
| 31 | + ├── fixtures/ # Minimal fake board trees (5 boards) |
| 32 | + │ ├── stm32h7_all_dshot/ |
| 33 | + │ ├── stm32h7_mixed_io/ |
| 34 | + │ ├── stm32h7_ppm_shared/ |
| 35 | + │ ├── stm32f4_no_dshot/ |
| 36 | + │ └── imxrt_all_dshot/ |
| 37 | + ├── snapshots/ # Expected markdown output (.md files) |
| 38 | + ├── test_parsers.py # Unit tests for parse_* functions |
| 39 | + ├── test_compute.py # Unit tests for compute_groups / compute_bdshot |
| 40 | + ├── test_generators.py # Snapshot tests for generate_*_section functions |
| 41 | + ├── test_helpers.py # Unit tests for helper functions |
| 42 | + └── test_wizard.py # Tests for wizard cache and generate_full_template |
| 43 | +``` |
| 44 | + |
| 45 | +## Running the script |
| 46 | + |
| 47 | +Run from the repo root (requires the PX4 `boards/` tree to be present): |
| 48 | + |
| 49 | +```sh |
| 50 | +# Generate metadata JSON + fc_sections.md (no file edits): |
| 51 | +python docs/scripts/fc_doc_generator/fc_doc_generator.py |
| 52 | + |
| 53 | +# Apply sections to existing FC docs: |
| 54 | +python docs/scripts/fc_doc_generator/fc_doc_generator.py --apply |
| 55 | + |
| 56 | +# Apply a single section only: |
| 57 | +python docs/scripts/fc_doc_generator/fc_doc_generator.py --apply --section pwm_outputs |
| 58 | + |
| 59 | +# Create a new stub FC doc (interactive wizard): |
| 60 | +python docs/scripts/fc_doc_generator/fc_doc_generator.py --new-doc |
| 61 | + |
| 62 | +# Check a single doc against quality specs: |
| 63 | +python docs/scripts/fc_doc_generator/fc_doc_generator.py --check-doc docs/en/flight_controller/holybro_kakuteh7.md |
| 64 | + |
| 65 | +# Check all FC docs: |
| 66 | +python docs/scripts/fc_doc_generator/fc_doc_generator.py --check-all |
| 67 | +``` |
| 68 | + |
| 69 | +Via yarn (from the `docs/` directory): `cd docs && yarn gen_fc_sections` |
| 70 | + |
| 71 | +## Running tests |
| 72 | + |
| 73 | +From `docs/scripts/fc_doc_generator/`: |
| 74 | + |
| 75 | +```sh |
| 76 | +pytest # run all tests |
| 77 | +pytest --update-snapshots # regenerate snapshot files after intentional changes |
| 78 | +pytest tests/test_generators.py # specific test file |
| 79 | +``` |
| 80 | + |
| 81 | +## Snapshot tests |
| 82 | + |
| 83 | +Tests in `test_generators.py` use the `snapshot` fixture from `conftest.py`. |
| 84 | +- Snapshot files live in `tests/snapshots/*.md` |
| 85 | +- To add a new snapshot test: call `snapshot("my_name.md", result)` — then run `pytest --update-snapshots` to create the file |
| 86 | +- After intentional generator changes: run `pytest --update-snapshots` then review diffs with `git diff tests/snapshots/` |
| 87 | + |
| 88 | +## Extension pattern (adding a new section) |
| 89 | + |
| 90 | +1. Write `parse_<thing>(board_path: Path) -> dict` and call it in `gather_board_data()`, merging into the entry |
| 91 | +2. Write `generate_<thing>_section(board_key, entry) -> str` |
| 92 | +3. Register both in `SECTION_GENERATORS` and `SECTION_ORDER` |
| 93 | +4. Add snapshot tests in `test_generators.py` |
| 94 | +5. Re-run `cd docs && yarn gen_fc_sections` to regenerate metadata JSON + `fc_sections.md` |
| 95 | + |
| 96 | +## Key architecture notes |
| 97 | + |
| 98 | +- **Parsers** read from `boards/<vendor>/<board>/` source files: |
| 99 | + - `nuttx-config/nsh/defconfig` — chip family, enabled UARTs, SD card |
| 100 | + - `src/board_config.h` — PWM count, IO board presence, GPIOs |
| 101 | + - `src/timer_config.cpp` — timer groups and channels |
| 102 | + - `default.px4board` — Kconfig board settings (serial labels, RC, GPS, drivers) |
| 103 | + - `nuttx-config/include/board.h` — flow control GPIO definitions |
| 104 | + - `init/rc.board_sensors` — sensor driver start commands |
| 105 | + |
| 106 | +- **Metadata JSON** in `metadata/` caches parsed data (`*_data.json`) and |
| 107 | + wizard-supplied overrides (`*_wizard.json`). Wizard data persists across runs |
| 108 | + and provides connector types, sensor names, dimensions, etc. |
| 109 | + |
| 110 | +- **`BOARD_TO_DOC`** — static mapping from `vendor/board` key to doc filename. |
| 111 | + Boards mapped to `None` have no existing doc page yet. |
| 112 | + |
| 113 | +- **Section insertion** — `_apply_section()` finds existing headings and |
| 114 | + replaces them, or inserts before anchor headings like `## Where to Buy`. |
| 115 | + The `specifications` section is special: it preserves hand-written content |
| 116 | + and appends generated content as a `<!-- specifications-proposed -->` comment. |
| 117 | + |
| 118 | +- **Wizard** — `--new-doc` runs an interactive prompts session and caches |
| 119 | + answers to `metadata/<stem>_wizard.json` for future re-use. |
| 120 | + |
| 121 | +## Conventions |
| 122 | + |
| 123 | +- British English in doc output |
| 124 | +- Asset files lowercase with underscores; asset folder named after doc stem |
| 125 | +- Section generators emit embedded `<!-- *-source-data ... -->` JSON comments |
| 126 | + so the raw parsed values are visible in the doc for manual verification |
| 127 | +- `TODO:` placeholders are left wherever data cannot be auto-detected |
| 128 | + |
| 129 | +## Development rules |
| 130 | + |
| 131 | +**When modifying `fc_doc_generator.py`:** |
| 132 | +1. All existing tests must pass: run `pytest` from `docs/scripts/fc_doc_generator/` |
| 133 | +2. New functionality must have new tests (unit tests and/or snapshot tests as appropriate) |
| 134 | +3. Update this `CLAUDE.md` if the change affects how to run the script, the architecture, extension patterns, or conventions |
0 commit comments