3 Commits

Author SHA1 Message Date
robin 45a888664b Merge main: snap wheel command to target on landing after airborne
Brings in the airborne-landing fix from main. The previously
committed ARM binary was built against the pre-fix source, so it's
dropped again here rather than carried forward stale — same
build-on-target convention as before: run_4wd.sh will compile a
fresh aarch64 binary on next launch on the Jetson. Build and commit
that binary back to this branch afterward.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 13:22:54 +09:00
robin ed34e1c025 Snap wheel command to target immediately on landing after airborne
Previously, once a wheel's airborne flag cleared, its target reverted
to the normal drive command but the actual RPM still had to ramp up
through the gentle standstill-launch accel_rate/jerk profile. Since
the chassis is already moving at that point (unlike a stop-start),
the wheel spent several hundred ms unable to match ground speed,
dragging/grinding against the surface and occasionally landing on a
momentarily negative curve-turn target, making it spin backward.

Track the airborne->grounded transition per wheel and, on the tick it
clears, snap cmd directly to target and reset the jerk accel state
instead of ramping, so the wheel rejoins the other three immediately.

Verified working on hardware.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 13:22:29 +09:00
robin 19fb70d998 Fix curve-steering wheel-reversal at partial throttle
Steering angular velocity (omega) was scaled by the constant max
speed (max_v) instead of the actual current forward speed (v_x).
This decoupled turn tightness from throttle position: at low/medium
throttle, a moderate left-stick steering input already produced an
omega large enough to flip the inner wheel's commanded velocity
negative, causing the robot to spin/reverse/lurch forward instead of
smoothly curving. Scaling by abs(v_x) keeps turn radius proportional
to speed as intended, matching prior full-throttle behavior while
fixing the reversal at partial throttle.

Also drops the stale committed x86-64 binary (built before this fix,
so its behavior no longer matched source). Build fresh on an x86
machine via `make`; run_4wd.sh already rebuilds automatically when
the binary is missing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 10:56:33 +09:00
2 changed files with 45 additions and 0 deletions
+45
View File
@@ -942,6 +942,12 @@ int main(int argc, char **argv) {
bool airborne_fl = false, airborne_fr = false;
bool airborne_rl = false, airborne_rr = false;
int air_count_fl = 0, air_count_fr = 0, air_count_rl = 0, air_count_rr = 0;
// 착지(airborne 해제) 직후 한 틱 동안: 차체는 이미 그 속도로 움직이고
// 있는데 cmd는 정지출발용 accel_rate로 천천히 재가속되면, 그 사이 바퀴가
// 지면 이동속도를 못 따라가 끌리며 긁히는 문제가 있어 즉시 target으로
// 스냅시켜 지연을 없앤다.
bool just_landed_fl = false, just_landed_fr = false;
bool just_landed_rl = false, just_landed_rr = false;
char wheel_status_str[5] = "OOOO";
bool fault_active = false; // 드라이버 알람(과전류/과부하 등) 발생 여부
@@ -1117,6 +1123,29 @@ int main(int argc, char **argv) {
state = "RUNNING";
}
} else if (state == "RUNNING") {
// 착지 직후: 정지출발용 저크 램프를 건너뛰고 차체가 이미 내고 있는
// 속도로 즉시 맞춰 지면과의 미끄러짐(끌림)을 최소화한다.
if (just_landed_fl) {
cmd_fl = target_fl;
accel_fl = 0.0f;
just_landed_fl = false;
}
if (just_landed_fr) {
cmd_fr = target_fr;
accel_fr = 0.0f;
just_landed_fr = false;
}
if (just_landed_rl) {
cmd_rl = target_rl;
accel_rl = 0.0f;
just_landed_rl = false;
}
if (just_landed_rr) {
cmd_rr = target_rr;
accel_rr = 0.0f;
just_landed_rr = false;
}
float jerk_now = is_spin_turn ? spin_jerk_rate : jerk_rate;
cmd_fl = jerkLimitedStep(cmd_fl, target_fl, accel_fl, accel_rate,
decel_rate, jerk_now);
@@ -1243,11 +1272,27 @@ int main(int argc, char **argv) {
air_count_rl = air_now_rl ? air_count_rl + 1 : 0;
air_count_rr = air_now_rr ? air_count_rr + 1 : 0;
bool prev_airborne_fl = airborne_fl;
bool prev_airborne_fr = airborne_fr;
bool prev_airborne_rl = airborne_rl;
bool prev_airborne_rr = airborne_rr;
airborne_fl = air_count_fl >= airborne_debounce_ticks;
airborne_fr = air_count_fr >= airborne_debounce_ticks;
airborne_rl = air_count_rl >= airborne_debounce_ticks;
airborne_rr = air_count_rr >= airborne_debounce_ticks;
// 방금 착지(뜬 상태 -> 정상)한 바퀴는 다음 틱에 cmd를 target으로 즉시
// 스냅해 재가속 지연을 없앤다.
if (prev_airborne_fl && !airborne_fl)
just_landed_fl = true;
if (prev_airborne_fr && !airborne_fr)
just_landed_fr = true;
if (prev_airborne_rl && !airborne_rl)
just_landed_rl = true;
if (prev_airborne_rr && !airborne_rr)
just_landed_rr = true;
auto statusChar = [](bool air, bool stall) {
return air ? 'A' : (stall ? 'S' : 'O');
};
Binary file not shown.