双臂烘箱调整

This commit is contained in:
2026-03-14 20:45:41 +08:00
parent 1afdf9c7f7
commit 763e555862
8 changed files with 275 additions and 56 deletions

View File

@@ -44,8 +44,10 @@ parser.add_argument(
parser.add_argument("--pos_sensitivity", type=float, default=None, help="Position sensitivity. Default: 1.0.")
parser.add_argument("--rot_sensitivity", type=float, default=None, help="Rotation sensitivity. Default: 0.3.")
parser.add_argument("--arm", type=str, default="left", choices=["left", "right"], help="Which arm/controller to use.")
parser.add_argument("--base_speed", type=float, default=3.0, help="Max wheel speed (rad/s) for joystick full forward.")
parser.add_argument("--base_speed", type=float, default=5.0, help="Max wheel speed (rad/s) for joystick full forward.")
parser.add_argument("--base_turn", type=float, default=2.0, help="Max wheel differential (rad/s) for joystick full left/right.")
parser.add_argument("--drive_speed", type=float, default=0.5, help="Max robot linear speed (m/s) for direct base control. Default: 0.5")
parser.add_argument("--drive_turn", type=float, default=1.5, help="Max robot yaw rate (rad/s) for direct base control. Default: 1.5")
AppLauncher.add_app_launcher_args(parser)
args_cli = parser.parse_args()
@@ -392,19 +394,54 @@ def main() -> None:
out[3:7] = torch.tensor(quat_root, dtype=torch.float32)
return out
def get_wheel_action() -> torch.Tensor:
"""Read left joystick → 4-DOF wheel velocity [right_b, left_b, left_f, right_f]."""
def get_chassis_commands() -> tuple[torch.Tensor, float, float]:
"""Read left joystick → (wheel_cmd 4D, v_fwd m/s, omega rad/s).
wheel_cmd : differential wheel velocities for the action vector (training data).
v_fwd : desired robot forward speed in m/s (for direct base control).
omega : desired robot yaw rate in rad/s (for direct base control).
"""
try:
joy = teleop_interface.xr_client.get_joystick("left")
jy = float(joy[1])
jx = float(joy[0])
except Exception:
return torch.zeros(4)
v = jy * args_cli.base_speed
omega = jx * args_cli.base_turn
right_vel = v - omega
left_vel = v + omega
return torch.tensor([right_vel, left_vel, left_vel, right_vel], dtype=torch.float32)
return torch.zeros(4), 0.0, 0.0
# Wheel velocity commands for action vector (rad/s)
v_w = jy * args_cli.base_speed
omega_w = jx * args_cli.base_turn
right_vel = v_w - omega_w
left_vel = v_w + omega_w
wheel_cmd = torch.tensor([right_vel, left_vel, left_vel, right_vel], dtype=torch.float32)
if abs(v_w) > 0.1 or abs(omega_w) > 0.1:
print(f"[WHEEL] joy=({jx:+.2f},{jy:+.2f}) v_wheel={v_w:.2f} ω_wheel={omega_w:.2f}{wheel_cmd.tolist()}")
# Direct base velocity commands (m/s, rad/s)
v_fwd = jy * args_cli.drive_speed
omega = -jx * args_cli.drive_turn # jx<0 (left push) → positive yaw = left turn
return wheel_cmd, v_fwd, omega
def apply_base_velocity(v_fwd: float, omega: float) -> None:
"""Directly set robot root linear+angular velocity to bypass isotropic friction.
PhysX uses isotropic friction, so skid-steer lateral slip is impossible through
wheel torques alone. This function overrides the base velocity each step to give
clean translational + rotational motion regardless of friction.
The write is buffered and applied at the start of the next env.step().
"""
if abs(v_fwd) < 1e-4 and abs(omega) < 1e-4:
return
robot = env.unwrapped.scene["robot"]
rq = robot.data.root_quat_w # [N, 4] wxyz
w_q, x_q, y_q, z_q = rq[:, 0], rq[:, 1], rq[:, 2], rq[:, 3]
# Robot forward direction in world frame (rotate [1,0,0] by root quaternion)
fwd_x = 1.0 - 2.0 * (y_q * y_q + z_q * z_q)
fwd_y = 2.0 * (x_q * y_q + w_q * z_q)
vel = torch.zeros(env.num_envs, 6, device=device)
vel[:, 0] = v_fwd * fwd_x # world x linear
vel[:, 1] = v_fwd * fwd_y # world y linear
# vel[:, 2] = 0 # z: let physics handle gravity/contact
vel[:, 5] = omega # world z angular (yaw)
robot.write_root_velocity_to_sim(vel)
obs, _ = env.reset()
clear_ik_target_state()
@@ -446,7 +483,7 @@ def main() -> None:
continue
policy_obs = obs["policy"]
wheel_np = get_wheel_action()
wheel_np, v_fwd, omega_base = get_chassis_commands()
if is_dual_arm:
eef_pos_left = policy_obs["eef_pos_left"][0].cpu().numpy()
@@ -482,6 +519,9 @@ def main() -> None:
actions = action_np.unsqueeze(0).repeat(env.num_envs, 1).to(device)
obs, _, _, _, _ = env.step(actions)
# Direct base velocity override: bypasses isotropic friction limitation
# so skid-steer turning works correctly.
apply_base_velocity(v_fwd, omega_base)
sim_frame += 1
if sim_frame % 30 == 0: