Skip to content

feat: ugv_strike vehicle profile for full-capability UGV testing - #317

Merged
rmeadomavic merged 3 commits into
mainfrom
feat/ugv-full-capability-profile
Aug 4, 2026
Merged

feat: ugv_strike vehicle profile for full-capability UGV testing#317
rmeadomavic merged 3 commits into
mainfrom
feat/ugv-full-capability-profile

Conversation

@rmeadomavic

Copy link
Copy Markdown
Owner

Enables the full detection-to-strike chain on the SORCC UGV kits for the Week 5 AI block, shipped as a committed vehicle profile.

Why a vehicle profile, not config.ini defaults

scripts/deploy.sh runs git stash before every pull and config.ini is tracked, so on-box config edits are silently stashed on update. A [vehicle.*] section ships in the repo and survives every pull. Each kit selects it with one line in /etc/hydra/vehicle.env.

What it turns on

Autonomous evaluation, servo tracking, truck/car target classes, GUIDED, operator-locked targeting, and a 25 km geofence centred on the operating area so the fence is satisfied without constraining the test.

Geofence cannot be disabled: _has_valid_geofence() requires a polygon or nonzero lat/lon, and both _eval_autonomy_live and _eval_autonomy_dryrun reject every detection without one. A non-binding fence is the supported way to get out of its way.

Strike path selection

_handle_strike_command sends one GUIDED waypoint at an estimated target GPS and misses a moving target. _handle_approach_strike_command runs ApproachMode.STRIKE, re-targeting continuously. ugv_strike is wired to the continuous path; every other profile keeps the existing one-shot behavior.

Defects found and fixed during review

  1. Strike re-entry. autonomous.evaluate only refreshes its cooldown when strike_cb returns truthy, and the approach handler returned False whenever an approach was already active. Once the 30 s cooldown expired mid-strike, every subsequent frame logged a spurious AUTONOMOUS STRIKE FAILED and recorded a reject decision. Re-striking the track already under approach is now idempotent; a different track is still refused.
  2. reserved_channels dropped. Vehicle profiles do not inherit — bootstrap.py reads only the named section. reserved_channels is a vehicle-local key read with fallback="", so omitting it skips the servo and light-bar channel-conflict guard rather than failing loudly. On the truck, 1 and 3 are steering and throttle. Now declared explicitly, with a test pinning it to [vehicle.ugv].
  3. Loop-killing attribute access. _autonomous_strike_handler runs every frame and read self._vehicle directly; fixtures that patch __init__ never set it, which _refuse_approach_for_fw already defends against. Now uses the same getattr idiom and matches _is_fw_profile's case normalization.

Out of scope

_eval_drop and _eval_rf_hunt remain unconditionally BLOCKED on #147; untouched.

Verification

2654 passed, flake8 clean. The 19 failures / 10 errors in test_ota_verify_pull.py and test_tak_pytak_emitter.py are pre-existing on the dev box (missing pytak) and reproduce identically on a clean tree. Every new test was confirmed red before its fix and green after.

Follow-up, not fixed here

autonomous.notify_strike_complete() (autonomous.py:565) clears _strike_in_progress, but it has no callers anywhere and the flag is never read as a gate. Write-only dead state; the cooldown is the only real re-entry control.

rmeadomavic and others added 3 commits August 4, 2026 18:08
Adds a committed [vehicle.ugv_strike] profile enabling autonomous
evaluation, servo tracking, and continuous strike approach for ground
vehicle testing. Shipping it as a vehicle profile rather than config.ini
defaults means it survives deploy.sh, which stashes local changes before
every pull.

Wires the autonomous strike callback per-profile: ugv_strike uses the
continuous ApproachMode.STRIKE path, which re-targets a moving vehicle
every frame. Other profiles keep the existing one-shot waypoint handler.

Fixes a re-entry defect in the continuous path: _handle_approach_strike_command
returned False when an approach was already active, and autonomous.evaluate
only refreshes its cooldown when strike_cb returns truthy. Once the 30s
cooldown expired mid-strike, every subsequent frame logged a spurious
AUTONOMOUS STRIKE FAILED. Re-striking the track already under approach is
now idempotent; a different track is still refused.

Declares reserved_channels explicitly, since vehicle profiles do not
inherit and its absence silently skips the servo channel-conflict guard.

Drop and RF hunt remain blocked on #147; untouched.

Co-authored-by: Claude <noreply@anthropic.com>
_autonomous_strike_handler runs in the detection loop on every frame and
read self._vehicle directly. Pre-existing fixtures construct Pipeline by
patching __init__ without setting _vehicle, which the codebase already
defends against in _refuse_approach_for_fw; the bare access would raise
AttributeError inside the loop.

Also matches _is_fw_profile's normalization contract so a HYDRA_VEHICLE
value of UGV_STRIKE does not silently fall back to the one-shot handler.

Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

CI FAIL — flake8 + pytest fast suite (2b86508) · run log

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

CI PASS — flake8 + pytest fast suite (290f19c) · run log

@rmeadomavic
rmeadomavic merged commit d8ba7c8 into main Aug 4, 2026
3 checks passed
@rmeadomavic
rmeadomavic deleted the feat/ugv-full-capability-profile branch August 4, 2026 22:14

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9221309a98

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread config.ini
autonomous.safe_mode = HOLD
autonomous.default_features = detect,mavlink,tak_output,logging

[vehicle.ugv_strike]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve shared-battery graceful stop for UGV strike

This new UGV profile does not set shared_battery = true. Because vehicle profiles do not inherit and Pipeline defaults _shared_battery to false when the active [vehicle.<name>] section omits the key, shared-pack UGV/truck kits selected with HYDRA_VEHICLE=ugv_strike will not wire the BatteryMonitor LOW-transition callback, so a low propulsion pack only gets the STATUSTEXT path instead of commanding HOLD and safing the servo tracker like the existing [vehicle.ugv] profile. Add shared_battery = true here unless this strike truck has a separate companion battery.

Useful? React with 👍 / 👎.

Comment thread config.ini
autonomous.safe_mode = HOLD
autonomous.default_features = detect,mavlink,tak_output,logging

[vehicle.ugv_strike]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add the UGV strike profile to factory config

[vehicle.ugv_strike] is added only to config.ini, but factory reset and fresh factory configs are sourced from config.ini.factory. After a dashboard/API factory reset or on images created from the factory file, setting HYDRA_VEHICLE=ugv_strike will hit the unknown-profile path and run the base config with autonomy disabled and servo tracking off instead of this strike profile. Mirror this section into config.ini.factory and include that file in the regression coverage.

Useful? React with 👍 / 👎.

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.

1 participant