Built with Conan 2 and CMake. Targets C++17, with optional C++20/23 features such as modules.
- Language: C/C++
- Build: Conan 2 + CMake
- Docs: Doxygen, Graphviz, Sphinx
- Modules: optional, enabled from C++23 up
- Metadata-Driven:
metadata.jsonholds the build, dependency, docs and CI settings - Skills & Agent: library-level
het-*skills + routing agent (.github/skills/) - Layout:
- headers and sources are named in pairs
- the suffix tells the languages apart: (.h, .c) for C, (.hpp, .cpp) for C++
- docs use .dox for doc-only pages and .cxx for example code
food_volume_measure measures food volume in cubic centimetres from a fixed oven-tray depth camera.
The IM (baseline-plane height-difference integral) pipeline is:
- Build an empty-oven baseline height map: fit the tray plane from the first empty frame,
project every empty frame into the same local
(u, v)frame, and take the per-cell median height. - Remove the dominant background plane(s) from the food frame, then filter food points by their baseline-relative height difference.
- Cluster the surviving points in baseline-plane (u, v) coordinates to separate multiple food items.
- Keep one top-surface point per cell and integrate
volume = Σ (food_top − baseline_height) × cell_size². - Conservatively complete enclosed depth holes inside a single component with inverse-distance interpolation (small, smooth holes) or a guarded quadratic surface fit (larger specular holes). Measured and interpolated cells are reported separately.
FoodVolumeMeasurer measurer; // defaults match the IM reference
measurer.set_baseline({empty_oven_frame}) // one or more empty-oven frames
.set_food(food_frame) // the food frame
.set_input_unit(LengthUnit::kMillimeter); // optional: inputs in mm
VolumeEstimate est = measurer.run();
// est.volume_cm3, est.raw_volume_cm3, est.interpolated_volume_cm3, est.component_count, ...- All geometry is in metres internally; set the input unit when inputs are millimetres.
- At least one baseline frame is required; a baseline cell that is missing from the empty-oven map is never replaced with an ideal zero plane.
- Hole filling is intentionally conservative: only holes whose boundary belongs to exactly one food component are considered, and several area / rim / fit-safety guards must pass.
FoodVolumeMeasurer has chainable setters for the common parameters, set_config for a full
MeasurementConfig, and JSON load/save for its configurable fields. JSON files may contain only
the values to override; the hole-completion safety guards remain internal constants:
FoodVolumeMeasurer measurer;
measurer.set_voxel_size(0.003) // downsampling voxel edge (m)
.set_integration_resolution(0.003) // raster cell edge (m)
.set_height_range(0.0015, 0.05) // accepted food height (m); max <= 0 disables the cap
.set_cluster_params(0.010, 8) // footprint DBSCAN radius + min points
.set_plane_distance_threshold(0.003) // background-plane RANSAC threshold (m)
.set_roi(roi) // optional axis-aligned crop before downsampling
.load_config_from_json("measurement_config.json"); // or set everything from JSONImplementation-only details (plane-local frames, grid keys, ROI bounds, height maps, hole
candidates, baseline rasters) stay private to src/ and are never part of the installed
headers.
include/pointcloudprocess.hpp additionally exposes the fine-grained point-cloud
operators the pipeline is built from — unit scaling, axis-aligned cropping, RANSAC plane
fitting and orientation, voxel downsampling, DBSCAN labelling, background-plane removal, and
the AABB / OBB / convex-hull reference volumes — so they can be reused and tested on their own.
An ROI object enables cropping; an empty selected_labels selects all eligible food components.
The secondary-plane removal uses plane_distance_threshold_m. Setting middle_cloud_dir
enables stage PCD output; an empty path disables it. 5_top_surface.pcd contains the measured
top-surface cells before hole completion, and 6_hole_filled_surface.pcd contains the full top
surface after completion. Both use world coordinates.
- Dependency management with Conan
- Supports C++ standards 17, 20, and 23
- Automatic module file generation (
.ixx/.cppm) from headers/sources - Builds on Windows, Linux and macOS
- Dual C and C++ interfaces with separate linkage targets
- Doxygen annotation support for object exporting (
@exporter,@attacher) - Automated docs via Doxygen and Sphinx
- Import, derivation and call graphs via Graphviz
metadata.jsonas the one place holding build / deps / docs / CI settings- Library-level VS Code skills + routing agent (
.github/skills/,/het-*slash commands) - Metadata + gitmoji driven CI/CD orchestration (GitHub Actions)
- Cross-compilation & on-board benchmark framework (
benchmark/) - Agentic Coding workspace (
/workspace/, git-ignored)
This repository reserves /workspace/ (declared in .gitignore) for agent-generated work products produced
during Agentic Coding sessions — e.g., implementation plans, test contracts, audit reports, and other
intermediate artifacts. Keep such working files under /workspace/ so they never pollute the tracked
source tree.
This repository ships a library-level skills system under .github/skills/ — 15 het-* skills plus one
routing agent, all invocable from Copilot Chat by typing /:
| Family | Skills | Audience |
|---|---|---|
| IaC usage (S0–S6) | het-guide, het-build, het-release, het-docs, het-quality, het-board, het-fix-ci |
CI/CD novices |
| Dev automation (N1–N8) | het-deps, het-module, het-setup, het-testgen, het-commit, het-audit, het-preflight, het-patent |
Developers |
| Routing agent (A1) | het-agent |
Everyone |
Examples: /het-guide for onboarding, /het-testgen to generate tests, /het-agent for natural-language
composite tasks (e.g. "add a module, test it, and commit"). See .github/skills/README.md and
PLAN-skills.md for the full execution plan.
- Python 3.10+ (Conan tooling)
- Conan 2.0+
- A C/C++ compiler:
- GCC
- Clang
- MSVC
- CMake (auto-installed by Conan)
- Doxygen
- Graphviz
- sphinx
- sphinx-intl
- sphinx-rtd-theme
- GTest
All GitHub Actions workflows are orchestrated from metadata.json (entry: ci-orchestrator.yml, decision:
metadata-controller.yml). Each pipeline is gated by a workflow_triggers.* switch and triggered by a
gitmoji in the commit message. The canonical commit form is <type>(<emoji>): <description> — the emoji
sits in the parentheses right after the commit word (e.g. feat(:fire:): ..., chore(:package:): ...);
as a soft rule the emoji also triggers from anywhere in the message:
| Pipeline | gitmoji in commit message | Gate (metadata.json) |
|---|---|---|
| Build | :building_construction: |
workflow_triggers.build |
| Tests + coverage | :beer: |
trigger_tests / activate_code_coverage (needs build_type=Debug) |
| Release | (:package:): |
workflow_triggers.release (needs build_type=Release) |
| Docs | :book: |
workflow_triggers.docs |
| Security / lint | :shield: |
workflow_triggers.security_scan (also runs on every PR) |
| Board cross-build | :fire: (or 🔥) |
hetai self-hosted runner |
Note:
workflow_triggers.build/.tests/.security_scanare enabled by default (commit-lint & schema gates always run on push/PR; build/tests/security shift-left on PRs).releaseanddocsrequire both the gitmoji and the switch (build_typemust match too).
From the repository root:
conan create . -s build_type=Debug --build=missing -c tools.build:jobs=4The full CTest suite runs only when trigger_tests is enabled in metadata.json.
cross-build to host device (assume toolchain and profile are ready):
conan create . -pr:b=default -pr:h=arm_profile -s build_type=Debug --build=missing \
-c tools.build:jobs=4 -tf=""python ./docs/build.pyUnix-like platforms (Linux, MacOS):
bash ./buildWindows:
Get-Content "build" | Invoke-ExpressionAdd your required libraries in conandata.yml where dependency graph is automatically computed from, then modify the dependencies field in metadata.json to config proper package names and associated targets to link (no need modification on CMakeLists.txt).
Requirements for your project can be the package archived on Conan Center, or user built ones. If the later one, at least you need a locale Conan server for managing your libraries.
MegaLinter mirrors the CI megalinter job (.github/workflows/security-linters.yml): same config
(.github/misc/.mega-linter.yml), same full image, and the same version (v8.8.0, pinned to match the
CI action). It runs the advisory SAST layer — gitleaks / semgrep / checkov / devskim, plus clang-format
& cppcheck. The required gates (clang-format / clang-tidy / gitleaks with pinned tool versions) are the
native quality-gates job of the same workflow.
Prerequisites: Docker (or Podman) + Node.js ≥ 20.
bash .github/misc/run-megalinter.sh # lint the whole codebase
bash .github/misc/run-megalinter.sh --fix # auto-apply fixes (e.g. clang-format)
bash .github/misc/run-megalinter.sh src/foo.c # lint selected files only
CONTAINER_ENGINE=podman bash .github/misc/run-megalinter.sh # Podman users- The first run pulls the
v8.8.0image (a few GB — cached on later runs). - Reports are written to
megalinter-reports/(git-ignored); per-linter details are inmegalinter-reports/linters_logs/ERROR-*.log. - The runner (
mega-linter-runner) is a devDependency —npm ciinstalls it, or it is fetched automatically on first use.
project-root/
├── conanfile.py # Conan recipe
├── CMakeLists.txt # CMake build framework
├── metadata.json # Package identity and all build/deps/docs switches
├── conandata.yml # Dependency specifications, Conan plugin support
├── package.json # Node-side tooling deps (commitlint / semantic-release / ajv)
├── CHANGELOG.md # Auto-generated by semantic-release (init tag required)
├── build # One-liner local build script
├── LICENSE # Apache v2 Project license
├── NOTICE # Notice file of Apache v2
├── .vscode/ # Recommended editor config (extensions / settings / tasks)
├── .devcontainer/ # Reproducible dev environment (Dockerfile)
├── .github/ # CI/CD + library-level skills
│ ├── workflows/ # ci-orchestrator / metadata-controller / build / test / docs / release / security
│ ├── skills/ # 16 het-* skills + het-agent + _shared + manifest.json
│ ├── misc/ # clang-format(-c/cpp) / clang-tidy / gitleaks / releaserc / commitlint /
│ │ # metadata.schema / mega-linter / pre-commit / labels / Codegen-Starter.txt
│ ├── CODEOWNERS # Required reviewers
│ ├── CONTRIBUTING.md # Contribution & commit conventions
│ ├── dependabot.yml # Grouped monthly dependency updates
│ └── PULL_REQUEST_TEMPLATE.md
├── api/ # Interface to advanced programming language
│ └── python_bindings.cpp # Python bindings interface
├── include/ # Public headers
│ ├── *.h # C interface headers
│ └── *.hpp # C++ interface headers
├── src/ # Implementation files
│ ├── *.c # C sources
│ ├── *.cpp # C++ sources
│ └── *.ixx/*.cppm # Auto-generated Module files (in experimental)
├── benchmark/ # Cross-compile & on-board benchmark framework (Cortex-M / Cortex-A)
├── .hetai/ # hetai package matrix (cross-compile targets)
├── wokspace/ # Agentic Coding work products (git-ignored)
├── docs/ # Documentations root
│ ├── doxygen/ # Doxygen system main root
│ │ ├── dox/ # Pure documentations' folder
│ │ │ ├── demos/ # Examples catalogue
│ │ │ │ ├── *.dox # Documenting docstring
│ │ │ │ └── *.cxx # Example codes
│ │ │ └── *.dox # Main pages and etc
│ │ └── ...
│ ├── sphinx/ # Sphinx system main root
│ │ ├── source/ # Source files of sphinx system
│ │ ├── locales/ # Pot files for internalization
│ │ └── ...
│ └── images/ # Static images for doxygen/sphinx system
└── test_package/ # Test project
├── export/ # Log for testing results
├── resources/ # Test resources for test_package/ programs
├── stress/
│ └── *.cpp # Scripts for stress testing
├── unit/
│ └── *.cpp # Scripts for unit testing
├── main.cpp # Validation program for package
├── conanfile.py # Conan recipe for test_package
└── CMakeLists.txt # CMake build workflow for test_package
When generate_modules_inplace is enabled in metadata.json:
- Header/source pairs automatically generate module files
#includedirectives are converted toimportstatements- Doxygen annotations control symbol visibility:
@exporter: Exports symbols in modules@attacher: Attaches symbols to modules
This feature is experimental now, however, the specific syntax can make the existing project a ease migration to fit the future C++ standard.
| Feature | MSVC | Clang | GCC | Apple-Clang |
|---|---|---|---|---|
| C++ Modules | ✓ | ✓ | ✓ | ✓ |
| C Compatibility | ✓ | ✓ | ✓ | ✓ |
| Automatic Export | ✓ | ✓ | ✓ | ✓ |
- Desktop: Windows, Linux, MacOS
- Mobile: arm-linux, risc-v
benchmark/ cross-compiles the library to real hardware and measures performance on-board:
- Cortex-M (baremetal): flash via JLink / OpenOCD / PyOCD, timing via SYSTICK
- Cortex-A (Linux): deploy via ADB / SSH, timing via
clock_gettime
Edit benchmark/bench_config.json (board parameters) and benchmark/bench_entry.c (algorithm cases),
then run python benchmark/script/run_bench.py (add --no-flash to build only). Results follow the
BENCHMARK_START / RESULT|name|cycles / BENCHMARK_END protocol. See benchmark/README.md.
Role split:
test_package/runs host-side GTest verification (desktop/x86_64, even when the library is cross-compiled to baremetal), whilebenchmark/runs target-side on-board verification.
Commit style uses the Conventional Commits specification, extended with the template's private emoji superset (see the CI/CD table above) so a single message both bumps the version and triggers the right pipeline.
Canonical commit form — the emoji is placed in the parentheses right after the commit word:
<type>(<emoji>): <description>
Examples: feat(:fire:): cross-compile support, test(:beer:): vector add cases,
chore(:package:): prepare release. As a soft rule, the emoji anywhere in the message also triggers the
pipeline, but the parenthesized placement is the recommended convention.
Versioning is driven by semantic-release (semver-release.yml + .github/misc/.releaserc.json): the commit prefix
decides the jump — feat → minor, fix/perf → patch, BREAKING CHANGE/! → major. A release
generates CHANGELOG.md and rewrites the version in metadata.json. (The legacy
commit-base-versioning mechanism has been removed.)
Possible frame design/validation on Apple Clang compiler (raised from dlib requirement).
[Apache-2.0] - See included LICENSE file for details.