First Commit

This commit is contained in:
meiqi
2026-03-27 16:10:51 +08:00
commit c45245038f
103 changed files with 10994 additions and 0 deletions

View File

@@ -0,0 +1,163 @@
"""
Robot Data Structure
Python equivalent of the C++ RobotData class
"""
import numpy as np
from scipy.spatial.transform import Rotation
from common.joystick import ControlFlag
import copy
class RobotData:
"""机器人状态数据结构"""
def __init__(self, motor_num: int = 29, whole_joint_num: int = 35):
self.motor_num = motor_num
self.whole_joint_num = whole_joint_num
# Joint states (actual)
self.q_a_ = np.zeros(whole_joint_num) # Joint positions
self.q_dot_a_ = np.zeros(whole_joint_num) # Joint velocities
self.tau_a_ = np.zeros(whole_joint_num) # Joint torques
self.temperature_a = np.zeros(motor_num) # Joint temperatures
self.q_a_last = np.zeros(whole_joint_num) # 上一时刻关节位置
self.qdot_a_last = np.zeros(whole_joint_num) # 上一时刻关节速度
self.tor_a_last = np.zeros(whole_joint_num) # 上一时刻关节力矩
# Joint commands (desired)
self.q_d_ = np.zeros(whole_joint_num) # Desired joint positions
self.q_d_s_ = np.zeros(whole_joint_num) # Desired serial joint positions
self.q_dot_d_ = np.zeros(whole_joint_num) # Desired joint velocities
self.tau_d_ = np.zeros(whole_joint_num) # Desired joint torques
# Control gains
self.joint_kp_p_ = np.zeros(motor_num) # Proportional gains
self.joint_kd_p_ = np.zeros(motor_num) # Derivative gains
# IMU data: [yaw, pitch, roll, gyro_x, gyro_y, gyro_z, acc_x, acc_y, acc_z]
self.imu_data_ = np.zeros(13)
self.imu_quat_ = np.array([1.0, 0.0, 0.0, 0.0], dtype=np.float32) # w, x, y, z
# Timing
self.time_now_ = 0.0
# Configuration
self.config_file_ = ""
# control cmd
# walk command
self.walk_cmd_ = np.zeros(3) # x_speed, y_speed, yaw_speed
# 控制符
self.control_flag = ControlFlag()
def copy_from(self, other: 'RobotData'):
"""从另一个RobotData对象复制数据"""
self.q_a_[:] = other.q_a_[:]
self.q_dot_a_[:] = other.q_dot_a_[:]
self.tau_a_[:] = other.tau_a_[:]
self.q_d_[:] = other.q_d_[:]
self.q_dot_d_[:] = other.q_dot_d_[:]
self.tau_d_[:] = other.tau_d_[:]
self.joint_kp_p_[:] = other.joint_kp_p_[:]
self.joint_kd_p_[:] = other.joint_kd_p_[:]
self.imu_data_[:] = other.imu_data_[:]
self.imu_quat_[:] = other.imu_quat_[:]
self.time_now_ = other.time_now_
self.config_file_ = other.config_file_
self.walk_cmd_[:] = other.walk_cmd_[:]
self.control_flag = copy.deepcopy(other.control_flag)
def get_joint_pos(self) -> np.ndarray:
joint_start_idx = 35 - self.motor_num
joint_pos = self.q_a_[joint_start_idx:].astype(np.float32)
return joint_pos
def get_serial_joint_pos_desired(self) -> np.ndarray:
joint_start_idx = 35 - self.motor_num
joint_pos_desired = self.q_d_s_[joint_start_idx:].astype(np.float32)
return joint_pos_desired
def get_joint_vel(self)-> np.ndarray:
joint_start_idx = 35 - self.motor_num
joint_vel = self.q_dot_a_[joint_start_idx:].astype(np.float32)
return joint_vel
def get_angular_velocity(self) -> np.ndarray:
omega_xyz = np.array([
self.imu_data_[3],
self.imu_data_[4],
self.imu_data_[5]
], dtype=np.float32)
return omega_xyz
def get_robot_quat(self):
if np.linalg.norm(self.imu_quat_) > 0.0:
return self.imu_quat_.astype(np.float32)
rpy = np.array([
self.imu_data_[2], # roll
self.imu_data_[1], # pitch
self.imu_data_[0] # yaw
], dtype=np.float32) * 1.0
robot_quat_wxyz = self.euler_to_quaternion_scipy(rpy[0], rpy[1], rpy[2])
return robot_quat_wxyz
def euler_to_quaternion_scipy(self, roll, pitch, yaw, degrees=False):
"""
使用SciPy进行欧拉角转四元数
参数:
roll: 绕x轴的旋转角度
pitch: 绕y轴的旋转角度
yaw: 绕z轴的旋转角度
degrees: 输入角度是否为度,默认为弧度
返回:
[w, x, y, z]: 四元数分量 (w为实部)
"""
# 创建旋转对象 (顺序: 'xyz' 对应 roll, pitch, yaw)
rotation = Rotation.from_euler('xyz', [roll, pitch, yaw], degrees=degrees)
# 转换为四元数 (顺序: [x, y, z, w])
quaternion = rotation.as_quat()
return [quaternion[3], quaternion[0], quaternion[1], quaternion[2]] # 返回 w, x, y, z
def get_waist_yrp(self) -> np.ndarray:
joint_pos = self.get_joint_pos()
waist_yaw, waist_roll, waist_pitch = joint_pos[12], joint_pos[13], joint_pos[14]
return np.array([waist_yaw, waist_roll, waist_pitch], dtype=np.float32)
def get_base_linear_acceleration(self) -> np.ndarray:
lin_acc = np.array([
self.imu_data_[6],
self.imu_data_[7],
self.imu_data_[8]
], dtype=np.float32)
return lin_acc
def get_project_gravity(self) -> np.ndarray:
"""根据机器人姿态重力投影(待完善)
Args:
None
"""
robot_quat_wxyz = self.get_robot_quat()
robot_quat_xyzw = np.array([robot_quat_wxyz[1], robot_quat_wxyz[2], robot_quat_wxyz[3], robot_quat_wxyz[0]])
g = np.array([0., 0., -1.])
projected_gravity = self.quat_rotate_inverse_numpy(robot_quat_xyzw, g)
return projected_gravity
def quat_rotate_inverse_numpy(self, q, v):
"""
q: [x, y, z, w], shape=(4)\\
v: [x, y, z], shape=(3)
"""
q_w = q[3]
q_vec = q[:3]
a = v * (2.0 * q_w ** 2 - 1.0)
b = np.cross(q_vec, v) * q_w * 2.0
c = q_vec * np.dot(q_vec, v) * 2.0
return a - b + c
def get_walk_cmd(self) -> np.ndarray:
"""获取行走命令: [x_speed, y_speed, yaw_speed]"""
return self.walk_cmd_