147 lines
4.1 KiB
Python
Raw Permalink Normal View History

2025-07-28 12:35:44 +08:00
# run sin motion joints, get command vs data
# in mujoco and on real robot
import argparse
import os
import pickle
import time
import mujoco
import mujoco_viewer
import numpy as np
from mini_bdx_runtime.hwi import HWI
from mini_bdx_runtime.rl_utils import (
ActionFilter,
make_action_dict,
mujoco_joints_order,
)
from utils import dof_to_id, id_to_dof, mujoco_init_pos
parser = argparse.ArgumentParser()
parser.add_argument("--dof", type=str, default="left_ankle")
parser.add_argument("--move_freq", type=float, default=10)
parser.add_argument("--move_amp", type=float, default=0.5)
parser.add_argument("--ctrl_freq", type=float, default=30)
parser.add_argument("--sampling_freq", type=float, default=100)
parser.add_argument("--duration", type=float, default=5)
parser.add_argument("--save_dir", type=str, default="./data")
parser.add_argument("--saved_actions", type=str, required=False)
args = parser.parse_args()
if args.saved_actions is not None:
saved_actions = pickle.loads(open(args.saved_actions, "rb").read())
os.makedirs(args.save_dir, exist_ok=True)
dt = 0.001
assert args.dof in id_to_dof.values()
## === Init mujoco ===
# Commented freejoint
model = mujoco.MjModel.from_xml_path("../../mini_bdx/robots/bdx/scene.xml")
model.opt.timestep = dt
data = mujoco.MjData(model)
mujoco.mj_step(model, data)
viewer = mujoco_viewer.MujocoViewer(model, data)
data.qpos = mujoco_init_pos
data.ctrl[:] = mujoco_init_pos
mujoco_command_value = []
## === Init robot ===
hwi = HWI(usb_port="/dev/ttyUSB0")
time.sleep(1)
hwi.turn_on()
pid = [500, 0, 500]
hwi.set_pid_all(pid)
time.sleep(3)
robot_command_value = []
action_filter = ActionFilter(window_size=10)
prev = time.time()
last_control = time.time()
last_sample = time.time()
start = time.time()
if args.saved_actions is None:
last_target = 0
else:
last_target = np.zeros(15)
i = 0
while True:
t = time.time()
dt = t - prev
if t - last_control > 1 / args.ctrl_freq:
last_control = t
if args.saved_actions is None:
last_target = (
mujoco_init_pos[dof_to_id[args.dof]]
+ np.sin(2 * np.pi * args.move_freq * t) * args.move_amp
)
data.ctrl[dof_to_id[args.dof]] = last_target
action_filter.push(last_target)
filtered_action = action_filter.get_filtered_action()
hwi.set_position(args.dof, filtered_action)
else:
last_target = saved_actions[i]
data.ctrl[:] = last_target
action_dict = make_action_dict(last_target, mujoco_joints_order)
hwi.set_position_all(action_dict)
mujoco.mj_step(model, data, 5)
if t - last_sample > 1 / args.sampling_freq:
last_sample = t
mujoco_command_value.append(
[
data.ctrl[:].copy(),
data.qpos[:].copy(),
]
)
if args.saved_actions is None:
last_robot_command = np.zeros(15)
print(last_target)
last_robot_command[dof_to_id[args.dof]] = last_target
else:
last_robot_command = last_target
robot_command_value.append(
[
last_robot_command,
list(hwi.get_present_positions()) + [0, 0],
]
)
mujoco_dof_vel = np.around(data.qvel[dof_to_id[args.dof]], 3)
robot_dof_vel = np.around(hwi.get_present_velocities()[dof_to_id[args.dof]], 3)
print(mujoco_dof_vel, robot_dof_vel)
i += 1
if t - start > args.duration:
break
if args.saved_actions is not None:
if i > len(saved_actions) - 1:
break
viewer.render()
prev = t
path = os.path.join(args.save_dir, f"{args.dof}.pkl")
data_dict = {
"config": {
"dof": args.dof,
"move_freq": args.move_freq,
"move_amp": args.move_amp,
"ctrl_freq": args.ctrl_freq,
"sampling_freq": args.sampling_freq,
"duration": args.duration,
},
"mujoco": mujoco_command_value,
"robot": robot_command_value,
}
pickle.dump(data_dict, open(path, "wb"))
print("saved to", path)