BT410 Phase 5.3.3: torso weapon-elevation aim -- completes the control surface
Reconstructs Torso::TorsoSimulation (installed as the Torso's per-frame Performance) and wires the torso aim into MechControlsMapper::InterpretControls, so the control surface now covers aiming as well as locomotion. - TORSO: analogElevationAxis/analogTwistAxis + SetAnalog* setters, CurrentElevation()/GetHorizontalEnabled() accessors. TorsoSimulation slews currentElevation += analogElevationAxis*baseElevationRate*dt clamped to the vertical limits, and (if horizontalEnabled) currentTwist by the twist axis clamped to the horizontal limits (authentic torso.cpp core; the skeleton-joint application is deferred with the render wave). - InterpretControls: routes stick pitch (stick_y, squared) into the torso elevation every mode; Std/Vet route stick yaw into the twist. BT_FORCE_ELEV dev hook. Verified: BT_FORCE_ELEV=0.8 -> the elevation slews up and clamps at the authentic verticalLimitTop = 0.349 rad = 20deg; neutral -> 0; zero Fail. Deferred: skeleton-joint application (render wave), HUD free-aim slew, look/eyepoint commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,10 @@
|
||||
# include <mech.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(TORSO_HPP)
|
||||
# include <torso.hpp>
|
||||
#endif
|
||||
|
||||
Derivation
|
||||
MechControlsMapper::ClassDerivations(
|
||||
Subsystem::ClassDerivations,
|
||||
@@ -184,8 +188,15 @@ void
|
||||
{
|
||||
stickPosition.x = (Scalar)atof(force_turn);
|
||||
}
|
||||
const char *force_elev = getenv("BT_FORCE_ELEV");
|
||||
if (force_elev != NULL)
|
||||
{
|
||||
stickPosition.y = (Scalar)atof(force_elev);
|
||||
}
|
||||
}
|
||||
|
||||
Torso *torso = (Torso *)mech->GetTorsoSubsystem();
|
||||
|
||||
Scalar topSpeed = mech->GetReverseStrideLength();
|
||||
Scalar walkSpeed = mech->GetWalkStrideLength();
|
||||
|
||||
@@ -209,17 +220,39 @@ void
|
||||
{
|
||||
stick_x = -stick_x;
|
||||
}
|
||||
Scalar stick_y = stickPosition.y * stickPosition.y;
|
||||
if (stickPosition.y < 0.0f)
|
||||
{
|
||||
stick_y = -stick_y;
|
||||
}
|
||||
Scalar pedal_3 = pedalsPosition * pedalsPosition * pedalsPosition;
|
||||
|
||||
turnDemand = 0.0f;
|
||||
|
||||
//
|
||||
// Torso aim. Every control mode routes the stick pitch (stick_y) into the
|
||||
// torso weapon-elevation axis. In Basic the stick yaw is the turn (legs);
|
||||
// in Standard/Veteran the stick yaw is the torso twist (free aim) and the
|
||||
// pedals steer. (The HUD free-aim slew + look/eyepoint commit are the
|
||||
// aiming/camera wave, deferred.)
|
||||
//
|
||||
if (controlMode == BasicMode)
|
||||
{
|
||||
turnDemand = stick_x;
|
||||
if (torso != NULL)
|
||||
{
|
||||
torso->SetAnalogElevationAxis(stick_y);
|
||||
torso->SetAnalogTwistAxis(0.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
turnDemand = pedal_3;
|
||||
if (torso != NULL)
|
||||
{
|
||||
torso->SetAnalogElevationAxis(stick_y);
|
||||
torso->SetAnalogTwistAxis(stick_x);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -248,9 +281,11 @@ void
|
||||
DEBUG_STREAM << "[mppr] thr=" << throttlePosition
|
||||
<< " rev=" << reverseThrust
|
||||
<< " stickX=" << stickPosition.x
|
||||
<< " stickY=" << stickPosition.y
|
||||
<< " mode=" << controlMode
|
||||
<< " -> speedDemand=" << speedDemand
|
||||
<< " turnDemand=" << turnDemand
|
||||
<< " torsoElev=" << (torso ? torso->CurrentElevation() : 0.0f)
|
||||
<< endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,11 +35,20 @@ drive are exercisable without hardware. `BT_MECH_LOG` prints a 1 Hz `[mppr]`
|
||||
demand trace. Verified: `throttle=1.0` → speedDemand=30; `throttle=0.3,turn=1.0`
|
||||
→ the mech walks a circle; neutral → 0. See MECH.NOTES.md (Phase 5.3 inc 2).
|
||||
|
||||
## Deferred (the aiming wave)
|
||||
## Torso aim wired (2026-07-21)
|
||||
|
||||
The torso/free-look half of the authentic InterpretControls is not yet
|
||||
reconstructed: the torso analog axes (`Torso::SetAnalogElevationAxis/
|
||||
SetAnalogTwistAxis`), HUD free-aim slew (`HUD::SetFreeAimSlew`), the recenter
|
||||
command, and the look/eyepoint commit (`BTCommitLookState`). These are the
|
||||
aiming/camera surface, separate from locomotion; they come with the
|
||||
Torso/HUD/eyepoint wave.
|
||||
InterpretControls now routes the stick PITCH (`stick_y`, squared soft response)
|
||||
into the torso weapon-elevation axis every control mode
|
||||
(`Torso::SetAnalogElevationAxis`), and in Standard/Veteran the stick YAW into the
|
||||
torso twist (`SetAnalogTwistAxis`); Basic keeps the stick yaw as the leg turn.
|
||||
`Torso::TorsoSimulation` slews + clamps the elevation/twist (see TORSO.NOTES.md).
|
||||
Verified: `BT_FORCE_ELEV=0.8` → torsoElev clamps at the authentic 20° limit.
|
||||
|
||||
## Deferred (the free-aim / camera wave)
|
||||
|
||||
Still not reconstructed: the HUD free-aim slew (`HUD::SetFreeAimSlew`, the
|
||||
Standard/Veteran torso-disabled path), the torso recenter command, and the
|
||||
look/eyepoint commit (`BTCommitLookState` — re-aims the eyepoint + re-arms the
|
||||
per-view weapon fire enables). These are the free-aim/camera surface; they come
|
||||
with the HUD/eyepoint wave. The skeleton-joint application of the torso angles
|
||||
is deferred with the render wave (TORSO.NOTES.md).
|
||||
|
||||
@@ -75,11 +75,22 @@ Torso::Torso(
|
||||
|
||||
currentTwist = 0.0f;
|
||||
currentElevation = 0.0f;
|
||||
for (int i = 0; i < 24; ++i)
|
||||
analogElevationAxis = 0.0f;
|
||||
analogTwistAxis = 0.0f;
|
||||
for (int i = 0; i < 22; ++i)
|
||||
{
|
||||
dynamicsState[i] = 0.0f;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the per-frame twist/elevation Performance (the replicant copy is
|
||||
// driven by console updates via TorsoCopySimulation instead, still staged).
|
||||
//
|
||||
if (owner->GetInstance() != Entity::ReplicantInstance)
|
||||
{
|
||||
SetPerformance(&Torso::TorsoSimulation);
|
||||
}
|
||||
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
@@ -100,12 +111,51 @@ Logical
|
||||
}
|
||||
|
||||
//
|
||||
// Per-frame torso twist / elevation integration. Not yet reconstructed.
|
||||
//#############################################################################
|
||||
// TorsoSimulation -- per-frame torso twist / weapon-elevation integration.
|
||||
//
|
||||
// Slews the current elevation/twist toward the analog aim axes (written by
|
||||
// MechControlsMapper::InterpretControls) at the resource base rates, clamped to
|
||||
// the resource limits. Authentic core (torso.cpp @004b6xxx): current += axis *
|
||||
// baseRate * dt. APPLYING the resolved angles onto the skeleton torso/gun
|
||||
// joints (horizontalJointNode / the elevation joint) is deferred with the
|
||||
// skeleton-link + render wave; here we advance the scalar aim state (read by the
|
||||
// HUD reticle / weapon aim and, once wired, the joints).
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
Torso::TorsoSimulation(Scalar)
|
||||
Torso::TorsoSimulation(Scalar time_slice)
|
||||
{
|
||||
Fail("Torso::TorsoSimulation -- torso.cpp not yet reconstructed");
|
||||
Check(this);
|
||||
|
||||
//
|
||||
// Elevation (weapon pitch): slew toward the analog axis, clamp to limits.
|
||||
//
|
||||
currentElevation += analogElevationAxis * baseElevationRate * time_slice;
|
||||
{
|
||||
Scalar lo = (verticalLimitBottom < verticalLimitTop)
|
||||
? verticalLimitBottom : verticalLimitTop;
|
||||
Scalar hi = (verticalLimitBottom < verticalLimitTop)
|
||||
? verticalLimitTop : verticalLimitBottom;
|
||||
if (currentElevation < lo) currentElevation = lo;
|
||||
if (currentElevation > hi) currentElevation = hi;
|
||||
}
|
||||
|
||||
//
|
||||
// Twist (horizontal torso rotation): only mechs with an enabled torso joint.
|
||||
//
|
||||
if (horizontalEnabled)
|
||||
{
|
||||
currentTwist += analogTwistAxis * baseTwistRate * time_slice;
|
||||
Scalar lo = (horizontalLimitLeft < horizontalLimitRight)
|
||||
? horizontalLimitLeft : horizontalLimitRight;
|
||||
Scalar hi = (horizontalLimitLeft < horizontalLimitRight)
|
||||
? horizontalLimitRight : horizontalLimitLeft;
|
||||
if (currentTwist < lo) currentTwist = lo;
|
||||
if (currentTwist > hi) currentTwist = hi;
|
||||
}
|
||||
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -68,7 +68,21 @@
|
||||
Logical
|
||||
TestInstance() const;
|
||||
Scalar
|
||||
CurrentTwist() const { return currentTwist; }
|
||||
CurrentTwist() const { Check(this); return currentTwist; }
|
||||
Scalar
|
||||
CurrentElevation() const { Check(this); return currentElevation; }
|
||||
Logical
|
||||
GetHorizontalEnabled() const{ Check(this); return horizontalEnabled; }
|
||||
|
||||
//
|
||||
// Analog aim inputs (written by MechControlsMapper::InterpretControls;
|
||||
// consumed by TorsoSimulation to slew the twist/elevation each frame).
|
||||
//
|
||||
void
|
||||
SetAnalogElevationAxis(Scalar axis) { Check(this); analogElevationAxis = axis; }
|
||||
void
|
||||
SetAnalogTwistAxis(Scalar axis) { Check(this); analogTwistAxis = axis; }
|
||||
|
||||
void
|
||||
TorsoSimulation(Scalar time_slice);
|
||||
void
|
||||
@@ -107,11 +121,13 @@
|
||||
void *horizontalShadowJointNode;
|
||||
Scalar currentTwist;
|
||||
Scalar currentElevation;
|
||||
Scalar analogElevationAxis;
|
||||
Scalar analogTwistAxis;
|
||||
//
|
||||
// Twist/elevation dynamics accumulators advanced by TorsoSimulation.
|
||||
// Reserved until the per-frame sim is reconstructed (phase 5).
|
||||
//
|
||||
Scalar dynamicsState[24];
|
||||
Scalar dynamicsState[22];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# TORSO.CPP / .HPP — reconstruction notes
|
||||
|
||||
`Torso` (: PowerWatcher) drives torso twist (horizontal) and weapon elevation
|
||||
(vertical). Tuning rates/limits stream from the resource
|
||||
(`horizontal/verticalRotationPerSecond`, `horizontal/verticalLimit*`,
|
||||
`torsoHorizontalEnabled`).
|
||||
|
||||
## Reconstructed
|
||||
|
||||
- Ctor: streams the base rates (deg→rad) + limits + `horizontalEnabled`, primes
|
||||
`currentTwist`/`currentElevation`/analog axes to 0, and installs
|
||||
`TorsoSimulation` as the per-frame Performance (the replicant copy is
|
||||
console-driven via `TorsoCopySimulation`, still staged).
|
||||
- `analogElevationAxis` / `analogTwistAxis` members + `SetAnalogElevationAxis` /
|
||||
`SetAnalogTwistAxis` setters (written by `MechControlsMapper::InterpretControls`).
|
||||
- `CurrentTwist()` / `CurrentElevation()` / `GetHorizontalEnabled()` accessors.
|
||||
- `TorsoSimulation(Scalar)` — per-frame aim integration (authentic core):
|
||||
- `currentElevation += analogElevationAxis · baseElevationRate · dt`, clamped
|
||||
to [verticalLimitBottom, verticalLimitTop];
|
||||
- if `horizontalEnabled`: `currentTwist += analogTwistAxis · baseTwistRate ·
|
||||
dt`, clamped to [horizontalLimitLeft, horizontalLimitRight].
|
||||
|
||||
**VERIFIED** (`BT_MECH_LOG` `[mppr] torsoElev=`, forced-input `BT_FORCE_ELEV`):
|
||||
stick pitch 0.8 slews the elevation up and clamps at the authentic
|
||||
`verticalLimitTop` = 0.349 rad = **20°**. Zero Fail.
|
||||
|
||||
## Deferred (skeleton-link + render wave)
|
||||
|
||||
`TorsoSimulation` advances the SCALAR aim state (elevation/twist), which the HUD
|
||||
reticle / weapon-aim read. APPLYING those angles onto the skeleton — rotating
|
||||
the `horizontalJointNode` (torso twist) and the elevation joint so the model's
|
||||
torso/gun barrels visibly aim — is deferred with the skeleton-joint-link +
|
||||
renderer wave (the joint handles are resolved null for now). `TorsoCopySimulation`
|
||||
(replicant console-driven aim) also stays staged.
|
||||
Reference in New Issue
Block a user