mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-23 17:56:07 +00:00
Add rerun vis
This commit is contained in:
@@ -8,9 +8,11 @@ import numpy as np
|
|||||||
from lerobot.robots.so101_follower_torque.config_so101_follower_t import SO101FollowerTConfig
|
from lerobot.robots.so101_follower_torque.config_so101_follower_t import SO101FollowerTConfig
|
||||||
from lerobot.robots.so101_follower_torque.so101_follower_t import SO101FollowerT
|
from lerobot.robots.so101_follower_torque.so101_follower_t import SO101FollowerT
|
||||||
from lerobot.utils.robot_utils import busy_wait
|
from lerobot.utils.robot_utils import busy_wait
|
||||||
|
from lerobot.utils.visualization_utils import _init_rerun, log_rerun_data
|
||||||
|
|
||||||
FRQ = 300
|
FRQ = 300
|
||||||
PRINT_HZ = 10
|
PRINT_HZ = 10
|
||||||
|
RERUN_HZ = 100
|
||||||
ESC_CLR_EOL = "\x1b[K"
|
ESC_CLR_EOL = "\x1b[K"
|
||||||
CURSOR_UP = "\x1b[F"
|
CURSOR_UP = "\x1b[F"
|
||||||
|
|
||||||
@@ -27,12 +29,12 @@ def to_cmd(tau_vec, joints):
|
|||||||
|
|
||||||
follower_cfg = SO101FollowerTConfig(
|
follower_cfg = SO101FollowerTConfig(
|
||||||
port="/dev/tty.usbmodem58760431551",
|
port="/dev/tty.usbmodem58760431551",
|
||||||
id="my_awesome_follower_arm",
|
id="follower_arm_t",
|
||||||
)
|
)
|
||||||
|
|
||||||
leader_cfg = SO101FollowerTConfig(
|
leader_cfg = SO101FollowerTConfig(
|
||||||
port="/dev/tty.usbmodem58760428721",
|
port="/dev/tty.usbmodem58760428721",
|
||||||
id="my_awesome_leader_arm",
|
id="leader_arm_t",
|
||||||
)
|
)
|
||||||
|
|
||||||
follower = SO101FollowerT(follower_cfg)
|
follower = SO101FollowerT(follower_cfg)
|
||||||
@@ -43,11 +45,18 @@ leader.connect()
|
|||||||
exec_f = ThreadPoolExecutor(max_workers=1)
|
exec_f = ThreadPoolExecutor(max_workers=1)
|
||||||
exec_l = ThreadPoolExecutor(max_workers=1)
|
exec_l = ThreadPoolExecutor(max_workers=1)
|
||||||
|
|
||||||
|
# Initialize Rerun for visualization
|
||||||
|
_init_rerun("bilateral_teleoperation")
|
||||||
|
|
||||||
print("Starting 4-channel bilateral teleoperation")
|
print("Starting 4-channel bilateral teleoperation")
|
||||||
first_print = True
|
first_print = True
|
||||||
loop_count = 0
|
loop_count = 0
|
||||||
tic_prev = time.perf_counter()
|
tic_prev = time.perf_counter()
|
||||||
|
|
||||||
|
# Initialize previous positions for velocity calculation
|
||||||
|
pos_f_prev = None
|
||||||
|
pos_l_prev = None
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
tic = time.perf_counter()
|
tic = time.perf_counter()
|
||||||
|
|
||||||
@@ -64,17 +73,32 @@ while True:
|
|||||||
tau_cmd_f, tau_cmd_l = [], []
|
tau_cmd_f, tau_cmd_l = [], []
|
||||||
debug_info_f, debug_info_l = {}, {}
|
debug_info_f, debug_info_l = {}, {}
|
||||||
|
|
||||||
|
# Collect torques with deterministic components removed for model
|
||||||
|
tau_interaction_l = {}
|
||||||
|
tau_interaction_f = {}
|
||||||
|
|
||||||
# Collect data for all motors
|
# Collect data for all motors
|
||||||
pos_f = {j: obs_f[f"{j}.pos"] for j in follower.bus.motors}
|
pos_f = {j: obs_f[f"{j}.pos"] for j in follower.bus.motors}
|
||||||
vel_f = {j: obs_f[f"{j}.vel"] for j in follower.bus.motors}
|
|
||||||
acc_f = {j: obs_f[f"{j}.acc"] for j in follower.bus.motors}
|
acc_f = {j: obs_f[f"{j}.acc"] for j in follower.bus.motors}
|
||||||
tau_meas_f = {j: obs_f[f"{j}.tau_meas"] for j in follower.bus.motors}
|
tau_meas_f = {j: obs_f[f"{j}.tau_meas"] for j in follower.bus.motors}
|
||||||
|
|
||||||
pos_l = {j: obs_l[f"{j}.pos"] for j in leader.bus.motors}
|
pos_l = {j: obs_l[f"{j}.pos"] for j in leader.bus.motors}
|
||||||
vel_l = {j: obs_l[f"{j}.vel"] for j in leader.bus.motors}
|
|
||||||
acc_l = {j: obs_l[f"{j}.acc"] for j in leader.bus.motors}
|
acc_l = {j: obs_l[f"{j}.acc"] for j in leader.bus.motors}
|
||||||
tau_meas_l = {j: obs_l[f"{j}.tau_meas"] for j in leader.bus.motors}
|
tau_meas_l = {j: obs_l[f"{j}.tau_meas"] for j in leader.bus.motors}
|
||||||
|
|
||||||
|
# Calculate velocities from position differences
|
||||||
|
if pos_f_prev is not None and pos_l_prev is not None:
|
||||||
|
vel_f = {j: (pos_f[j] - pos_f_prev[j]) / dt for j in follower.bus.motors}
|
||||||
|
vel_l = {j: (pos_l[j] - pos_l_prev[j]) / dt for j in leader.bus.motors}
|
||||||
|
else:
|
||||||
|
# First iteration: initialize with zeros
|
||||||
|
vel_f = dict.fromkeys(follower.bus.motors, 0.0)
|
||||||
|
vel_l = dict.fromkeys(leader.bus.motors, 0.0)
|
||||||
|
|
||||||
|
# Update previous positions for next iteration
|
||||||
|
pos_f_prev = pos_f.copy()
|
||||||
|
pos_l_prev = pos_l.copy()
|
||||||
|
|
||||||
# Compute reaction torques using model-based approach
|
# Compute reaction torques using model-based approach
|
||||||
tau_reaction_f = follower._compute_model_based_disturbance(pos_f, vel_f, acc_f, tau_meas_f)
|
tau_reaction_f = follower._compute_model_based_disturbance(pos_f, vel_f, acc_f, tau_meas_f)
|
||||||
tau_reaction_l = leader._compute_model_based_disturbance(pos_l, vel_l, acc_l, tau_meas_l)
|
tau_reaction_l = leader._compute_model_based_disturbance(pos_l, vel_l, acc_l, tau_meas_l)
|
||||||
@@ -87,8 +111,8 @@ while True:
|
|||||||
inertia_f = follower._inertia_from_q_dq(pos_f, vel_f, acc_f)
|
inertia_f = follower._inertia_from_q_dq(pos_f, vel_f, acc_f)
|
||||||
inertia_l = leader._inertia_from_q_dq(pos_l, vel_l, acc_l)
|
inertia_l = leader._inertia_from_q_dq(pos_l, vel_l, acc_l)
|
||||||
|
|
||||||
Kp = 5.0 # Position gain
|
Kp = 8.0 # Position gain
|
||||||
Kd = 0.1 # Velocity gain
|
Kd = 0.5 # Velocity gain
|
||||||
Kf = 0.05 # Force reflection gain
|
Kf = 0.05 # Force reflection gain
|
||||||
|
|
||||||
# Friction compensation parameters (feedforward)
|
# Friction compensation parameters (feedforward)
|
||||||
@@ -151,6 +175,12 @@ while True:
|
|||||||
tau_cmd_f.append(tau_ref_f)
|
tau_cmd_f.append(tau_ref_f)
|
||||||
tau_cmd_l.append(tau_ref_l)
|
tau_cmd_l.append(tau_ref_l)
|
||||||
|
|
||||||
|
# Store interaction torques (cmd minus deterministic components) for model
|
||||||
|
tau_interaction_l[j] = tau_ref_l - grav_l[j] - inertia_l[j] - tau_friction_l
|
||||||
|
tau_interaction_f[j] = -(
|
||||||
|
tau_meas_f[j] - grav_f[j] - inertia_f[j] - tau_friction_f
|
||||||
|
) # Invert to match leader
|
||||||
|
|
||||||
# Store debug info
|
# Store debug info
|
||||||
debug_info_f[j] = {
|
debug_info_f[j] = {
|
||||||
"τ_measured": tau_meas_f[j],
|
"τ_measured": tau_meas_f[j],
|
||||||
@@ -182,8 +212,30 @@ while True:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Send torques to both arms
|
# Send torques to both arms
|
||||||
follower.send_action(to_cmd(np.array(tau_cmd_f), list(follower.bus.motors.keys())))
|
follower_action = to_cmd(np.array(tau_cmd_f), list(follower.bus.motors.keys()))
|
||||||
leader.send_action(to_cmd(np.array(tau_cmd_l), list(leader.bus.motors.keys())))
|
leader_action = to_cmd(np.array(tau_cmd_l), list(leader.bus.motors.keys()))
|
||||||
|
|
||||||
|
follower.send_action(follower_action)
|
||||||
|
leader.send_action(leader_action)
|
||||||
|
|
||||||
|
# Create structured observation and action for rerun
|
||||||
|
# Observation: follower side only (θ_f, ω_f, τ_ext)
|
||||||
|
observation = {
|
||||||
|
"follower_joint_angles": pos_f, # θ_f: current angles
|
||||||
|
"follower_angular_velocities": vel_f, # ω_f: current velocities
|
||||||
|
"follower_external_torques": tau_interaction_f, # τ_ext: measured minus deterministic components
|
||||||
|
}
|
||||||
|
|
||||||
|
# Action: leader targets (θ_leader[τ], ω_leader[τ], τ_leader[τ])
|
||||||
|
action = {
|
||||||
|
"leader_target_angles": pos_l, # θ_leader[τ]: absolute target angles
|
||||||
|
"leader_target_velocities": vel_l, # ω_leader[τ]: absolute target velocities
|
||||||
|
"leader_interaction_torques": tau_interaction_l, # τ_leader[τ]: cmd minus deterministic components
|
||||||
|
}
|
||||||
|
|
||||||
|
# Log data for visualization (100 Hz)
|
||||||
|
if loop_count % (FRQ // RERUN_HZ) == 0:
|
||||||
|
log_rerun_data(observation, action)
|
||||||
|
|
||||||
# Console diagnostics (10 Hz)
|
# Console diagnostics (10 Hz)
|
||||||
loop_count += 1
|
loop_count += 1
|
||||||
|
|||||||
Reference in New Issue
Block a user