Skip to content

fix(sim): apply Replacement teleport fully to the physics body - #6

Open
taitaitai58 wants to merge 1 commit into
masterfrom
fix/replacement-teleport-physics
Open

fix(sim): apply Replacement teleport fully to the physics body#6
taitaitai58 wants to merge 1 commit into
masterfrom
fix/replacement-teleport-physics

Conversation

@taitaitai58

Copy link
Copy Markdown

Summary

Replacement (robot/ball teleport, from PR #3) already called DynamicRigidBody.reset() on position, which does genuinely warp the PhysX body — but two gaps made teleport unreliable enough that per-robot placement/calibration on this sim was effectively unusable:

  1. Ball velocity dropped. mocSim_BallReplacement.vx/vy were parsed but never forwarded to physics — a ball teleported with a requested launch velocity just sat still.
  2. Robot teleport didn't stick if a velocity command was in flight. A robot's previously-commanded veltangent/velnormal/velangular stayed latched in the Robot model after a teleport. The very next simulation tick re-applied that stale command, so the robot immediately drove off again — from the outside this looks exactly like "the teleport doesn't move the physics body," even though the position was actually applied for one instant. On top of that, the QML-side pose bookkeeping (prePoses/preVelocities) still held the pre-teleport pose, so the position jump itself read as a brief phantom velocity through MotionControl's accel limiter, causing a short coast even after the stale-command issue is fixed.

Changes

  • src/models/robot.{h,cpp}: new Robot::resetMotion() — zeroes kick/spinner/tangent/normal/angular targets and clears the actuation-delay pipeline (dead-time buffers) immediately, no ramp-down.
  • src/observer.{h,cpp}: visionReceive() calls resetMotion() on the replaced robot before re-emitting {blue,yellow}RobotsChanged, so QML picks up the stop on the very next tick instead of waiting for the next commands packet. Also decodes ballReplacement.vx()/vy() (m/s, has_vx()/has_vy() optional) and forwards them through a widened ballReplacementRequested(sceneX, sceneZ, hasVelocity, sceneVx, sceneVz) signal, converted to scene mm/s with the same axis convention as position (sceneVz = -vy*1000).
  • src/qml/sim/GameObjects.qml:
    • onRobotReplacementRequested now also seeds prePoses[id]/preVelocities[id] to the just-placed, at-rest pose, eliminating the phantom one-tick velocity.
    • New placeBall(scenePosition, velocity) helper, factored out of the existing mouse "place ball" (resetPosition("ball", ...)) code path — that path is behaviorally unchanged (calls placeBall(pos, null)), it just no longer duplicates the reset logic. onBallReplacementRequested uses the same helper and passes the velocity through when the packet had one.

Test plan

Built and ran headless (QT_QPA_PLATFORM=offscreen QSG_RENDER_LOOP=basic QT_QUICK_CONTROLS_STYLE=Basic ./bin/m2-Sim), sending mocSim_Packet Replacement datagrams via protoc --encode=mocSim_Packet to 127.0.0.1:20694 and reading the SSL vision output back with protoc --decode=SSL_WrapperPacket.

  • Robot teleport while a velocity command is latched (the calibration-blocking case): sent a continuous veltangent command to robot 2, then teleported it to (-2000, -2000) mid-stream.
    • Before fix: robot kept driving in the old commanded direction the entire ~0.83 s observed (teleport had no visible effect on subsequent motion).
    • After fix: robot lands at (-2000, -2000) and drifts < 0.06 mm over 1.3 s (80 vision frames) — i.e. it actually stays put.
  • Ball Replacement with vx/vy: placed the ball at (1.0, 0.5) m with vx=2.0 m/s. Ball now visibly travels (+x) and decelerates under the existing slip/roll friction model, instead of sitting motionless as before.
  • Ball Replacement without vx/vy (the common case, e.g. kickoff placement): unaffected — ball is placed and stays at rest (drift < 3 mm over 1.25 s, plain numerical/contact jitter).
  • No cross-talk: while robot 5 was under an independent, ongoing velocity command, teleporting robot 2 elsewhere didn't disturb robot 5's motion, and robot 2 landed exactly on target.
  • Full project rebuild (cmake --build .) is clean, no new warnings from the touched files.

Not covered: grSim-side / real bridge client verification (tested via a hand-rolled UDP sender against the raw proto, not through a specific AI client's bridge implementation), and the pre-existing mouse-driven "grab & carry" / "place ball" UI paths (unchanged code, not exercised interactively since this was a headless run — resetPosition("ball", ...)'s behavior was preserved byte-for-byte in the placeBall() refactor).

🤖 Generated with Claude Code

Replacement (robot/ball teleport) already called DynamicRigidBody.reset()
on position, but two gaps left it looking like the physics body never
really moved:

- mocSim_BallReplacement.vx/vy were parsed but silently dropped, so a
  teleported ball with a requested launch velocity just sat still.
- A robot's previously-commanded velocity (veltangent/velnormal/velangular)
  stayed latched in the Robot model after a teleport, so the very next
  tick re-applied it and the robot immediately drove off again — plus the
  QML-side pose bookkeeping (prePoses/preVelocities) still held the
  pre-teleport pose, reading the position jump itself as a brief phantom
  velocity through MotionControl's accel limiter.

Fixes:
- Robot::resetMotion() zeroes kick/spinner/tangent/normal/angular targets
  and clears the actuation-delay buffers; observer.cpp calls it for the
  replaced robot before re-emitting {blue,yellow}RobotsChanged so QML
  picks up the stop immediately instead of waiting on the next commands
  packet.
- onRobotReplacementRequested seeds prePoses/preVelocities to the
  just-placed, at-rest pose so there's no phantom one-tick velocity.
- observer.cpp now forwards ball vx/vy (m/s -> scene mm/s, same axis
  convention as position) through a widened ballReplacementRequested
  signal; GameObjects.qml's new placeBall() helper (factored out of the
  existing mouse "place ball" path, which behaves identically to before)
  applies it via setLinearVelocity() when present.

Verified headless (QT_QPA_PLATFORM=offscreen) by sending mocSim_Packet
Replacement datagrams via protoc --encode and reading back vision:
- Robot teleported mid-command (veltangent latched) now lands and stays
  within ~0.05mm over 1.3s, vs. previously coasting away at full speed.
- Ball Replacement with vx/vy now visibly travels and decelerates under
  the existing slip/roll friction model instead of sitting still.
- Ball Replacement without vx/vy (the common case) is unaffected: still
  placed at rest.
- A second robot's independent, ongoing velocity command is unaffected
  by another robot's Replacement (no cross-talk).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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