Conversation
…threaded mujoco control (#13) * feat(sim): add gravity-comp physics loop for sim robot - i2rt/robots/sim_robot.py: added background physics thread with gravity compensation, enable/disable toggles, cmd<->mj qpos mapping, and clean shutdown in close() - i2rt/robots/get_robot.py: pass unit gravity_comp_factor to SimRobot so sim uses exact model-based compensation - i2rt/utils/mujoco_control_interface.py: start sim physics on run(), default to VIS mode in sim, and toggle grav-comp on SPACE between VIS and CONTROL - i2rt/robots/config/yam.yml: tune joint-4 gravity_comp_factor from 1.3 to 1.2 Co-authored-by: Claude <noreply@anthropic.com> * feat(grav-comp): add motor-side kd damping via grav_comp_kd YAML field Replaces the reverted host-side damping (df0b3b3) with the motor's MIT-mode kd channel. Previous approach computed `-damping * qvel` on the host each control iteration, which introduced a one-sample delay and amplified CAN velocity quantization noise — together causing the oscillation. The MIT-mode kd runs on the motor's onboard loop at kHz rate with no CAN round-trip, eliminating both failure modes. grav_comp_kd is active only in gravity-comp idle mode; control-mode paths (command_joint_pos / command_joint_state) continue to use self._kd as before. Gripper slot is padded with 0 — no passive damping needed since it's position-commanded, not gravity-balanced. - i2rt/robots/config/yam.yml: add grav_comp_kd [0.5, 0.5, 0.5, 0.15, 0.15, 0.15] (hand-tuned); also bump J3 gravity_comp_factor 1.2 → 1.35 - i2rt/robots/config/yam_pro.yml: add grav_comp_kd [2.0, 2.0, 2.0, 0.5, 0.5, 0.5] (default, tune on hardware) - i2rt/robots/config/yam_ultra.yml: same default as yam_pro - i2rt/robots/config/big_yam.yml: same default as yam_pro - i2rt/robots/utils.py: add grav_comp_kd field to _ArmHWConfig and parse it in _load_arm_config - i2rt/robots/get_robot.py: load hw.grav_comp_kd, append 0.0 for gripper slot, pass to MotorChainRobot - i2rt/robots/motor_chain_robot.py: accept grav_comp_kd kwarg, store as self._grav_comp_kd with length assertion, seed _commands.kd from it only when zero_gravity_mode=True, expose in get_robot_info Co-authored-by: Claude <noreply@anthropic.com> * chore(grav-comp): tune per-arm grav_comp_kd and yam J3 gravity_comp_factor Hardware-tuned starting values after validating the motor-side MIT-mode kd path on yam. The 2.0/0.5 defaults introduced in the prior commit were too stiff — dropping by 4× gives smooth settling without chatter. big_yam wrist J4 kept higher (0.3) since it drives a larger moment arm than yam_pro/ultra. - i2rt/robots/config/yam.yml: pull J3 gravity_comp_factor 1.35 → 1.3 (over-compensation was contributing to the stiction limit cycle) - i2rt/robots/config/yam_pro.yml: grav_comp_kd [2.0,...,0.5,...] → [0.5, 0.5, 0.5, 0.15, 0.15, 0.15] - i2rt/robots/config/yam_ultra.yml: same values as yam_pro - i2rt/robots/config/big_yam.yml: grav_comp_kd → [0.5, 0.5, 0.5, 0.3, 0.15, 0.15] (J4 higher to match larger wrist) Co-authored-by: Claude <noreply@anthropic.com> * fix(grav-comp): restore grav-comp idle commands on CONTROL→VIS toggle - i2rt/robots/motor_chain_robot.py: add `enter_gravity_comp_idle()` that resets `self._commands` to zeros with `kd=self._grav_comp_kd`, mirroring the `zero_gravity_mode=True` init branch; leaves `self._kp`/`self._kd` untouched so later control commands keep correct gains. - i2rt/utils/mujoco_control_interface.py: on CONTROL→VIS SPACE toggle, call the new `enter_gravity_comp_idle()` instead of `update_kp_kd(zeros, zeros)` — the old call only rewrote member caches and left the stale PD target in `_commands`, causing motors to keep holding the last CONTROL pose (felt as per-joint friction after toggling back). Co-authored-by: Claude <noreply@anthropic.com> * chore(grav-comp): retune yam gravity_comp_factor and grav_comp_kd - i2rt/robots/config/yam.yml: bumped J2/J3 gravity_comp_factor (1.1→1.4, 1.35→1.4), lowered J4 (1.3→1.2); reduced grav_comp_kd across all joints for softer motor-side damping Co-authored-by: Claude <noreply@anthropic.com> * chore(grav-comp): retune yam J2 gravity_comp_factor and grav_comp_kd - i2rt/robots/config/yam.yml: lower J2 gravity_comp_factor from 1.4 to 1.1 and zero out most grav_comp_kd except J4 (0.2) to reduce chatter Co-authored-by: Claude <noreply@anthropic.com> * feat(grav-comp): add Coulomb friction comp and thread mujoco control loop - i2rt/robots/config/coulomb_friction.yml: new motor-type→friction (Nm) table (DM4310/DM4340/DM6248/DM3507) for sign(q_dot)-based friction comp - i2rt/robots/utils.py: add _load_coulomb_friction_table (lru_cached) and get_motor_chain_coulomb_friction to map motor_list → per-joint friction array - i2rt/robots/motor_chain_robot.py: accept coulomb_friction kwarg, apply coulomb_friction * sign(q_dot) alongside gravity comp in update(), expose via get_robot_info - i2rt/robots/get_robot.py: build friction array from the assembled motor_list (gripper-aware) and pass to MotorChainRobot - i2rt/robots/config/yam.yml: retune gravity_comp_factor to [1.0, 1.1, 1.1, 1.2, 1.0, 1.0] now that friction comp is active - i2rt/utils/mujoco_control_interface.py: move sliders/mocap → IK → collision → command_joint_pos into a daemon control thread at control_dt cadence; guard shared MjData with viewer.lock() and only hold the lock for brief snapshot/write-back sections so viewer render never stalls commands Co-authored-by: Claude <noreply@anthropic.com> * fix(grav-comp): fix passive encoder script and expose CanInterface.channel - i2rt/motor_drivers/can_interface.py: store channel as instance attribute so PassiveEncoderReader can access it - i2rt/robots/config/yam.yml: retune J4 grav_comp_kd from 0.2 to 0.15 - scripts/run_gello_with_passive_encoder.py: lower encoder firmware requirement to >=2.2.0, remove motor 7, disable buffered reader Co-authored-by: Claude <noreply@anthropic.com> * chore(grav-comp): retune DM4310 Coulomb friction and yam J4 gravity_comp_factor - i2rt/robots/config/coulomb_friction.yml: bump DM4310 friction from 0.05 to 0.06 - i2rt/robots/config/yam.yml: increase J4 gravity_comp_factor from 1.2 to 1.3 Co-authored-by: Claude <noreply@anthropic.com> * fix(grav-comp): address PR #13 review comments - i2rt/robots/sim_robot.py: add docstring to command_joint_pos explaining grav-comp disable/re-enable lifecycle during control mode - i2rt/robots/sim_robot.py: use wall-clock-relative sleep in _physics_loop to prevent timing drift at 200 Hz - i2rt/utils/mujoco_control_interface.py: reword _log() comment to accurately describe thread-safety of qpos reads - i2rt/robots/utils.py: add non-negative assertion in get_motor_chain_coulomb_friction - scripts/run_gello_with_passive_encoder.py: fix return type annotation from None to EncoderChain Co-authored-by: Claude <noreply@anthropic.com> * chore(grav-comp): retune grav_comp_kd and yam_ultra J4 gravity factor for testing - i2rt/robots/config/yam_pro.yml: zero grav_comp_kd on J1-J3/J5/J6, keep J4 at 0.15 to evaluate idle-mode damping with motor kd disabled on non-critical joints - i2rt/robots/config/yam_ultra.yml: match yam_pro grav_comp_kd tuning and lower J4 gravity_comp_factor from 1.3 to 1.1 to align with yam_pro overshoot behavior Co-authored-by: Claude <noreply@anthropic.com> * chore(grav-comp): zero grav_comp_kd on big_yam J1-J3, J5, J6 for testing - i2rt/robots/config/big_yam.yml: set grav_comp_kd to [0.0, 0.0, 0.0, 0.3, 0.0, 0.0] to isolate gravity/friction tuning without MIT-mode velocity damping on all joints except J4 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(grav-comp): retune J4 gravity factors and yam_pro J1 grav_comp_kd - i2rt/robots/config/big_yam.yml: bump J4 gravity_comp_factor 1.0 → 1.1 to better hold against gravity - i2rt/robots/config/yam.yml: reduce J4 gravity_comp_factor 1.3 → 1.2 to ease over-compensation - i2rt/robots/config/yam_pro.yml: bump J4 gravity_comp_factor 1.1 → 1.2 and enable J1 grav_comp_kd 0.0 → 0.15 for idle damping - i2rt/robots/config/yam_ultra.yml: reduce J2 gravity_comp_factor 1.3 → 1.1 to ease over-compensation Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * refactor(grav-comp): move coulomb friction from motor-type table to per-joint arm config - i2rt/robots/config/yam.yml: added coulomb_friction [0.3, 0.3, 0.3, 0.06, 0.06, 0.06] so each joint can be tuned independently of motor type - i2rt/robots/config/yam_pro.yml: same as yam.yml — preserves current per-motor-type values as the new per-joint baseline - i2rt/robots/config/yam_ultra.yml: same as yam.yml — preserves current per-motor-type values as the new per-joint baseline - i2rt/robots/config/big_yam.yml: added coulomb_friction [0.0, 0.0, 0.3, 0.3, 0.06, 0.06] matching its [DM6248x2, DM4340x2, DM4310x2] motor layout - i2rt/robots/config/coulomb_friction.yml: deleted — values now live per-joint in each arm config - i2rt/robots/utils.py: added coulomb_friction ndarray field to _ArmHWConfig, parse + non-negativity assert + log in _load_arm_config, removed _COULOMB_FRICTION_PATH / _load_coulomb_friction_table / get_motor_chain_coulomb_friction - i2rt/robots/get_robot.py: build coulomb_friction from hw.coulomb_friction.copy(), append 0.0 for gripper slot so the gripper never receives friction comp (held by position commands, not balanced against gravity) Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(grav-comp): retune big_yam J2 grav_comp_kd and lower J1-J3 coulomb friction - i2rt/robots/config/big_yam.yml: raise J2 grav_comp_kd from 0.0 to 0.1 to reduce coast on that joint - i2rt/robots/config/yam_pro.yml: lower J1-J3 coulomb_friction from 0.3 to 0.2 to reduce stiction overshoot - i2rt/robots/config/yam_ultra.yml: lower J1 coulomb_friction from 0.3 to 0.2 to match yam_pro tuning Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(gripper): update crank_4310 gripper mass to 0.73030 kg - i2rt/robot_models/gripper/crank_4310/crank_4310.xml: updated gripper inertial mass from 0.55366 to 0.73030 kg to reflect measured value Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(gripper): revert crank_4310 gripper mass to 0.60366 kg - i2rt/robot_models/gripper/crank_4310/crank_4310.xml: restored gripper inertial mass from 0.73030 kg back to 0.60366 kg Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * refactor(control-with-mujoco): run robot and viewer in separate subprocesses - examples/control_with_mujoco/control_with_mujoco.py: split the script into a robot_worker + viewer_worker pair spawned via multiprocessing, with the main process only hosting the IPC primitives (SharedMemory-backed numpy state, command Queue, stop Event). This isolates the 250 Hz CAN control loop from viewer/IK/rendering GIL contention. ProxyRobot/ProxyMotorChain/ProxyJointState stubs forward the Robot surface MujocoControlInterface uses — state reads come from shared memory, commands go onto the queue. The published loop_hz mirrors motor_chain.comm_freq (fallback to a 1 s RateRecorder) so --log now shows the real driver rate instead of the viewer's data-read cadence. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(grav-comp): harmonize grav_comp_kd and friction across yam variants - i2rt/robots/config/yam.yml: raise grav_comp_kd to [0.1,0.1,0.1,0.3,0.05,0.05] for consistent damping with pro/ultra - i2rt/robots/config/yam_pro.yml: align gravity_comp_factor, grav_comp_kd, and coulomb_friction with yam/yam_ultra tuning - i2rt/robots/config/yam_ultra.yml: align gravity_comp_factor, grav_comp_kd, and coulomb_friction with yam/yam_pro tuning Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(gitignore): ignore mjb files * fix(control-with-viser): gate commands on self-collision and restore grav-comp on VIS exit - i2rt/utils/viser_control_interface.py: add scratch _check_data MjData buffer and _has_self_collision so IK and joint-slider modes refuse commands that would self-collide; refactor _denormalize_slide_joints / _enforce_eq_constraints into _on(data) variants so the collision check writes to _check_data without corrupting render state. Add _enter_vis_grav_comp / _enter_control_grav_comp helpers (hasattr dispatch: SimRobot.enable/disable_gravity_comp, MotorChainRobot.enter_gravity_comp_idle) and detect vis<->control transitions in the main loop — dispatching from the GUI callback raced with in-flight command_joint_pos calls and could leave the arm clamped in PD after returning to VIS. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(grav-comp): bump big_yam grav_comp_kd and base coulomb_friction - i2rt/robots/config/big_yam.yml: raise grav_comp_kd to [0.5, 0.5, 0.5, 0.3, 0.1, 0.1] and add 0.1 Nm coulomb_friction on joints 0-1 to reduce coasting and sticky feel during gravity-comp idle Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(grav-comp): remove redundant block comments added in this PR - examples/control_with_mujoco/control_with_mujoco.py: drop multi-line block comments explaining spawn semantics, shared-memory sentinel, RateRecorder rationale, sentinel/teardown notes; section markers and inline comments retained - i2rt/robots/get_robot.py: drop block comments on gripper grav-comp/friction zero slots and sim grav-comp factor - i2rt/robots/motor_chain_robot.py: drop block comments on grav_comp_kd defaults, coulomb_friction defaults, zero_gravity_mode kd seeding, and friction-comp deadband; inline param comments and docstrings retained - i2rt/robots/sim_robot.py: drop "Physics simulation state" divider and grav-comp race-condition note - i2rt/utils/mujoco_control_interface.py: drop block comments on viewer-handle lifetime, lock atomicity, sim grav-comp toggles, _log thread-safety, and _control_loop sub-section markers; preserves pre-existing "Seed sliders" comment - i2rt/utils/viser_control_interface.py: drop block comments on scratch MjData and main-loop grav-comp transition rationale Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * style(big_yam): match link colors to yam/yam_pro/yam_ultra - i2rt/robot_models/arm/big_yam/big_yam.xml: updated base and link1-link5 rgba values to match the shared yam family palette (purple base, tan link1, blue link2, olive link3, gray-tan link4, pink link5) for visual consistency across arm variants Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(control-with-mujoco): drop per-command joint log spam - i2rt/utils/mujoco_control_interface.py: remove unconditional `logger.info("joint command: ...")` and `logger.info("IK joint command: ...")` from `_control_loop()`; they fired on every slider/mocap update and shredded the structured `--log` table. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(grav-comp): drop passive encoder script changes from PR - scripts/run_gello_with_passive_encoder.py: revert to main; this script's edits are out of scope for the gravity-comp PR Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * chore(robots/config): remove redundant block comments - i2rt/robots/config/big_yam.yml: drop multi-line grav_comp_kd and coulomb_friction explanation blocks - i2rt/robots/config/crank_4310.yml: drop multi-line last_joint_mount header comment - i2rt/robots/config/flexible_4310.yml: drop multi-line last_joint_mount header comment - i2rt/robots/config/linear_3507.yml: drop multi-line last_joint_mount header comment - i2rt/robots/config/linear_4310.yml: drop multi-line last_joint_mount header comment - i2rt/robots/config/no_gripper.yml: drop multi-line last_joint_mount header comment - i2rt/robots/config/yam.yml: drop multi-line grav_comp_kd and coulomb_friction explanation blocks - i2rt/robots/config/yam_pro.yml: drop multi-line grav_comp_kd and coulomb_friction explanation blocks - i2rt/robots/config/yam_teaching_handle.yml: drop multi-line last_joint_mount header comment - i2rt/robots/config/yam_ultra.yml: drop multi-line grav_comp_kd and coulomb_friction explanation blocks Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
… threaded mujoco - README.md: add Coulomb friction + threaded mujoco to Features; new "Gravity & friction compensation" subsection under YAM Arm pointing at the new guide - docs/guides/gravity-compensation.md: new guide covering the τ = τ_PD + g·gravity_comp_factor + coulomb_friction·sign(q_dot) formula, per-arm YAML knobs with defaults from yam.yml, runtime override, enter_gravity_comp_idle semantics, sim parity, tuning workflow, and troubleshooting table - docs/releases/v1.1.1.md: new patch release notes covering grav_comp_kd, coulomb_friction, enter_gravity_comp_idle(), SimRobot physics thread, and the threaded mujoco control loop - docs/releases/v1.0.md → v1.0.0.md, v1.1.md → v1.1.0.md: rename to semver vX.Y.Z; update H1 only - docs/sdk/yam-arm.md: document enter_gravity_comp_idle(); add "Per-Arm YAML Configuration" section listing kp/kd, gravity_comp_factor, grav_comp_kd, coulomb_friction - docs/examples/control-with-mujoco.md: clearer threaded-loop description (200Hz daemon, viewer.lock contention); expand SPACE-toggle behaviour to cover hardware vs sim physics thread; add See Also - docs/.vitepress/config.mjs: add Guides top-nav + sidebar block; rename release sidebar links to semver; point Releases nav at v1.1.1 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
- docs/guides/gravity-compensation.md: replace single get_robot.py command with motor_chain_robot.py, control_with_viser.py, and control_with_mujoco.py entry points so users can pick headless, Viser, or MuJoCo grav-comp idle workflows Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds gravity + Coulomb friction compensation, sim-side gravity comp, a threaded mujoco control loop, and self-collision gating for the viser interface. Tuned per-arm
grav_comp_kdandcoulomb_frictionfor yam, yam_pro, yam_ultra, and big_yam after hardware validation.Changes
.gitignore: ignore*.mjbmujoco binary cache files.examples/control_with_mujoco/control_with_mujoco.py: split the script into arobot_worker+viewer_workerpair spawned viamultiprocessing, with the main process hosting only the IPC primitives (SharedMemory-backed numpy state, command Queue, stop Event). Isolates the 250 Hz CAN control loop from viewer/IK/rendering GIL contention.ProxyRobot/ProxyMotorChain/ProxyJointStatestubs forward theRobotsurfaceMujocoControlInterfaceuses; the publishedloop_hzmirrorsmotor_chain.comm_freq(fallback to a 1 sRateRecorder) so--logreports the real driver rate.i2rt/robot_models/arm/big_yam/big_yam.xml: update base + link1–link5 rgba values to match the shared yam family palette (purple base, tan link1, blue link2, olive link3, gray-tan link4, pink link5) for visual consistency.i2rt/robot_models/gripper/crank_4310/crank_4310.xml: no net mass change in this PR (briefly bumped, then reverted to 0.60366 kg).i2rt/robots/config/yam.yml: addgrav_comp_kd [0.1, 0.1, 0.1, 0.3, 0.05, 0.05]andcoulomb_friction [0.3, 0.3, 0.3, 0.06, 0.06, 0.06]; retunegravity_comp_factorafter friction-comp activation.i2rt/robots/config/yam_pro.yml: aligngravity_comp_factor,grav_comp_kd, andcoulomb_frictionwith yam/yam_ultra tuning.i2rt/robots/config/yam_ultra.yml: same tuning as yam_pro.i2rt/robots/config/big_yam.yml:grav_comp_kd [0.5, 0.5, 0.5, 0.3, 0.1, 0.1]and 0.1 Nmcoulomb_frictionon joints 0–1 (J4 weighting matches its larger wrist moment arm).i2rt/robots/config/{crank_4310,flexible_4310,linear_3507,linear_4310,no_gripper,yam_teaching_handle}.yml: drop multi-linelast_joint_mountblock comments.i2rt/robots/get_robot.py: loadhw.grav_comp_kdandhw.coulomb_friction, append0.0for the gripper slot (gripper is position-commanded, not gravity-balanced), and pass both intoMotorChainRobot. Pass unitgravity_comp_factortoSimRobotso sim uses exact model-based comp.i2rt/robots/motor_chain_robot.py: acceptgrav_comp_kdandcoulomb_frictionkwargs, store with length asserts, seed_commands.kdfromgrav_comp_kdonly whenzero_gravity_mode=True, applycoulomb_friction * sign(q_dot)alongside gravity comp inupdate(), expose both inget_robot_info(). Addenter_gravity_comp_idle()that resets_commandsto zeros withkd=self._grav_comp_kdso CONTROL→VIS toggles re-enter idle damping cleanly without rewriting cached_kp/_kd.i2rt/robots/sim_robot.py: add a daemon physics thread that runs gravity compensation against the mujoco model, withenable_gravity_comp/disable_gravity_comptoggles, cmd ↔mj_qposmapping, wall-clock-relative sleep at 200 Hz, and clean shutdown inclose().i2rt/robots/utils.py: addgrav_comp_kdandcoulomb_frictionndarray fields to_ArmHWConfig, parse with non-negativity asserts and logging in_load_arm_config.i2rt/utils/mujoco_control_interface.py: movesliders/mocap → IK → collision → command_joint_posinto a daemon control thread atcontrol_dtcadence; guard sharedMjDatawithviewer.lock()and only hold the lock for brief snapshot/write-back sections so the viewer never stalls commands. Start sim physics onrun(), default to VIS in sim, toggle grav-comp on SPACE between VIS and CONTROL, and drop per-commandjoint command:log spam.i2rt/utils/viser_control_interface.py: add a scratch_check_dataMjDatabuffer and_has_self_collisionso IK and joint-slider modes refuse commands that would self-collide. Refactor_denormalize_slide_joints/_enforce_eq_constraintsinto_on(data)variants so the collision check writes to_check_datawithout corrupting render state. Add_enter_vis_grav_comp/_enter_control_grav_comphelpers (hasattr dispatch:SimRobot.enable/disable_gravity_comp,MotorChainRobot.enter_gravity_comp_idle) and detect VIS↔CONTROL transitions in the main loop instead of from the GUI callback (avoids races with in-flightcommand_joint_poscalls).Test Plan
git fetch origin && git checkout feat/grav-comp-friction-threaded-mujoco && uv sync.uv run python examples/control_with_mujoco/control_with_mujoco.py --robot yam --simand confirm the viewer opens in VIS mode by default.--logprints aloop_hznear the expected control rate (≈250 Hz).uv run python examples/control_with_mujoco/control_with_mujoco.py --robot yamand confirm the arm enters gravity-comp idle on startup (you can hand-guide each joint with smooth settling, no chatter).--robot yam_pro,--robot yam_ultra, and--robot big_yam. Confirm joint settling is smooth with the newgrav_comp_kd/coulomb_frictionvalues.uv run python examples/control_with_viser/control_with_viser.py --robot yam --sim). Drag the IK target into a self-colliding pose and confirm the arm refuses the command (joints clamp at the last safe pose).q_dotsign and the arm doesn't lurch when reversing.uv run pytest.🤖 Generated with Claude Code