Skip to content

Easy gui - #571

Open
MartinMokros wants to merge 23 commits into
MapsHD:mainfrom
MartinMokros:easy-gui
Open

MartinMokros wants to merge 23 commits into
MapsHD:mainfrom
MartinMokros:easy-gui

Conversation

@MartinMokros

Copy link
Copy Markdown

No description provided.

MartinMokros and others added 22 commits October 17, 2026 19:26
New raylib app apps/easy_gui for non-experts: pick a raw Mandeye folder,
run lidar odometry with the precision forestry preset, get a session.
Export (LAZ 1.4 + trajectory CSV) follows in M2.

- Pre-flight check with plain-language findings: file pairing exactly as
  load_data does it (by position, unmatched trailing files reported),
  readable LAZ headers, single lidar id, calibration consistency (the
  cases where step 1 would abort() or exit()), IMU/lidar clock overlap,
  output folder location and a disk estimate (120 B per raw point of work
  space + 2.5x raw LAZ size of results).
- Step 1 runs as a child process (lidar_odometry_step_1 <in> <toml> <out>)
  for crash isolation and a real cancel (process group / job object kill).
  stdin is closed so load_data's cin.get() cannot hang; success is judged
  by session.mjs, since step 1 returns 0 after caught exceptions.
- Step 1 runs on a staging folder of links to the recording, because
  load_data writes cache/ and preview/ next to its input: nothing is ever
  written into the recording (which may be the scanner's USB stick).
- Parameters: preset 2 ("precise forestry") written with step 1's TomlIO,
  with threshould_output_filter lowered to filter_threshold_xy_inner. That
  filter is output-only: on a 117 M-point forest walk the trajectory is
  byte-identical to a manual preset 2 run, with 6.1 % more points kept.
- Progress parsed from step 1's log (phases, per-chunk odometry progress,
  ETA) with a known-failure -> plain message table.
- easy_gui --headless <recording> <output> runs the same pipeline without
  a window.
- easy_gui_tests (doctest): pre-flight on synthetic recordings, staging,
  preset file, child process, progress parser on a real log excerpt; plus
  integration tests against the real step 1 binary (cancel mid-odometry,
  broken recording) when EASY_GUI_TEST_RECORDING is set.

No existing app, step 1 source or core_math file is changed; the root
CMakeLists only adds the app and its tests. The Windows child-process code
is written but not yet compiled on Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ctory CSV

After lidar odometry, Easy GUI now writes point_cloud.laz, trajectory.csv
and a README.txt describing every field into the output folder.

- point_cloud.laz: LAS 1.4, point format 6, gps_time in Unix epoch seconds
  (global encoding bit 0 = 0), point_source_id = scan index, user_data =
  lidar id, named extra bytes range_m (float32) and near_added (uint8). The
  extra-bytes VLR is written by hand: laszip_add_attribute always sets the
  scale bit, which makes readers return near_added as float64.
- Odometry points are placed exactly as step 2's export does it (Session in
  load_cache_mode for poses and trajectories, points streamed per scan): on a
  117 M-point forest walk all 89,326,756 points are integer-identical to
  multi_view_tls_registration_step_2 --export; the trajectory matches step 2's
  trajectories.csv to 0.05 mm.
- Near points: raw points step 1's distance filters removed (the exact
  complement of its load and output filters), at least 0.4 m away, no-return
  points dropped, placed with step 1's own rule (last node before the raw
  time, within 10 ms). A --check-band test mode re-adds the 1.0-1.2 m band
  step 1 also exported: NN distance to step 1's points median 0.10 mm, p99
  12.9 mm where step 1 has the point; rebuilding step 1's timestamp ramp
  reproduces its points to 0.17 mm and attributes the remaining difference
  to the ramp time choosing a neighbouring pose.
- Streams one scan or one raw file at a time: peak memory 102 MB, ~1.5 min on
  the full recording. Measured sizes set the pre-flight result estimate to
  2.25x the raw LAZ size (session 0.82x + point cloud 1.24x + CSV 0.03x).
- New Export stage with progress and cancel in the window and in --headless;
  an export failure keeps the odometry session. --export-only runs the export
  on an existing session.
- core_no_gui is now always built (Easy GUI links it for Session).
- Tests: LAS 1.4 writer round trip, the export on a synthetic step 1 session
  with known poses (near rule edge cases, check band, cancel), and an
  end-to-end run against the real step 1. scripts/check_export.py runs the
  acceptance checks (fields, range, alignment, step 2 reference) with laspy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…E.md

place_by_raw_time places every point from the raw files with the trajectory
pose at its real gps_time instead of taking step 1's points (placed at step
1's even-spread ramp time), and writes the raw gps_time. Step 1's distance
filters and the near-point rule are unchanged; the raw points step 1 drops
between its 0.1 s pieces are included. Available as Settings /
ExportRequest::place_by_raw_time, --place-by-raw-time and an experimental
checkbox; the default stays off until its effect on sharpness is measured.

On the 117 M-point test walk: 93,359,291 instead of 89,326,756 points inside
step 1's limits (+4,026,808 from the inter-chunk gaps). For the common points,
79 % get the same pose; moved points shift by a median 8 / 13 / 23 / 47 mm at
1-3 / 3-5 / 5-10 / 10-20 m (a neighbouring pose's rotation, ~9 mrad).

CLAUDE.md documents the repository and the Easy GUI decisions and
measurements (M1, M2, this option).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es near_added

The default export is now a hybrid: step 1's own points as step 1 placed them,
plus two kinds of raw points step 1 left out, both placed with the pose at
their real gps_time:
- near points (unchanged rule), and
- gap points: raw points inside step 1's distance limits that step 1 skips
  between its 0.1 s pieces (from a piece's last pose to the next piece's
  first). On the 117 M-point test walk that is 4,026,788 points (4.1 %).

The extra-bytes flag near_added becomes point_origin (uint8): 0 = step 1,
1 = near point, 2 = gap point, 3 = check-band test point. The README now
explains where each kind of point comes from.

Validation (check_export.py, full recording): gap points sit as close to
step 1's points as a missing 5 ms slice of step 1's own points does (NN
median 19.4 vs 19.8 mm, p99 187 vs 192 mm, the same in every range bin);
step 1's points are still integer-identical to step 2's export. Peak memory
106 MB; point_cloud.laz 948 MB (1.29x the raw LAZ, within the 2.25x
pre-flight estimate).

place_by_raw_time stays an experimental option (default off): on the same
89.3 M matched points it measured slightly less sharp than step 1's own
placement (ground +0.1 mm median, thinner in only 37 % of cells; stem RMSE
+0.09 mm, sharper for 3 of 17 trunks; no diameter bias). The sharpness study
is recorded in CLAUDE.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cking CLAUDE.md

DESIGN.md collects the design decisions, Mandeye raw-data facts, what step 1
does to points, the export, validation and sharpness results, written for
collaborators and reviewers. CLAUDE.md becomes local working notes
(untracked). Source comments now point to DESIGN.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With -DHDMAPPING_EASY_GUI_ONLY=ON only easy_gui, lidar_odometry_step_1 and
the libraries they link are built (plus easy_gui_tests with BUILD_TESTING),
and only those two programs are installed. The library directories and the
step 1 directory are added EXCLUDE_FROM_ALL; all other apps, test suites and
the optional tool sets are skipped. With the default (off) the build is
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… for Easy-GUI-only builds

Window title, heading, messages, the generated README.txt, the LAS system
identifier and the default output folder (Documents/HDMapping Easy Forestry)
use the new name. Internal names (apps/easy_gui, easy_gui) are unchanged.

HDMAPPING_EASY_GUI_ONLY on macOS now defaults CMAKE_OSX_DEPLOYMENT_TARGET to
13.0, so release builds do not require the build machine's macOS version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
apps/easy_gui/README.md: user guide for non-experts (requirements,
installation incl. first-launch warnings, the four steps with a screenshot,
output fields, CloudCompare, troubleshooting, getting help, citation).
DESIGN.md: naming, macOS deployment target, effect of the near-point
displacement (§7.3), macOS packaging and ad-hoc re-signing notes (§10).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Window title and heading, messages, the generated README.txt, the LAS
system identifier, the default output folder (Documents/Easy Forest
HDMapping), the user README, the root README banner, DESIGN.md and the
placeholder release names (EasyForestHDMapping-windows.zip,
EasyForestHDMapping-mac.dmg, "Easy Forest HDMapping.app"). Screenshot
retaken. Internal names (apps/easy_gui, easy_gui) are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New workflows easy-forest-macos.yml / easy-forest-windows.yml (tags easy-forest-v*,
manual dispatch), separate from the upstream ones, building with
HDMAPPING_EASY_GUI_ONLY=ON. Packaging scripts in apps/easy_gui/packaging:

- macOS: static PROJ built for 13.0, oneTBB without hwloc, .app bundle with
  easy_gui + lidar_odometry_step_1 + dylibs (rpaths rewritten), ad hoc
  re-sign, minos <= 13.0 check on every bundled binary, DMG with an
  Applications shortcut.
- Windows: easy_gui is a WIN32-subsystem app (CLI modes attach to the parent
  console), UTF-8 process code page manifest, folder + zip with all DLLs and
  the MSVC runtime, checked with dumpbin.

HDMAPPING_EASY_GUI_ONLY builds no longer configure OpenCV. easy_gui_tests
now also cover ChildProcess on Windows and argument quoting on all platforms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… CMake

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ion)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Window title, README.txt and easy_gui.log show "Easy Forest HDMapping 0.1.0
(HDMapping 0.105.0)". The LAZ header's 32-character fields get one name each:
generating software "Easy Forest HDMapping 0.1.0", system identifier
"HDMapping 0.105.0" (Las14Writer::open takes the system identifier now).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both download placeholders point to the releases page (not /releases/latest,
which skips pre-releases). Windows: built and unit-tested, not yet tested on a
real PC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t match EASY_FOREST_VERSION

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…earlier attempt

Groundwork for batch mode: runPreflight(..., resume_unfinished) accepts an output
folder holding nothing but Easy GUI's own run files, and the pipeline clears it
(keeping and continuing easy_gui.log) when PipelineRequest::resume_unfinished is
set. Single mode is unchanged. OutputLayout gains the batch done marker path;
availableSpace() and formatBytes() are exported for the batch disk check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ck, runner)

New batch module in easy_gui_core, used by the GUI and --batch in the next commits:
- discoverRecordings: recordings among a parent folder's direct subfolders, plus
  the parent itself; other folders are listed with the reason.
- output names: validation (valid on Windows and macOS), case-insensitive
  collisions, defaults that avoid folders holding someone else's files.
- done marker (easy_gui_done.txt) identifying the recording by its files, so a
  restarted batch skips finished recordings even if the stick is mounted elsewhere.
- batch disk check: largest temporary need + all results.
- BatchRunner: sequential runs through the unchanged Pipeline; a failure marks the
  recording failed and continues; stop after current / stop now; batch.log and
  batch_summary.csv (rewritten after every recording); weighted progress and ETA.
- SleepBlocker: IOPMAssertion on macOS, SetThreadExecutionState on Windows.

Tests use a fake RecordingJob.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Headless batch mode with the GUI's rules: every recording that passes the check is
processed, finished ones are skipped, the batch disk check refuses to start when
space is short. Ctrl+C stops after the current recording, a second Ctrl+C stops now.
Exit code 0 when every selected recording succeeded or was already done.

planBatch() (discover, name, check) is shared by --batch and the tests. The
integration test runs two copies of the test recording plus a recording that
passes the check but fails in lidar odometry, then restarts the batch.

Also moves the stage progress bar and the advanced settings of the window into
their own functions, for the batch view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A toggle between one recording and several. In batch mode the user picks a parent
folder; the table lists each recording with an include checkbox, its length, the
pre-flight result (checked row by row in the background) and an editable output
folder name (validated, case-insensitive collisions flagged). Folders that are not
recordings are listed as skipped with the reason. Below the table: each problem in
words and the batch disk check. While running: overall progress with ETA, the
current recording's stage, per-row status, "Stop after this recording" and
"Stop now". The default output folder is reused when it holds an earlier batch,
so starting the same batch again continues it.

The main window now gets a scrollbar when its content is taller than the window.
--screenshot accepts --batch <parent folder>; EASY_GUI_SCREENSHOT_START and
EASY_GUI_SCREENSHOT_FRAME capture a running batch for documentation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README: new section "Processing many recordings" (the table, stopping and
continuing a batch, batch_summary.csv and batch.log, --batch), troubleshooting
entries, and the scope note now says one point cloud per walk.
DESIGN.md: new §10 Batch mode (discovery, output names, checks, done markers and
restarting, sleep prevention, progress, tests with measured numbers); status M4.
EASY_FOREST_VERSION 0.2.0 (not released yet).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@michalpelka michalpelka left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is side car project to hdmapping. In this form cannot be merged and need to be integrated to become one into existing versioning pattern, CMake, 3rdparty and CI wiring.
This contribution propose own CI, release pattern and way to handle 3rd parties..
I recommend two things:

  • Option 1 (a lot of work):

    • work on integration (e.g. bulding proj from source on Mac for whole hdmapping)
    • integration in release script
    • proven support for all platforms.
  • Option 2 (almost no work, only Linux supprot):

    • sister project to hdmapping in HDMaps orgranization, with own release, packing and 3rd patterns and compatibility matrix.

Version: Easy Forest HDMapping has its own version (`EASY_FOREST_VERSION` in `apps/easy_gui/CMakeLists.txt`,
equal to the `easy-forest-v*` tag). Window title, README.txt and easy_gui.log show both, e.g. "Easy Forest HDMapping
0.2.0 (HDMapping 0.105.0)". The LAZ header's 32-character fields cannot hold that: generating software is
"Easy Forest HDMapping 0.2.0", system identifier "HDMapping 0.105.0".

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Own versioning pace in one repo in one product is no-go for me. All tooling in HDMapping is released together under same version, on one version number.
I believe it is a tool that was externally used and now is idea to make it canonical t o hdmapping. If so, I would require to release it together with HDmapping under the same CIs suporting Windows, Linux and Macos.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it rather should live in agent.md or claude.md. - documentation should be trimmed by human reviewier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is redundant. If you need to build a proj library for new tool, you should replace all tools to use it.
We cannot have requirement to get proj from hombrew and build it. It can lead to nasty linking errors.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once again - packing should be performed by one central script.

…ndows batch code builds in CI

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants