LiangShiyun af42d0c71b stash
2025-06-12 20:06:35 +08:00

152 lines
6.9 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import sys
import numpy as np
from scipy.spatial.transform import Rotation as R
from .arm_state import ArmState
from .base_controller import BaseController
from pathlib import Path
sys.path.append(str(Path(__file__).resolve().parent.parent))
from tools.yaml_operator import read_yaml
import time
class HybridAdmitController(BaseController):
def __init__(self, name, state: ArmState,config_path) -> None:
super().__init__(name, state)
self.load_config(config_path)
self.laset_print_time = 0
def load_config(self, config_path):
config_dict = read_yaml(config_path)
if self.name != config_dict['name']:
raise ValueError(f"Controller name {self.name} does not match config name {config_dict['name']}")
# 姿态调节器
# 位控 2x2矩阵
self.Kp_R = np.diag(np.array(config_dict['Kp_R']))
self.Ki_R = np.diag(np.array(config_dict['Ki_R']))
self.Kd_R = np.diag(np.array(config_dict['Kd_R']))
mass_rot = np.array(config_dict['mass_z'])
stiff_rot = np.array(config_dict['stiff_z'])
desired_xi = np.array(config_dict['desired_xi'])
damp_rot = np.array(config_dict['damp_z'])
self.D_z_min = 10.0
self.D_z_max = 100.0
self.D_z_lambda = 5.0
self.M_z = np.diag(mass_rot)
self.K_z = np.diag(stiff_rot)
self.D_z = np.diag(damp_rot)
# 位控 2x2矩阵
self.Kp = np.diag(np.array(config_dict['Kp']))
self.Ki = np.diag(np.array(config_dict['Ki']))
self.Kd = np.diag(np.array(config_dict['Kd']))
self.pose_integral_error = np.zeros(6)
def step(self,dt):
# 方向统一
if self.state.desired_orientation.dot(self.state.arm_orientation) < 0:
self.state.arm_orientation = -self.state.arm_orientation
# 缓存常用计算
arm_ori_quat = R.from_quat(self.state.arm_orientation)
arm_ori_mat = arm_ori_quat.as_matrix()
# 位置误差
temp_pose_error = self.state.arm_position - self.state.desired_position
self.state.pose_error[:3] = arm_ori_mat.T @ temp_pose_error
# 姿态误差(四元数)
rot_err_quat = arm_ori_quat.inv() * R.from_quat(self.state.desired_orientation)
self.state.pose_error[3:] = -rot_err_quat.as_rotvec(degrees=False)
# 期望加速度
wrench_err = self.state.external_wrench_tcp - self.state.desired_wrench
# z方向力导纳控制
self.state.arm_desired_acc[2] = 1/self.M_z * (wrench_err[2] - self.D_z * (self.state.arm_desired_twist[2] - self.state.desired_twist[2]) - self.K_z * self.state.pose_error[2])
# print("self.state.arm_desired_acc[2]:",self.state.arm_desired_acc[2],self.M_z,wrench_err[2],self.K_z,self.D_z)
self.pose_integral_error += self.state.pose_error * dt
# 位控制
self.state.arm_desired_acc[:2] = -self.Kd @ self.state.arm_desired_twist[:2] - self.Kp @ self.state.pose_error[:2] - self.Ki @ self.pose_integral_error[:2]
# 姿态pid
self.state.arm_desired_acc[3:] = -self.Kd_R @ self.state.arm_desired_twist[3:] - self.Kp_R @ self.state.pose_error[3:] - self.Ki_R @ self.pose_integral_error[3:]
self.clip_command(self.state.arm_desired_acc, "acc")
## 更新速度和位姿
self.state.arm_desired_twist += self.state.arm_desired_acc * dt
self.clip_command(self.state.arm_desired_twist, "vel")
# 计算位姿变化
delta_pose = np.concatenate([
arm_ori_mat @ (self.state.arm_desired_twist[:3] * dt),
self.state.arm_desired_twist[3:] * dt
])
self.clip_command(delta_pose, "pose")
# 更新四元数
delta_ori_quat = R.from_rotvec(delta_pose[3:]).as_quat()
arm_ori_quat_new = arm_ori_quat * R.from_quat(delta_ori_quat)
self.state.arm_orientation_command = arm_ori_quat_new.as_quat()
# 归一化四元数
self.state.arm_orientation_command /= np.linalg.norm(self.state.arm_orientation_command)
# 更新位置
self.state.arm_position_command = self.state.arm_position + delta_pose[:3]
def step_traj(self,dt):
# 方向统一
if self.state.desired_orientation.dot(self.state.arm_orientation) < 0:
self.state.arm_orientation = -self.state.arm_orientation
# 缓存常用计算
arm_ori_quat = R.from_quat(self.state.arm_orientation)
arm_ori_mat = arm_ori_quat.as_matrix()
# 位置误差
temp_pose_error = self.state.arm_position - self.state.desired_position + self.state.desired_twist[:3] * dt
self.state.pose_error[:3] = arm_ori_mat.T @ temp_pose_error
# 姿态误差(四元数)
angular_velocity = np.array(self.state.desired_twist[3:]) # 形状 (3,)
# 用旋转向量(小角度近似)
rotvec = angular_velocity * dt # 旋转向量 = 角速度 × 时间
rot_quat = R.from_rotvec(rotvec).as_quat() # 转成四元数,形状 (4,)
rot_err_quat = R.from_quat(rot_quat).inv() * arm_ori_quat.inv() * R.from_quat(self.state.desired_orientation)
self.state.pose_error[3:] = -rot_err_quat.as_rotvec(degrees=False)
# 期望加速度
wrench_err = self.state.external_wrench_tcp - self.state.desired_wrench
# z方向力导纳控制
self.state.arm_desired_acc[2] = 1/self.M_z * (wrench_err[2] - self.D_z * (self.state.arm_desired_twist[2] - self.state.desired_twist[2] + self.state.desired_acc[2]*dt) - self.K_z * self.state.pose_error[2]) + self.state.desired_acc[2]
self.pose_integral_error += self.state.pose_error * dt
# 位控制
self.state.arm_desired_acc[:2] = -self.Kd @ self.state.arm_desired_twist[:2] - self.Kp @ self.state.pose_error[:2] - self.Ki @ self.pose_integral_error[:2]
# 姿态pid
self.state.arm_desired_acc[3:] = -self.Kd_R @ self.state.arm_desired_twist[3:] - self.Kp_R @ self.state.pose_error[3:] - self.Ki_R @ self.pose_integral_error[3:]
self.clip_command(self.state.arm_desired_acc, "acc")
## 更新速度和位姿
self.state.arm_desired_twist += self.state.arm_desired_acc * dt
self.clip_command(self.state.arm_desired_twist, "vel")
# 计算位姿变化
delta_pose = np.concatenate([
arm_ori_mat @ (self.state.arm_desired_twist[:3] * dt),
self.state.arm_desired_twist[3:] * dt
])
self.clip_command(delta_pose, "pose")
# 更新四元数
delta_ori_quat = R.from_rotvec(delta_pose[3:]).as_quat()
arm_ori_quat_new = arm_ori_quat * R.from_quat(delta_ori_quat)
self.state.arm_orientation_command = arm_ori_quat_new.as_quat()
# 归一化四元数
self.state.arm_orientation_command /= np.linalg.norm(self.state.arm_orientation_command)
# 更新位置
self.state.arm_position_command = self.state.arm_position + delta_pose[:3]