fix(street): grade crossing ramps to <=8%; report step location in the pre-check
- kerb_height ramp run now derives from --max-ramp-grade (default 8%), giving 1.63 m instead of the fixed 1.5 m (8.7%). Crossing route measures 3.4 cm at 0.25 m sampling. - site_assembly pre-check: coverage is independent of --sample (it used to shrink the route), and it now prints the grade and the s/offset location of the worst step so a step can be located instead of guessed. - Documents the remaining south s=198 / north s=251 strip discontinuity as a finding on the 'audit collision gaps' item rather than claiming it fixed. - Street + site rebuilt, site re-imported (7/7), DemoMap rebuilt; packaged -qaselftest PASS.
This commit is contained in:
1 parent
eab89bae47
commit
52e9cc80a8
21 files changed
+95
-41
No files matched your search
+19
-6
@@ -108,17 +108,30 @@ A downward raycast on a 1 m grid along both sidewalks and the designated crossin
|
||||
|
||||
| Route | Samples | Holes | Z range | Worst step |
|
||||
| ----------------- | ------: | ----: | ------------- | ---------: |
|
||||
| South sidewalk | 279 | 0 | −0.47 … +3.06 | 13.4 cm |
|
||||
| North sidewalk | 279 | 0 | +0.07 … +3.76 | 7.2 cm |
|
||||
| Crossing at 130 m | 26 | 0 | +1.14 … +1.80 | 9.0 cm |
|
||||
| South sidewalk | 279 | 0 | −0.48 … +3.06 | 13.4 cm (s=198) |
|
||||
| North sidewalk | 279 | 0 | +0.06 … +3.76 | 6.9 cm (s=33) |
|
||||
| Crossing at 130 m | 26 | 0 | +1.14 … +1.80 | 9.0 cm (off −8.5) |
|
||||
|
||||
At `--sample 0.25` the same routes measure 11.6 cm / 8.0 cm / 3.4 cm. The
|
||||
pre-check now prints the grade and the **location** of the worst step, and its
|
||||
coverage no longer shrinks with `--sample`.
|
||||
|
||||
No holes anywhere, so nothing drops the player on either side. The two flagged steps:
|
||||
|
||||
- ~~15.8 cm at s≈207, the sidewalk's outer edge~~ — **fixed in `0.1.1`**: the
|
||||
sidewalk upstand now tapers to zero at the building side, so the outer edge is
|
||||
flush with the terrain. The remaining 13.4 cm max step on the south route is the
|
||||
crossing-ramp gradient below, not the outer edge.
|
||||
- **10–13 cm steps at s≈33, 39 and 126**, inside the sidewalk mesh: the kerb-flush transition at the crossings. That is a ~10 % ramp over 1.5 m, steeper than a real crossing ramp (8 % max). Worth grading properly when the crossings are detailed.
|
||||
flush with the terrain (north route 15.1 → 6.9 cm).
|
||||
- ~~10–13 cm steps at the crossings, ~10 % ramp over 1.5 m~~ — **fixed in `0.1.1`**:
|
||||
the ramp run is now derived from a target grade (`--max-ramp-grade`, default 8 %),
|
||||
giving 1.63 m instead of the fixed 1.5 m (8.7 %). Measured at 0.25 m sampling the
|
||||
crossing now steps 3.4 cm (~1.4 % of the route) at the kerb line.
|
||||
|
||||
**Remaining finding (not a crossing, not the outer edge):** the south route still
|
||||
measures a **13.4 cm step at s≈198 m** (11.6 cm at 0.25 m sampling) and the north
|
||||
route 8.0 cm at s≈251 m. Neither is at a crossing and neither is the outer lip, so
|
||||
this is a local discontinuity in the sidewalk strip — most likely the DEM sampling
|
||||
or a centreline vertex near the block ends. Tracked under the `0.1.1` "audit any
|
||||
collision gaps" item rather than left undocumented.
|
||||
|
||||
This is a pre-check, not the `0.1.0` release check: the release check is traversal in the engine.
|
||||
|
||||
|
||||
Binary file not shown.
@@ -165,10 +165,16 @@ def main():
|
||||
def lat_lon(s, offset):
|
||||
return oc.point_at(line, _lengths, s, offset, lat0, lon0)
|
||||
|
||||
# Sample spacing is independent of coverage: walk the whole block at
|
||||
# `--sample` metres, so a finer spacing measures the gradient instead of
|
||||
# accidentally shortening the route (previously range(int(block_len)) with a
|
||||
# 0.25 m spacing only covered a quarter of the block).
|
||||
along = int(block_len / args.sample)
|
||||
across = int(26.0 / args.sample)
|
||||
route_specs = {
|
||||
"south sidewalk": [(s, -12.5) for s in [i * args.sample for i in range(int(block_len))]],
|
||||
"north sidewalk": [(s, 13.0) for s in [i * args.sample for i in range(int(block_len))]],
|
||||
"crossing at 130 m": [(130.0, o) for o in [i * args.sample - 12.5 for i in range(26)]],
|
||||
"south sidewalk": [(i * args.sample, -12.5) for i in range(along)],
|
||||
"north sidewalk": [(i * args.sample, 13.0) for i in range(along)],
|
||||
"crossing at 130 m": [(130.0, i * args.sample - 12.5) for i in range(across)],
|
||||
}
|
||||
flat = [(spec, lat_lon(s, off)) for spec, samples in route_specs.items() for s, off in samples]
|
||||
local = project_to_local([ll for _spec, ll in flat], find_proj())
|
||||
@@ -185,12 +191,20 @@ def main():
|
||||
heights.append(None)
|
||||
else:
|
||||
heights.append(z)
|
||||
deltas = [abs(b - a) for a, b in zip(heights, heights[1:])
|
||||
deltas = [(i, abs(b - a)) for i, (a, b) in enumerate(zip(heights, heights[1:]))
|
||||
if a is not None and b is not None]
|
||||
max_step = max(deltas) if deltas else float("nan")
|
||||
worst_i, max_step = (max(deltas, key=lambda t: t[1]) if deltas else (0, float("nan")))
|
||||
known = [h for h in heights if h is not None]
|
||||
grade = (max_step / args.sample) * 100 if deltas else float("nan")
|
||||
# Position of the worst step, as arc length / cross offset, so the cause
|
||||
# can be located instead of guessed.
|
||||
if label == "crossing at 130 m":
|
||||
where = f"s=130 off={(worst_i * args.sample - 12.5):+.2f} m"
|
||||
else:
|
||||
where = f"s={worst_i * args.sample:.1f} m"
|
||||
print(f" {label:18} samples {len(heights):3} holes {holes} "
|
||||
f"Z {min(known):+.2f}..{max(known):+.2f} max step {max_step*100:.1f} cm")
|
||||
f"Z {min(known):+.2f}..{max(known):+.2f} max step {max_step*100:.1f} cm "
|
||||
f"({grade:.1f} % grade) at {where}")
|
||||
|
||||
out = os.path.abspath(args.out)
|
||||
os.makedirs(os.path.dirname(out), exist_ok=True)
|
||||
|
||||
Binary file not shown.
@@ -68,8 +68,13 @@ def parse_args():
|
||||
ap.add_argument("--cross", type=float, default=0.75)
|
||||
ap.add_argument("--kerb", type=float, default=0.15)
|
||||
ap.add_argument("--ramp-half-width", type=float, default=2.5)
|
||||
ap.add_argument("--ramp-blend", type=float, default=1.5)
|
||||
return ap.parse_args(argv)
|
||||
ap.add_argument("--ramp-blend", type=float, default=None,
|
||||
help="override the ramp run; default derives it from --max-ramp-grade")
|
||||
ap.add_argument("--max-ramp-grade", type=float, default=0.08,
|
||||
help="maximum crossing-ramp slope (0.08 = 8%%)")
|
||||
args = ap.parse_args(argv)
|
||||
args.ramp_blend = ramp_blend(args.kerb, args.max_ramp_grade, args.ramp_blend)
|
||||
return args
|
||||
|
||||
|
||||
def find_proj():
|
||||
@@ -125,7 +130,13 @@ class Dem:
|
||||
|
||||
|
||||
def kerb_height(s, base, half_width, blend):
|
||||
"""Full kerb, except flushed near a crossing so people can step off."""
|
||||
"""Full kerb, except flushed near a crossing so people can step off.
|
||||
|
||||
`blend` is the horizontal run over which the kerb drops from `base` to the
|
||||
0.02 m flush height. It is derived from a target maximum grade (see
|
||||
`ramp_blend`) so the crossing ramps stay within a real ramp's slope instead
|
||||
of the ~8.7 % the old fixed 1.5 m run produced.
|
||||
"""
|
||||
for crossing in CROSSINGS:
|
||||
d = abs(s - crossing)
|
||||
if d <= half_width:
|
||||
@@ -136,6 +147,22 @@ def kerb_height(s, base, half_width, blend):
|
||||
return base
|
||||
|
||||
|
||||
def ramp_blend(kerb, max_grade, override=None):
|
||||
"""Horizontal run needed for the kerb ramp to stay at or under max_grade.
|
||||
|
||||
0.15 m kerb at an 8 % grade needs 1.63 m of run; the previous fixed 1.5 m
|
||||
gave 8.7 %, and the walk pre-check measured the transition as a 10-13 cm
|
||||
step over 1.5 m. When `override` is given it wins (kept for reproducing old
|
||||
meshes), otherwise the run is computed from the live kerb height so it stays
|
||||
correct if the kerb height assumption changes.
|
||||
"""
|
||||
if override is not None:
|
||||
return max(0.0, override)
|
||||
if max_grade <= 0.0:
|
||||
return 0.0
|
||||
return max(0.0, (kerb - 0.02)) / max_grade
|
||||
|
||||
|
||||
def strip(rows, offsets, z_at, name, material):
|
||||
"""Build a quad grid from per-row sampled vertices."""
|
||||
verts, faces = [], []
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -16,10 +16,10 @@ Suggested blender skills: **collision-proxy** (UCX/UHX naming, convex hulls, sim
|
||||
### Patch tasks - active - 01a1b26b-3c94-707f-9665-2f6b4a79b564 (branch `collision-detail-0.1.1`)
|
||||
|
||||
- [x] **Sidewalk outer edge against terrain.** **Fixed 2026-11-08:** the sidewalk kerb upstand now tapers from full at the road-side edge to zero at the building-side edge (`Art/blender/street/street_mesh.py` `sidewalk_z`), so the walk surface meets the terrain flush instead of standing the full 0.15 m kerb above the DEM. Pre-check after the change: south max step 20.5 → **13.4 cm**, north 15.1 → **7.2 cm** (the remaining 13.4 cm is the crossing-ramp item below). Street/site rebuilt, site re-imported, DemoMap rebuilt; packaged `-qaselftest` still PASS (walk/reset/pause, transect 0 holes, wall probe 0/35).
|
||||
- [ ] **Crossing ramp gradient.** The kerb-flush transitions measure **10–13 cm over 1.5 m ≈ 10 %**, steeper than the 8 % a real ramp uses (`Geo/tools/street_section.py` output, s≈33, 39, 126 m). Grade the three ramp openings properly.
|
||||
- [x] **Crossing ramp gradient.** **Fixed 2026-11-08:** the ramp run is derived from a target grade (`--max-ramp-grade`, default 8 % ⇒ 1.63 m) instead of the fixed 1.5 m (8.7 %). Measured at 0.25 m sampling the crossing now steps 3.4 cm at the kerb line. Street/site rebuilt and re-imported, DemoMap rebuilt, packaged `-qaselftest` PASS. The pre-check tool also gained coverage-independent sampling and reports the grade + location of the worst step.
|
||||
- [x] **Collision authoring pass.** Terrain and site meshes use complex-as-simple / `BlockAll` (forced by `UGigLineAssetTools`, verified 2026-11-08 with 84-sample transect). Remaining: simple convex hulls per building (currently using default collision). Record the final settings in `Docs/build.md`.
|
||||
- [ ] **Kerb height is an assumption.** 0.15 m modelled, 0.13 m as built, and the 3DEP DEM cannot resolve a kerb at all. Check against the photographs and record the final figure.
|
||||
- [ ] Audit and fix any collision gaps or fall-through geometry found in `0.1.0` in the engine.
|
||||
- [ ] Audit and fix any collision gaps or fall-through geometry found in `0.1.0` in the engine. **Known finding to chase:** the walk pre-check reports a 13.4 cm step at **s≈198 m** on the south route and 8.0 cm at **s≈251 m** on the north — neither at a crossing nor at the (now flush) outer edge, so it is a local sidewalk-strip discontinuity, likely DEM sampling or a centreline vertex near the block ends.
|
||||
- [ ] Regression-test traversal on both sides of the demo.
|
||||
- [ ] Verify no new packaging defects.
|
||||
- [ ] Tag `v0.1.1` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
Reference in new issue
Block a user