|
1 | 1 | # Changelog |
2 | 2 |
|
| 3 | +## v1.4.1 |
| 4 | + |
| 5 | +### Perf — `pypatchworkpp.patchworkpp` per-patch heap traffic eliminated |
| 6 | + |
| 7 | +Three changes inside `PatchWorkpp::extract_piecewiseground` and |
| 8 | +`PatchWorkpp::estimate_plane` take KITTI seq 00 from 10.26 ms to |
| 9 | +8.94 ms per frame (**97.5 Hz → 111.9 Hz, +14.8% Hz**, median of 3 |
| 10 | +runs, i7-12700). This closes the part of #96 that was driven by |
| 11 | +short-lived allocations in R-VPF + R-GPF. |
| 12 | + |
| 13 | +**High-impact (this is where the +14.8% comes from):** |
| 14 | + |
| 15 | +- `estimate_plane`: drop `Eigen::MatrixX3f eigen_ground` + `centered` |
| 16 | + + `centered.adjoint() * centered`. Replace with a single-pass |
| 17 | + scalar accumulation of mean and 9 cross-products, then build the |
| 18 | + 3x3 covariance on the stack. No more per-call Eigen heap |
| 19 | + allocations. |
| 20 | +- `extract_piecewiseground`: promote `src_wo_verticals` and |
| 21 | + `src_tmp` to reused instance scratch members. `vector::clear()` |
| 22 | + keeps capacity, so per-patch malloc pressure on the glibc heap |
| 23 | + (which was serialising the loop, see #96) drops away after the |
| 24 | + first few patches. |
| 25 | +- `estimateGround` main loop: `auto& zone` instead of `auto zone` |
| 26 | + for `ConcentricZoneModel_[zone_idx]`. Avoids a deep-copy of the |
| 27 | + full 3-level nested vector per outer iteration. Safe because each |
| 28 | + `(zone, ring, sector)` patch is read once and the CZM is flushed |
| 29 | + at the top of every `estimateGround` call. |
| 30 | + |
| 31 | +**Lower-impact, kept for cleanliness:** |
| 32 | + |
| 33 | +- `JacobiSVD<Matrix3f>` to `SelfAdjointEigenSolver::computeDirect` |
| 34 | + for the 3x3 PSD covariance in both `cpp/common/src/plane_fit.cpp` |
| 35 | + and the in-place `PatchWorkpp::estimate_plane`. Closed-form, no |
| 36 | + Jacobi iterations. `singular_values_` is repacked descending so |
| 37 | + every consumer (`linearity_` / `planarity_` in `common`, |
| 38 | + `flatness_thr` index `(2)` in patchwork classic, |
| 39 | + `ground_flatness=minCoeff()` and `line_variable=sv(0)/sv(1)` in |
| 40 | + patchwork++) keeps the same convention bit-for-bit. |
| 41 | +- `const&` on `addCloud`'s `add` parameter, `RevertCandidate` loop |
| 42 | + vars, and the `temporal_ground_revert` / |
| 43 | + `calc_point_to_plane_d` / `calc_mean_stdev` signatures. |
| 44 | + |
| 45 | +Patchwork classic is unaffected on the perf side: TBB |
| 46 | +`parallel_for` already amortises allocations across cores and SVD |
| 47 | +is sub-us/patch. |
| 48 | + |
| 49 | +### Numerical equivalence |
| 50 | + |
| 51 | +KITTI seq 00 (4541 frames), v1.4.0 to v1.4.1: |
| 52 | + |
| 53 | +| Method (protocol) | Before | After | Δ F1 | |
| 54 | +| ------------------- | -------------------------- | -------------------------- | ----: | |
| 55 | +| `patchwork` (pw) | P 92.34, R 94.64, F1 93.41 | P 92.34, R 94.64, F1 93.41 | 0.00 | |
| 56 | +| `patchworkpp` (pp) | P 94.88, R 98.47, F1 96.62 | P 94.89, R 98.48, F1 96.63 | +0.01 | |
| 57 | + |
| 58 | +Algebraic identity of `JacobiSVD` vs `eigh` verified on 500 real |
| 59 | +KITTI patch covariances: `normal_` (up to sign), |
| 60 | +`singular_values_`, `linearity_`, `planarity_`, `ground_flatness`, |
| 61 | +`line_variable` all match to FP precision. Both within the ±0.05 |
| 62 | +macro budget. |
| 63 | + |
| 64 | +### References |
| 65 | + |
| 66 | +- #100 — PR (perf: alloc-free + eigh) |
| 67 | +- #96 — Issue (R-VPF / R-GPF allocation profile) |
| 68 | + |
3 | 69 | ## v1.4.0 |
4 | 70 |
|
5 | 71 | ### Refactor — shared `common` library + optional TBB parallelisation |
|
0 commit comments