8及12自由度四足机器人VMC(虚拟模型)控制代码

2 篇文章 3 订阅
1 篇文章 1 订阅

 代码算法参考知乎:华北舵狗王--华北舵狗王带你一起做四足机器人3(Moco-8四足机器人导航算法简介)

参考论文:四足机器人对角小跑步态虚拟模型直觉控制方法研究

代码结构参考知乎 :xyYu

效果视频:https://www.bilibili.com/video/BV18T4y157cq?from=search&seid=943344308179708495

代码如下:

如需引用,请注明出处:

"""VMC_test_py controller."""
##8自由度
from controller import Robot
import math
import numpy as np
import copy

# create the Robot instance.
robot = Robot()
timestep = int(1)

# 机器人所有马达
#   0  1  2  3
#   LF RF RB LB
# 0 跨 ........
# 1 髋 ........
# 2 膝 ........
robot_motor = []  # LF RF RB LB
for i in range(4):
    robot_motor.append([])
# 左前足马达
robot_motor[0].append(robot.createMotor("LFL0_rotational motor"))
robot_motor[0].append(robot.createMotor("LFL1_rotational motor"))
robot_motor[0].append(robot.createMotor("LFL2_rotational motor"))
# 右前足马达
robot_motor[1].append(robot.createMotor("RFL0_rotational motor"))
robot_motor[1].append(robot.createMotor("RFL1_rotational motor"))
robot_motor[1].append(robot.createMotor("RFL2_rotational motor"))
# 右后足马达
robot_motor[2].append(robot.createMotor("RBL0_rotational motor"))
robot_motor[2].append(robot.createMotor("RBL1_rotational motor"))
robot_motor[2].append(robot.createMotor("RBL2_rotational motor"))
# 左后足马达
robot_motor[3].append(robot.createMotor("LBL0_rotational motor"))
robot_motor[3].append(robot.createMotor("LBL1_rotational motor"))
robot_motor[3].append(robot.createMotor("LBL2_rotational motor"))

# 机器人所有位置传感器
#   0  1  2  3
#   LF RF RB LB
# 0 跨 ........
# 1 髋 ........
# 2 膝 ........
robot_pos_sensor = []  # LF RF RB LB
for i in range(4):
    robot_pos_sensor.append([])
# 左前足位置传感器
robot_pos_sensor[0].append(robot.createPositionSensor("LFL0_position sensor"))
robot_pos_sensor[0].append(robot.createPositionSensor("LFL1_position sensor"))
robot_pos_sensor[0].append(robot.createPositionSensor("LFL2_position sensor"))
# 右前足位置传感器
robot_pos_sensor[1].append(robot.createPositionSensor("RFL0_position sensor"))
robot_pos_sensor[1].append(robot.createPositionSensor("RFL1_position sensor"))
robot_pos_sensor[1].append(robot.createPositionSensor("RFL2_position sensor"))
# 右后足位置传感器
robot_pos_sensor[2].append(robot.createPositionSensor("RBL0_position sensor"))
robot_pos_sensor[2].append(robot.createPositionSensor("RBL1_position sensor"))
robot_pos_sensor[2].append(robot.createPositionSensor("RBL2_position sensor"))
# 左后足位置传感器
robot_pos_sensor[3].append(robot.createPositionSensor("LBL0_position sensor"))
robot_pos_sensor[3].append(robot.createPositionSensor("LBL1_position sensor"))
robot_pos_sensor[3].append(robot.createPositionSensor("LBL2_position sensor"))

# 触地传感器
# LF RF RB LB
robot_touch_sensor = []
robot_touch_sensor.append(robot.createTouchSensor("LF_touch sensor"))
robot_touch_sensor.append(robot.createTouchSensor("RF_touch sensor"))
robot_touch_sensor.append(robot.createTouchSensor("RB_touch sensor"))
robot_touch_sensor.append(robot.createTouchSensor("LB_touch sensor"))

# inertial unit
IMU = robot.createInertialUnit("inertial unit")
ACC = robot.createAccelerometer("accelerometer")
KeyBoard = robot.getKeyboard()


# ROll Pich Yaw
def get_IMU_Angle():
    data = IMU.getRollPitchYaw()
    # return ROll Pich Yaw
    return [data[1] * 180.0 / math.pi, data[0] * 180.0 / math.pi, data[2] * 180.0 / math.pi]


def webot_device_init():
    KeyBoard.enable(timestep)
    ACC.enable(timestep)
    # IMU使能
    IMU.enable(timestep)
    for leg in range(4):
        # 跨关节锁定
        robot_motor[leg][0].setPosition(0)
        # 初始化使能接触传感器
        robot_touch_sensor[leg].enable(timestep)
        # 初始化位置传感器
        for joint in range(3):
            robot_pos_sensor[leg][joint].enable(timestep)


def set_motor_torque(leg, name, torque):
    if torque > 1800:
        torque = 1800
    if torque < -1800:
        torque = -1800
    robot_motor[leg][name].setTorque(torque)


def get_motor_angle(leg, name):
    angle = 0
    angle = robot_pos_sensor[leg][name].getValue()
    return angle * 180.0 / math.pi


def get_all_motor_angle():
    temp_list = list()
    for leg in range(4):  # 遍历四条腿 每条腿三个关节
        temp_list.append([])
        for joint in range(3):
            temp_list[leg].append(get_motor_angle(leg, joint))
    return temp_list


def is_foot_touching(leg):
    return robot_touch_sensor[leg].getValue()


def all_is_foot_touching():
    temp_list = list()
    for leg in range(4):
        temp_list.append(robot_touch_sensor[leg].getValue())
    return temp_list


# def print_leg_angle():
#     for i in range(4):
#         print("腿", i, end=" ")
#         for j in range(3):
#             temp = get_motor_angle(i, j)
#             print("关节", j, "角度/°", int(temp), end=" ")
#         print("")


class Quadruped_robot_8DOF():
    def __init__(self):
        self.L = 0
        self.R = 1

        self.zh = -0.4  # 抬腿到高度 0.4
        self.H_des = - 0.55  # 0.5
        self.Tf = 0.25  # 飞行时间
        self.Ts = 0.25  # 支撑时间
        # 机器人机身参数
        self.L = 0.6  # 前后髋关节
        self.W = 0.48  # 左右髋关节
        self.a0 = 0
        self.a1 = 0.4
        self.a2 = 0.4
        self.m0 = 4
        self.m1 = 4
        self.M = 50 + 8 * 4

        # 四足支撑系数
        self.Kpitch = 1000  # 1000
        self.Dpitch = 300  # 300

        self.Kroll = 1000  # 1000
        self.Droll = 300  # 300

        # 行进时系数
        self.Kpitch_r = 1700  # 1000
        self.Dpitch_r = 300  # 200

        self.Kroll_r = 1000  # 1000
        self.Droll_r = 300  # 200

        self.Kyaw = 170  # 200

        # 悬空足系数
        self.Kxk = 800  # 800
        self.Dxk = 200  # 200

        self.Kzk = 4000  # 1000
        self.Dzk = 200  # 300

        # 支撑足系数
        self.Kx = 900  # 1000
        self.Dx = 100  # 100

        self.Kz = 6000  # 4000
        self.Dz = 500  # 300
        # self.Dyaw = 10
        # 摆动时速度增益
        self.Kvx = 0.3
        # 期望值
        self.Vx_des = -0.01
        self.W_des = 0

        self.Pitch_des = - 0 / 180.0 * math.pi  # 上负
        self.Roll_des = 0 / 180.0 * math.pi  # 左负
        self.Yaw_des = 0

        # 存储变量
        # 当前欧拉角
        self.Pitch = 0
        self.Roll = 0
        self.Yaw = 0
        # 上一时刻欧拉角
        self.pre_eulerAngle = [0, 0, 0]
        # 欧拉角导数
        self.dot_Pitch = 0
        self.dot_Roll = 0
        self.dot_Yaw = 0
        # 上一时刻欧拉角导数
        self.dot_Pitch_pre = 0
        self.dot_Roll_pre = 0
        self.dot_Yaw_pre = 0
        # 支撑模式 0->L 1->R 3->全着地 4->悬空
        self.standFoot = 4
        self.swallFoot = 4
        # 四脚着地状态 逆时针编号
        self.is_touching = [0, 0, 0, 0]
        # 四足足端当前坐标
        self.pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        for leg in range(4):
            self.pos[leg] = self.forwardkinematics([0, 0.6, -1.28])
        # 四足关节角
        self.theta = list()
        # 四足足端当前导数
        self.dot_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        # 四足足端当前二阶导数
        self.dot_2_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        # 四足足端上一时坐标
        self.pre_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        # 四足足端上一时刻导数
        self.pre_dot_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        # 不态时间
        self.time = 0
        # 是否停止 用于切换行进和四足着地
        self.stop = 1
        # 用于切换悬空 四脚离地一定时间后进入悬空状态
        self.fly_time = 0
        # 键盘控制变量
        self.key_data = [0, 0, 0]
        self.mass_center = 0.4  # 位置系数

    def forwardkinematics(self, theta):
        a0 = self.a0
        a1 = self.a1  # 腿长
        a2 = self.a2  # 腿长
        # 横滚髋关节和俯仰髋关节偏差为0
        # theta= L0 L1 L2
        # 足底位置
        s1 = math.sin(theta[1] / 180.0 * math.pi)
        c1 = math.cos(theta[1] / 180.0 * math.pi)
        s0 = math.sin(theta[0] / 180.0 * math.pi)
        c0 = math.cos(theta[0] / 180.0 * math.pi)

        s12 = math.sin(theta[1] / 180.0 * math.pi + theta[2] / 180.0 * math.pi)
        c12 = math.cos(theta[1] / 180.0 * math.pi + theta[2] / 180.0 * math.pi)

        x = -a1 * s1 - a2 * s12 #+ self.L / 2
        y = a0 * s0 + a1 * s0 * c1 + a2 * s0 * c12 #+ self.W / 2
        z = - a0 * c0 - a1 * c0 * c1 - a2 * c0 * c12
        return [x, y, z]

    def create_transJ(self, theta):
        a0 = self.a0
        a1 = self.a1  # 腿长
        a2 = self.a2  # 腿长
        # 横滚髋关节和俯仰髋关节偏差为0
        # theta= L0 L1 L2
        s0 = math.sin(theta[0] / 180.0 * math.pi)
        c0 = math.cos(theta[0] / 180.0 * math.pi)
        s1 = math.sin(theta[1] / 180.0 * math.pi)
        c1 = math.cos(theta[1] / 180.0 * math.pi)

        s12 = math.sin(theta[1] / 180.0 * math.pi + theta[2] / 180.0 * math.pi)
        c12 = math.cos(theta[1] / 180.0 * math.pi + theta[2] / 180.0 * math.pi)

        transJ = np.zeros((3, 3))
        transJ[0, 0] = 0
        transJ[0, 1] = -a0 * c1 - a2 * c12
        transJ[0, 2] = -a2 * c12

        transJ[1, 0] = c0 * (a0 + a1 * c1 + a2 * c12)
        transJ[1, 1] = -s0 * (a1 * s1 + a2 * s12)
        transJ[1, 2] = - a2 * s0 * s12

        transJ[2, 0] = s0 * (a0 + a1 * c1 + a2 * c12)
        transJ[2, 1] = c0 * (a1 * s1 + a2 * s12)
        transJ[2, 2] =  a2 * c0 * s12
        return transJ.T

    def update_food_touch_sensor(self):
        self.is_touching = all_is_foot_touching()


    def update_theta(self):
        self.theta = get_all_motor_angle()

    # 相位切换, 通过时间和足底传感器确定支撑对角腿和摆动对角腿
    def phase_swap(self):
        if self.time > 0.75 * self.Tf:
            if self.standFoot == self.L:
                if self.is_touching == [1, 1, 1, 1]:
                    self.standFoot = self.R
                    self.swallFoot = self.L
                    self.time = 0
                    # print("L-->R")

            elif self.standFoot == self.R:
                if self.is_touching == [1, 1, 1, 1]:
                    self.standFoot = self.L
                    self.swallFoot = self.R
                    self.time = 0
                    # print("R-->L")
            elif self.standFoot == 4:
                if self.is_touching == [1, 1, 1, 1]:
                    self.standFoot = 3
                    self.swallFoot = 3
                    self.stop = 1
                    self.time = 0
                    # print("悬空-->四脚着地")
            elif self.standFoot == 3:
                if self.is_touching == [1, 1, 1, 1] and self.stop == 0:
                    self.standFoot = self.R
                    self.swallFoot = self.L
                    self.time = 0
                    # print("四脚着地-->行进")
            if self.is_touching == [1, 1, 1, 1] and self.stop == 1:
                self.standFoot = 3
                self.swallFoot = 3
                self.time = 0
                # print("任意-->四脚着地")
            if self.is_touching == [0, 0, 0, 0]:  # and self.stop == 0
                self.fly_time += 0.001 * timestep
                if self.fly_time > 0.05:
                    self.standFoot = 4
                    self.swallFoot = 4
                    self.stop = 1
                    self.fly_time = 0
                    self.time = 0
                    # print("任意-->悬空")

    # 更新全部状态
    def update_robot_state(self):
        self.key_control()
        # 更新IMU及导数
        self.update_IMU()
        # 足底接触传感器更新
        self.update_food_touch_sensor()
        # 更新关节角
        self.update_theta()
        # 更新四条腿的运动学正解
        for leg in range(4):
            for joint in range(3):
                self.pos[leg] = self.forwardkinematics(self.theta[leg])
        self.update_V_P()
        self.phase_swap()
        self.time += timestep * 0.001

    # IMU获得欧拉角
    def update_IMU(self):
        # print("pre roll pitch yaw", self.pre_eulerAngle)
        eulerAngle = get_IMU_Angle()  # Roll Pitch Yaw 当前欧拉角
        # print("roll pitch yaw",eulerAngle)
        self.Roll = eulerAngle[0]  # 获得当前roll
        self.dot_Roll = (eulerAngle[0] - self.pre_eulerAngle[0]) / (0.001 * timestep)  # 求导数 dot_roll
        self.dot_Roll = self.dot_Roll * 0.3 + self.dot_Roll_pre * 0.7
        self.dot_Roll_pre = self.dot_Roll  # 更新记录上次的变量 dot_Roll_pre

        self.Pitch = eulerAngle[1]  # 获得当前pitch
        self.dot_Pitch = (eulerAngle[1] - self.pre_eulerAngle[1]) / (0.001 * timestep)  # 求导数 dot_pitch
        self.dot_Pitch = self.dot_Pitch * 0.3 + self.dot_Pitch_pre * 0.7  # 低通滤波
        self.dot_Pitch_pre = self.dot_Pitch  # 更新记录上次的变量 dot_Pitch_pre

        self.Yaw = eulerAngle[2]  # 获得当前yaw
        self.dot_Yaw = (eulerAngle[2] - self.pre_eulerAngle[2]) / (0.001 * timestep)  # 求导数 dot_yaw
        self.dot_Yaw = self.dot_Yaw * 0.3 + self.dot_Yaw_pre * 0.7  # 低通滤波
        self.dot_Yaw_pre = self.dot_Yaw  # 更新记录上次的变量 dot_Yaw_pre

        self.pre_eulerAngle = copy.deepcopy(eulerAngle)

    # 速度,加速度更新
    def update_V_P(self):
        dot_pos = (((np.array(self.pos) - np.array(self.pre_pos))
                    / (0.001 * timestep)) * 1.0 + np.array(self.pre_dot_pos) * 0).tolist()
        # 上一步坐标
        self.pre_pos = copy.deepcopy(self.pos)
        # 对速度求导 所有腿和关节 加速度
        dot_2_pos = ((np.array(dot_pos) - np.array(self.pre_dot_pos)) / (0.001 * timestep)).tolist()
        # 上一步导数
        self.pre_dot_pos = copy.deepcopy(dot_pos)
        self.dot_pos = copy.deepcopy(dot_pos)
        self.dot_2_pos = copy.deepcopy(dot_2_pos)
        pass

    # 键盘控制
    def key_control(self):
        key = KeyBoard.getKey()
        if key == KeyBoard.UP:
            self.Pitch_des += 0.1 / 180.0 * math.pi
            print(self.Pitch_des)
        elif key == KeyBoard.DOWN:
            self.Pitch_des -= 0.1 / 180.0 * math.pi
            print(self.Pitch_des)
        elif key == KeyBoard.LEFT:
            self.Roll_des -= 0.1 / 180.0 * math.pi
        elif key == KeyBoard.RIGHT:
            self.Roll_des += 0.1 / 180.0 * math.pi
        elif key == ord('P'):
            self.stop = 1
            self.Pitch_des = 0
            self.Roll_des = 0
        elif key == ord('W'):
            self.stop = 0
            self.Vx_des = -0.3
        elif key == ord('S'):
            self.stop = 0
            self.Vx_des = 0.3
        elif key == ord('A'):
            self.Vx_des = 0
            self.W_des = 20 / 180.0 * math.pi
            self.stop = 0
        elif key == ord('D'):
            self.Vx_des = 0
            self.W_des = -20 / 180.0 * math.pi
            self.stop = 0
        elif key == ord('Q'):
            self.Vx_des = -0.2
            self.W_des = 20 / 180.0 * math.pi
            self.stop = 0
        elif key == ord('E'):
            self.Vx_des = -0.2
            self.W_des = -20 / 180.0 * math.pi
            self.stop = 0
        elif key == ord('T'):
            self.stop = 1
            self.Vx_des = -0.01
            self.W_des = 0
        elif key == ord('U'):
            self.H_des -= 0.001 * timestep
            self.zh = self.H_des + 0.12
            print("目标 ", self.H_des, "当前", self.pos[0][2])
        elif key == ord('L'):
            self.H_des += 0.001 * timestep
            self.zh = self.H_des + 0.12
            print(self.H_des)
            print("目标 ", self.H_des, "当前", self.pos[0][2])
        else:
            # self.stop = 0
            self.Vx_des = -0.05
            self.W_des = 0

    # 轨迹
    def curve(self, xt, init_pos, init_dotpos):
        ft = [0, 0, 0]  # x,z
        dft = [0, 0, 0]  # x,z
        xT = xt
        t = self.time
        x0 = init_pos[0]
        z0 = init_pos[2]
        dx0 = init_dotpos[0]
        Tf = self.Tf
        zh = self.zh
        # // x, y
        if t < Tf / 4.0:
            ft[0] = -4 * dx0 * t * t / Tf + dx0 * t + x0
            dft[0] = -8 * dx0 * t / Tf + dx0
        elif (t >= Tf / 4.0) and (t < 3.0 * Tf / 4.0):

            ft[0] = (-4 * Tf * dx0 - 16 * xT + 16 * x0) * t * t * t / (Tf * Tf * Tf) + \
                    (7 * Tf * dx0 + 24 * xT - 24 * x0) * t * t / (Tf * Tf) + \
                    (-15 * Tf * dx0 - 36 * xT + 36 * x0) * t / (4 * Tf) + \
                    (9 * Tf * dx0 + 16 * xT) / 16
            dft[0] = (-4 * Tf * dx0 - 16 * xT + 16 * x0) * 3 * t * t / (Tf * Tf * Tf) + \
                     (7 * Tf * dx0 + 24 * xT - 24 * x0) * 2 * t / (Tf * Tf) + \
                     (-15 * Tf * dx0 - 36 * xT + 36 * x0) / (4 * Tf)
        else:
            ft[0] = xT
            dft[0] = 0
            # // z
        if t < Tf / 2.0:
            ft[2] = 16 * (z0 - zh) * t * t * t / (Tf * Tf * Tf) + 12 * (zh - z0) * t * t / (Tf * Tf) + z0
            dft[2] = 16 * (z0 - zh) * 3 * t * t / (Tf * Tf * Tf) + 12 * (zh - z0) * 2 * t / (Tf * Tf)
        elif (t >= Tf / 2.0) and (t < 3.0 * Tf / 4.0):
            ft[2] = 4 * (z0 - zh) * t * t / (Tf * Tf) - 4 * (z0 - zh) * t / Tf + z0
            dft[2] = 4 * (z0 - zh) * 2 * t / (Tf * Tf) - 4 * (z0 - zh) / Tf
        else:
            ft[2] = 4 * (z0 - zh) * t * t / (Tf * Tf) - 4 * (z0 - zh) * t / Tf + z0
            dft[2] = 4 * (z0 - zh) * 2 * t / (Tf * Tf) - 4 * (z0 - zh) / Tf

        return [ft, dft]

    def run(self):
        init_pos = [[0, 0, 0], [0, 0, 0]]  # 左右
        init_dotpos = [[0, 0, 0], [0, 0, 0]]  # 左右
        path_pos = [[0, 0, 0], [0, 0, 0]]
        dot_path_pos = [[0, 0, 0], [0, 0, 0]]
        while robot.step(timestep) != -1:
            # print(ACC.getValues())
            for leg in range(4):
                # 跨关节锁定
                robot_motor[leg][0].setPosition(0)
            self.update_robot_state()

            # 获取支撑腿和摆动腿状态
            sw = [0, 0, 0, 0, 0]  # 摆动足 腿序号 左,右,前,后,特殊位
            st = [0, 0, 0, 0, 0]  # 支撑足 腿序号 左,右,前,后,特殊位
            # 左脚着地
            if self.standFoot == self.L:  # 左对角线

                st[0] = 0  # 左
                st[1] = 2  # 右
                st[2] = 0  # 前
                st[3] = 2  # 后

                sw[0] = 3  # 左
                sw[1] = 1  # 右
                sw[2] = 1  # 前
                sw[3] = 3  # 后
            # 右脚着地
            elif self.standFoot == self.R:  # 右对角线
                st[0] = 3  # 左
                st[1] = 1  # 右
                st[2] = 1  # 前
                st[3] = 3  # 后

                sw[0] = 0  # 左
                sw[1] = 2  # 右
                sw[2] = 0  # 前
                sw[3] = 2  # 后
            # 四脚着地
            elif self.standFoot == 3:
                st[0] = 3  # 左
                st[1] = 1  # 右
                st[2] = 1  # 前
                st[3] = 3  # 后

                sw[0] = 0  # 左
                sw[1] = 2  # 右
                sw[2] = 0  # 前
                sw[3] = 2  # 后
                st[4] = 100
            # 四脚悬空
            elif self.standFoot == 4:
                sw[4] = 200
            # print(self.standFoot, 'sw', sw)
            # 对角步态状态控----------------------------------------------------------------------------------对角步态状态控

            if st[4] == 0 and sw[4] == 0:
                # 支撑足 非stop
                # 计算姿态虚拟力
                F_pitch = self.Kpitch_r * (self.Pitch_des - self.Pitch / 180.0 * math.pi) + \
                          self.Dpitch_r / 2 * (0 - self.dot_Pitch / 180.0 * math.pi)
                F_roll = self.Kroll_r * (self.Roll_des - self.Roll / 180.0 * math.pi) + \
                         self.Droll_r * (0 - self.dot_Roll / 180.0 * math.pi)

                # 高低叠加控制姿态
                K_pi_z = 0.01
                H_des_front = self.H_des / 2 + K_pi_z * F_pitch
                H_des_back = self.H_des / 2 - K_pi_z * F_pitch

                K_roll_z = 0.01
                H_des_left = self.H_des / 2 - K_roll_z * F_roll
                H_des_right = self.H_des / 2 + K_roll_z * F_roll
                #
                Hz_left = self.H_des
                Hz_right = self.H_des

                # 左前右后对应
                if st.index(st[2]) == 0:
                    Hz_left = H_des_left + H_des_front
                    Hz_right = H_des_right + H_des_back

                    Fz_left = self.Kz * (Hz_left - self.pos[st[0]][2]) + \
                              self.Dz * (0 - self.dot_pos[st[0]][2]) \
                              - self.M * 9.81 * self.mass_center * math.cos(self.Pitch / 180.0 * math.pi)
                    Fz_right = self.Kz * (Hz_right - self.pos[st[1]][2]) + \
                               self.Dz * (0 - self.dot_pos[st[1]][2]) \
                               - self.M * 9.81 * (1 - self.mass_center) * math.cos(-self.Pitch / 180.0 * math.pi)
                # 左后右前对应
                elif st.index(st[2]) == 1:
                    Hz_left = H_des_left + H_des_back
                    Hz_right = H_des_right + H_des_front

                    # 计算Z轴虚拟力
                    Fz_left = self.Kz * (Hz_left - self.pos[st[0]][2]) + \
                              self.Dz * (0 - self.dot_pos[st[0]][2]) \
                              - self.M * 9.81 * (1 - self.mass_center) * math.cos(self.Pitch / 180.0 * math.pi)
                    Fz_right = self.Kz * (Hz_right - self.pos[st[1]][2]) + \
                               self.Dz * (0 - self.dot_pos[st[1]][2]) \
                               - self.M * 9.81 * self.mass_center * math.cos(self.Pitch / 180.0 * math.pi)
                # print(self.pos)
                if not self.W_des == 0:
                    F_yaw = self.Kyaw * (self.W_des - (
                            self.dot_Yaw * 0.1 + self.dot_Yaw_pre * 0.9) / 180.0 * math.pi)
                else:
                    F_yaw = 0
                Kyaw_x = 0.01
                V_des_left = self.Vx_des + Kyaw_x * F_yaw
                V_des_right = self.Vx_des - Kyaw_x * F_yaw

                # est_dot_pos=(np.array(self.dot_pos)*0.1+np.array(self.pre_dot_pos)*0.9).tolist()

                # print(self.dot_pos)
                # 计算X轴虚拟力
                Fx_left = self.Kx * (V_des_left - self.dot_pos[st[0]][0]) \
                          + self.M * 9.8 * math.sin(self.Pitch / 180.0 * math.pi) * self.mass_center
                Fx_right = self.Kx * (V_des_right - self.dot_pos[st[1]][0]) \
                           + self.M * 9.8 * math.sin(self.Pitch / 180.0 * math.pi) * (1 - self.mass_center)

                T_left = self.create_transJ(self.theta[st[0]]) @ np.array([[Fx_left], [Fz_left]])
                T_right = self.create_transJ(self.theta[st[1]]) @ np.array([[Fx_right], [Fz_right]])

                set_motor_torque(st[0], 1, T_left[0, 0])
                set_motor_torque(st[0], 2, T_left[1, 0])

                set_motor_torque(st[1], 1, T_right[0, 0])
                set_motor_torque(st[1], 2, T_right[1, 0])

                # 摆动足--------------------------------------------------------------------------------------------------摆动足

                # 获得初始速度和位置

                if self.time == 0.001 * timestep:  # 刚刚切换过对角腿,记录此时的摆动足即可
                    init_pos[0] = self.pos[sw[0]]
                    init_pos[1] = self.pos[sw[1]]

                    init_dotpos[0] = self.dot_pos[sw[0]]
                    init_dotpos[1] = self.dot_pos[sw[1]]
                # print("初始点 初始速度", init_pos, init_dotpos)
                est_dot_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
                if not self.time == 0.001 * timestep:
                    est_dot_pos = (np.array(self.dot_pos) * 0.5 + np.array(self.pre_dot_pos) * 0.5).tolist()
                # print("速度估计", est_dot_pos)
                xT = [0.2, 0.2]  # 落足点 左右
                xT[0] = est_dot_pos[st[0]][0] * self.Ts / 2.0 - self.Kvx * (est_dot_pos[st[0]][0] - V_des_left)
                xT[1] = est_dot_pos[st[1]][0] * self.Ts / 2.0 - self.Kvx * (est_dot_pos[st[1]][0] - V_des_right)
                # xT[0] = est_dot_pos[st[0]][0] * self.Ts / 2.0 - self.Kvx * (est_dot_pos[st[0]][0] - self.Vx_des)V_des_left
                # xT[1] = est_dot_pos[st[1]][0] * self.Ts / 2.0 - self.Kvx * (est_dot_pos[st[1]][0] - self.Vx_des)
                # print("落足点", xT)

                if self.is_touching[sw[0]] == 1 and self.time > 0.5 * self.Tf:
                    path_pos[0], dot_path_pos[0] = self.pos[sw[0]], [0, 0, 0]
                    # pass
                else:
                    path_pos[0], dot_path_pos[0] = self.curve(xT[0], init_pos[0], init_dotpos[0])
                if self.is_touching[sw[1]] == 1 and self.time > 0.5 * self.Tf:
                    path_pos[1], dot_path_pos[1] = self.pos[sw[1]], [0, 0, 0]
                else:
                    path_pos[1], dot_path_pos[1] = self.curve(xT[1], init_pos[1], init_dotpos[1])

                # 左摆动足 索引值sw[0]
                Fx_left_sw = self.Kxk * (path_pos[0][0] - self.pos[sw[0]][0]) + \
                             self.Dxk * (dot_path_pos[0][0] - self.dot_pos[sw[0]][0]) \
                    # + self.M * 9.8 * math.sin(self.Pitch / 180.0 * math.pi) * self.mass_center
                # 右摆动足 索引值sw[1]
                Fx_right_sw = self.Kxk * (path_pos[1][0] - self.pos[sw[1]][0]) + \
                              self.Dxk * (dot_path_pos[1][0] - self.dot_pos[sw[1]][0]) \
                    # + self.M * 9.8 * math.sin(self.Pitch / 180.0 * math.pi) * (1 - self.mass_center)

                if self.time <= 0.55 * self.Tf:
                    KKZ = self.Kzk
                    KKD = self.Dzk
                else:
                    KKZ = 600
                    KKD = 100
                # if self.is_touching[sw[0]]==1:
                #     KKZ = self.Kzk * 0.1
                Fz_left_sw = KKZ * (path_pos[0][2] - self.pos[sw[0]][2]) + \
                             KKD * (dot_path_pos[0][2] - self.dot_pos[sw[0]][2])
                Fz_right_sw = KKZ * (path_pos[1][2] - self.pos[sw[1]][2]) + \
                              KKD * (dot_path_pos[1][2] - self.dot_pos[sw[1]][2])

                T_left_sw = self.create_transJ(self.theta[sw[0]]) @ np.array([[Fx_left_sw], [Fz_left_sw]])
                T_right_sw = self.create_transJ(self.theta[sw[1]]) @ np.array([[Fx_right_sw], [Fz_right_sw]])

                set_motor_torque(sw[0], 1, T_left_sw[0, 0])
                set_motor_torque(sw[0], 2, T_left_sw[1, 0])

                set_motor_torque(sw[1], 1, T_right_sw[0, 0])
                set_motor_torque(sw[1], 2, T_right_sw[1, 0])

            # 四足站立状态控制------------------------------------------------------------------------------------------四足站立状态控制
            elif st[4] == 100:
                F_pitch = self.Kpitch * (self.Pitch_des - self.Pitch / 180.0 * math.pi) + \
                          self.Dpitch / 2 * (0 - self.dot_Pitch / 180.0 * math.pi)
                F_roll = self.Kroll * (self.Roll_des - self.Roll / 180.0 * math.pi) + \
                         self.Droll * (0 - self.dot_Roll / 180.0 * math.pi)

                K_pi_z = 0.02
                H_des_front = + K_pi_z * F_pitch / 2
                H_des_back = - K_pi_z * F_pitch / 2

                K_roll_z = 0.01
                H_des_left = - K_roll_z * F_roll / 2
                H_des_right = + K_roll_z * F_roll / 2

                Fz_left_F = self.Kz * (self.H_des + H_des_left + H_des_front - self.pos[0][2]) + self.Dz * (
                        0 - self.dot_pos[0][2])
                Fz_right_F = self.Kz * (self.H_des + H_des_right + H_des_front - self.pos[1][2]) + self.Dz * (
                        0 - self.dot_pos[1][2])
                Fz_left_B = self.Kz * (self.H_des + H_des_left + H_des_back - self.pos[3][2]) + self.Dz * (
                        0 - self.dot_pos[3][2])
                Fz_right_B = self.Kz * (self.H_des + H_des_right + H_des_back - self.pos[2][2]) + self.Dz * (
                        0 - self.dot_pos[2][2])

                Fz_left_F = Fz_left_F - self.M * 10 / 4
                Fz_right_F = Fz_right_F - self.M * 10 / 4
                Fz_left_B = Fz_left_B - self.M * 10 / 4
                Fz_right_B = Fz_right_B - self.M * 10 / 4  # / 2

                # print("run3")kpx * (0.0 - x) + kdx * (0 - dx)
                Fx_left_f = self.Kxk * (0 - self.pos[0][0]) + self.Dxk * (0.0 - self.dot_pos[0][0])
                Fx_right_f = self.Kxk * (0 - self.pos[1][0]) + self.Dxk * (0.0 - self.dot_pos[1][0])
                Fx_left_b = self.Kxk * (0 - self.pos[3][0]) + self.Dxk * (0.0 - self.dot_pos[3][0])
                Fx_right_b = self.Kxk * (0 - self.pos[2][0]) + self.Dxk * (0.0 - self.dot_pos[2][0])

                T_left_F = self.create_transJ(self.theta[0]) @ np.array([[Fx_left_f], [Fz_left_F]])
                T_left_B = self.create_transJ(self.theta[3]) @ np.array([[Fx_left_b], [Fz_left_B]])
                T_right_F = self.create_transJ(self.theta[1]) @ np.array([[Fx_right_f], [Fz_right_F]])
                T_right_B = self.create_transJ(self.theta[2]) @ np.array([[Fx_right_b], [Fz_right_B]])

                set_motor_torque(0, 1, float(T_left_F[0, 0]))
                set_motor_torque(0, 2, float(T_left_F[1, 0]))

                set_motor_torque(1, 1, float(T_right_F[0, 0]))
                set_motor_torque(1, 2, float(T_right_F[1, 0]))

                set_motor_torque(2, 1, float(T_right_B[0, 0]))
                set_motor_torque(2, 2, float(T_right_B[1, 0]))

                set_motor_torque(3, 1, float(T_left_B[0, 0]))
                set_motor_torque(3, 2, float(T_left_B[1, 0]))

                pass
            # 四足悬空状态控制------------------------------------------------------------------------------------------四足悬空状态控制
            elif sw[4] == 200:  # 全悬空
                # print("run3")


                Fx_left_F = self.Kxk * (0.0 - self.pos[0][0]) + self.Dxk * (0.0 - self.dot_pos[0][0])
                Fx_right_F = self.Kxk * (0.0 - self.pos[1][0]) + self.Dxk * (0.0 - self.dot_pos[1][0])
                Fx_left_B = self.Kxk * (0.0 - self.pos[3][0]) + self.Dxk * (0.0 - self.dot_pos[3][0])
                Fx_right_B = self.Kxk * (0.0 - self.pos[2][0]) + self.Dxk * (0.0 - self.dot_pos[2][0])

                Fy_left_F = self.Kxk * (0.0 - self.pos[0][1]) + self.Dxk * (0.0 - self.dot_pos[0][1])
                Fy_right_F = self.Kxk * (0.0 - self.pos[1][1]) + self.Dxk * (0.0 - self.dot_pos[1][1])
                Fy_left_B = self.Kxk * (0.0 - self.pos[3][1]) + self.Dxk * (0.0 - self.dot_pos[3][1])
                Fy_right_B = self.Kxk * (0.0 - self.pos[2][1]) + self.Dxk * (0.0 - self.dot_pos[2][1])

                Fz_left_F = self.Kzk * (self.H_des - self.pos[0][2]) + self.Dzk * (0 - self.dot_pos[0][2])
                Fz_right_F = self.Kzk * (self.H_des - self.pos[1][2]) + self.Dzk * (0 - self.dot_pos[1][2])
                Fz_left_B = self.Kzk * (self.H_des - self.pos[3][2]) + self.Dzk * (0 - self.dot_pos[3][2])
                Fz_right_B = self.Kzk * (self.H_des - self.pos[2][2]) + self.Dzk * (0 - self.dot_pos[2][2])

                T_left_F = self.create_transJ(self.theta[0]) @ np.array([[Fx_left_F],[Fy_left_F], [Fz_left_F]])
                T_left_B = self.create_transJ(self.theta[3]) @ np.array([[Fx_left_B],[Fy_left_B], [Fz_left_B]])
                T_right_F = self.create_transJ(self.theta[1]) @ np.array([[Fx_right_F],[Fy_right_F], [Fz_right_F]])
                T_right_B = self.create_transJ(self.theta[2]) @ np.array([[Fx_right_B], [Fy_right_B],[Fz_right_B]])

                set_motor_torque(0, 0, float(T_left_F[0, 0]))
                set_motor_torque(0, 1, float(T_left_F[1, 0]))
                set_motor_torque(0, 2, float(T_left_F[2, 0]))

                set_motor_torque(0, 0, float(T_right_F[0, 0]))
                set_motor_torque(1, 1, float(T_right_F[1, 0]))
                set_motor_torque(1, 2, float(T_right_F[2, 0]))

                set_motor_torque(0, 0, float(T_right_B[0, 0]))
                set_motor_torque(2, 1, float(T_right_B[1, 0]))
                set_motor_torque(2, 2, float(T_right_B[2, 0]))

                set_motor_torque(0, 0, float(T_left_B[0, 0]))
                set_motor_torque(3, 1, float(T_left_B[1, 0]))
                set_motor_torque(3, 2, float(T_left_B[2, 0]))


if __name__ == '__main__':
    q = Quadruped_robot_8DOF()
    webot_device_init()
    q.run()

 12自由度:

"""VMC_test_py controller."""

from controller import Robot
import math
import numpy as np
import copy
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
# y1 = []

    # y1.append(i)  # 每迭代一次,将i放入y1中画出来
    
    # plt.pause(0.1)

# create the Robot instance.
robot = Robot()
timestep = 1

# 机器人所有马达
#   0  1  2  3
#   LF RF RB LB
# 0 跨 ........
# 1 髋 ........
# 2 膝 ........
robot_motor = []  # LF RF RB LB
for i in range(4):
    robot_motor.append([])
# 左前足马达
robot_motor[0].append(robot.createMotor("LFL0_rotational motor"))
robot_motor[0].append(robot.createMotor("LFL1_rotational motor"))
robot_motor[0].append(robot.createMotor("LFL2_rotational motor"))
# 右前足马达
robot_motor[1].append(robot.createMotor("RFL0_rotational motor"))
robot_motor[1].append(robot.createMotor("RFL1_rotational motor"))
robot_motor[1].append(robot.createMotor("RFL2_rotational motor"))
# 右后足马达
robot_motor[2].append(robot.createMotor("RBL0_rotational motor"))
robot_motor[2].append(robot.createMotor("RBL1_rotational motor"))
robot_motor[2].append(robot.createMotor("RBL2_rotational motor"))
# 左后足马达
robot_motor[3].append(robot.createMotor("LBL0_rotational motor"))
robot_motor[3].append(robot.createMotor("LBL1_rotational motor"))
robot_motor[3].append(robot.createMotor("LBL2_rotational motor"))

# 机器人所有位置传感器
#   0  1  2  3
#   LF RF RB LB
# 0 跨 ........
# 1 髋 ........
# 2 膝 ........
robot_pos_sensor = []  # LF RF RB LB
for i in range(4):
    robot_pos_sensor.append([])
# 左前足位置传感器
robot_pos_sensor[0].append(robot.createPositionSensor("LFL0_position sensor"))
robot_pos_sensor[0].append(robot.createPositionSensor("LFL1_position sensor"))
robot_pos_sensor[0].append(robot.createPositionSensor("LFL2_position sensor"))
# 右前足位置传感器
robot_pos_sensor[1].append(robot.createPositionSensor("RFL0_position sensor"))
robot_pos_sensor[1].append(robot.createPositionSensor("RFL1_position sensor"))
robot_pos_sensor[1].append(robot.createPositionSensor("RFL2_position sensor"))
# 右后足位置传感器
robot_pos_sensor[2].append(robot.createPositionSensor("RBL0_position sensor"))
robot_pos_sensor[2].append(robot.createPositionSensor("RBL1_position sensor"))
robot_pos_sensor[2].append(robot.createPositionSensor("RBL2_position sensor"))
# 左后足位置传感器
robot_pos_sensor[3].append(robot.createPositionSensor("LBL0_position sensor"))
robot_pos_sensor[3].append(robot.createPositionSensor("LBL1_position sensor"))
robot_pos_sensor[3].append(robot.createPositionSensor("LBL2_position sensor"))

# 触地传感器
# LF RF RB LB
robot_touch_sensor = []
robot_touch_sensor.append(robot.createTouchSensor("LF_touch sensor"))
robot_touch_sensor.append(robot.createTouchSensor("RF_touch sensor"))
robot_touch_sensor.append(robot.createTouchSensor("RB_touch sensor"))
robot_touch_sensor.append(robot.createTouchSensor("LB_touch sensor"))

# inertial unit
IMU = robot.createInertialUnit("inertial unit")
ACC = robot.createAccelerometer("accelerometer")
KeyBoard = robot.getKeyboard()
# Camera=robot.createCamera("camera")

# ROll Pich Yaw
def get_IMU_Angle():
    data = IMU.getRollPitchYaw()
    # return ROll Pich Yaw
    return [data[1] * 180.0 / math.pi, data[0] * 180.0 / math.pi, data[2] * 180.0 / math.pi]


def webot_device_init():
    # Camera.enable(timestep)
    KeyBoard.enable(timestep)
    ACC.enable(timestep)
    # IMU使能
    IMU.enable(timestep)
    for leg in range(4):
        # 跨关节锁定
        robot_motor[leg][0].setPosition(0)
        # 初始化使能接触传感器
        robot_touch_sensor[leg].enable(timestep)
        # 初始化位置传感器
        for joint in range(3):
            robot_pos_sensor[leg][joint].enable(timestep)


def set_motor_torque(leg, name, torque):
    max = 1800
    if torque > max:
        # print("error torque >max=", torque)
        torque = max
    if torque < -max:
        # print("error torque >max=", torque)
        torque = -max
    robot_motor[leg][name].setTorque(torque)


def get_motor_angle(leg, name):
    angle = 0
    angle = robot_pos_sensor[leg][name].getValue()
    return angle * 180.0 / math.pi


def get_all_motor_angle():
    temp_list = list()
    for leg in range(4):  # 遍历四条腿 每条腿三个关节
        temp_list.append([])
        for joint in range(3):
            temp_list[leg].append(get_motor_angle(leg, joint))
    return temp_list


def is_foot_touching(leg):
    return robot_touch_sensor[leg].getValue()


def all_is_foot_touching():
    temp_list = list()
    for leg in range(4):
        temp_list.append(robot_touch_sensor[leg].getValue())
    return temp_list


# def print_leg_angle():
#     for i in range(4):
#         print("腿", i, end=" ")
#         for j in range(3):
#             temp = get_motor_angle(i, j)
#             print("关节", j, "角度/°", int(temp), end=" ")
#         print("")


class Quadruped_robot_mix():
    def __init__(self):
        self.L = 0
        self.R = 1

        self.zh = -0.4  # 抬腿到高度 0.4
        self.H_des = - 0.55  # 0.5
        self.Tf = 0.25  # 飞行时间
        self.Ts = 0.25  # 支撑时间
        # 机器人机身参数
        self.L = 0.6  # 前后髋关节w
        self.W = 0.48  # 左右髋关节
        self.a0 = 0
        self.a1 = 0.4
        self.a2 = 0.4
        self.m0 = 4
        self.m1 = 4
        self.M = 50 + 8 * 4

        # 四足支撑系数
        self.Kpitch = 1000  # 1000
        self.Dpitch = 300  # 300

        self.Kroll = 1000  # 1000
        self.Droll = 300  # 300

        self.Kyaw = 1000  # 1000
        self.Dyaw = 300  # 300

        self.Kxs = 2000  # 1000
        self.Dxs = 100  # 100

        self.Kys = 2000  # 4000
        self.Dys = 500  # 300

        self.Kzs = 5000  # 4000
        self.Dzs = 200  # 300

        # 行进时系数
        self.Kpitch_r = 2000  # 2000
        self.Dpitch_r = 300  # 300

        self.Kroll_r = 2000  # 1000
        self.Droll_r = 400  # 400

        self.Kyaw_r = 700  # 6000

        # 行进支撑足系数
        self.Kx = 1000  # 1000
        # self.Dx = 100  # 100

        self.Ky = 10  # 4000
        self.Dy = 500  # 300

        self.Kz = 4000  # 3000
        self.Dz = 300  # 300

        # 悬空足系数
        self.Kxk = 1500  # 1000
        self.Dxk = 200  # 200

        self.Kzk = 5000  # 3000
        self.Dzk = 200  # 300

        self.Kyk = 1000  # 1000
        self.Dyk = 200  # 300

        # self.Dyaw = 10
        # 摆动时速度增益
        self.Kvx = 0.2  # 0.1
        self.Kvy = 0.25  # 0.25
        # 期望值
        self.Vx_des = 0
        self.Vy_des = 0
        self.W_des = 0

        self.Vx=0.3
        self.Vy=0.3
        self.W=40

        self.Pitch_des = - 0 / 180.0 * math.pi  # 上负
        self.Roll_des = 0 / 180.0 * math.pi  # 左负
        self.Yaw_des = 0

        # 存储变量
        # 当前欧拉角
        self.Pitch = 0
        self.Roll = 0
        self.Yaw = 0
        # 上一时刻欧拉角
        self.pre_eulerAngle = [0, 0, 0]
        # 欧拉角导数
        self.dot_Pitch = 0
        self.dot_Roll = 0
        self.dot_Yaw = 0
        # 上一时刻欧拉角导数
        self.dot_Pitch_pre = 0
        self.dot_Roll_pre = 0
        self.dot_Yaw_pre = 0
        # 支撑模式 0->L 1->R 3->全着地 4->悬空
        self.standFoot = 4
        self.swallFoot = 4
        # 四脚着地状态 逆时针编号
        self.is_touching = [0, 0, 0, 0]
        # 四足足端当前坐标
        self.pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        for leg in range(4):
            self.pos[leg] = self.forwardkinematics([0, 0.6, -1.28])
        # 四足关节角
        self.theta = list()
        # 四足足端当前导数
        self.dot_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        # 四足足端当前二阶导数
        self.dot_2_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        # 四足足端上一时坐标
        self.pre_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        # 四足足端上一时刻导数
        self.pre_dot_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
        # 不态时间
        self.time = 0
        # 是否停止 用于切换行进和四足着地
        self.stop = 1
        # 用于切换悬空 四脚离地一定时间后进入悬空状态
        self.fly_time = 0
        # 键盘控制变量
        self.key_data = [0, 0, 0]
        self.mass_center = 0.5  # 位置系数

    def forwardkinematics(self, theta):
        a0 = self.a0
        a1 = self.a1  # 腿长
        a2 = self.a2  # 腿长
        # 横滚髋关节和俯仰髋关节偏差为0
        # theta= L0 L1 L2
        # 足底位置

        s0 = math.sin(theta[0] / 180.0 * math.pi)
        c0 = math.cos(theta[0] / 180.0 * math.pi)
        s1 = math.sin(theta[1] / 180.0 * math.pi)
        c1 = math.cos(theta[1] / 180.0 * math.pi)

        s12 = math.sin(theta[1] / 180.0 * math.pi + theta[2] / 180.0 * math.pi)
        c12 = math.cos(theta[1] / 180.0 * math.pi + theta[2] / 180.0 * math.pi)

        x = -a1 * s1 - a2 * s12  # + self.L / 2
        y = a0 * s0 + a1 * s0 * c1 + a2 * s0 * c12  # + self.W / 2
        z = - a0 * c0 - a1 * c0 * c1 - a2 * c0 * c12

        return [x, y, z]

    # 腿部坐标转换到机体坐标下
    def convert_pos(self, leg, pos):
        x, y, z = pos
        if leg == 0 or leg == 1:
            x += self.L / 2
        else:
            x -= self.L / 2

        if leg == 0 or leg == 3:
            y += self.W / 2
        else:
            y -= self.W / 2
        return [x, y, z]

    def convert_all_leg(self, pos):
        temp = []
        for i in range(4):
            temp.append(self.convert_pos(i, pos[i]))
        return temp

    def create_transJ(self, theta):
        a0 = self.a0
        a1 = self.a1  # 腿长
        a2 = self.a2  # 腿长
        # 横滚髋关节和俯仰髋关节偏差为0
        # theta= L0 L1 L2
        s0 = math.sin(theta[0] / 180.0 * math.pi)
        c0 = math.cos(theta[0] / 180.0 * math.pi)
        s1 = math.sin(theta[1] / 180.0 * math.pi)
        c1 = math.cos(theta[1] / 180.0 * math.pi)

        s12 = math.sin(theta[1] / 180.0 * math.pi + theta[2] / 180.0 * math.pi)
        c12 = math.cos(theta[1] / 180.0 * math.pi + theta[2] / 180.0 * math.pi)

        transJ = np.zeros((3, 3))
        transJ[0, 0] = 0
        transJ[0, 1] = -a0 * c1 - a2 * c12
        transJ[0, 2] = -a2 * c12

        transJ[1, 0] = c0 * (a0 + a1 * c1 + a2 * c12)
        transJ[1, 1] = -s0 * (a1 * s1 + a2 * s12)
        transJ[1, 2] = - a2 * s0 * s12

        transJ[2, 0] = s0 * (a0 + a1 * c1 + a2 * c12)
        transJ[2, 1] = c0 * (a1 * s1 + a2 * s12)
        transJ[2, 2] = a2 * c0 * s12
        return transJ.T

    def create_Q_inv(self, posf, posb):
        # q_inv = np.zeros((6, 6))

        xf = posf[0]
        yf = posf[1]
        zf = posf[2]

        xh = posb[0]
        yh = posb[1]
        zh = posb[2]

        # q_inv[0, 0] = ((xf - xh) * yh * zf - ((xf + xh) * yf - 2 * xf * yh) * zh) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[0, 1] = ((xf + xh) * (xf * yh - xh * yf)) / 2 * (yf - yh) * (xf * zh - xh * zf)
        # q_inv[0, 2] = ((xf - xh) * (xf + xh)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[0, 3] = (xf + xh) / 2 * (xh * zf - xf * zh)
        # q_inv[0, 4] = ((xf - xh) * (zf + zh)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[0, 5] = 0
        #
        # q_inv[1, 0] = (yh * zf - yf * zh) / 2 * (xh * zf - xf * zh)
        # q_inv[1, 1] = (xh * yf - xf * yh) / 2 * (xh * zf - xf * zh)
        # q_inv[1, 2] = (xf - xh) / 2 * (xh * zf - xf * zh)
        # q_inv[1, 3] = (yf - yh) / 2 * (xh * zf - xf * zh)
        # q_inv[1, 4] = (zf - zh) / 2 * (xh * zf - xf * zh)
        # q_inv[1, 5] = 0
        #
        # q_inv[2, 0] = ((zf + zh) * (zf * yh - zh * yf)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[2, 1] = (xf * yh * (zh - zf) + xh * ((zf + zh) * yf - 2 * zf * yh)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[2, 2] = ((xf + xh) * (zf - zh)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[2, 3] = (zf + zh) / 2 * (xh * zf - xf * zh)
        # q_inv[2, 4] = ((zf + zh) * (zf - zh)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[2, 5] = 0
        #
        # q_inv[3, 0] = (yf * zh * (xh - xf) + zf * (2 * yf * xh - (xf + xh) * yh)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[3, 1] = ((xf + xh) * (xf * yh - xh * yf)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[3, 2] = ((xf + xh) * (xf - xh)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[3, 3] = (xf + xh) / 2 * (zh * xf - zf * xh)
        # q_inv[3, 4] = ((zf + zh) * (xh - xf)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[3, 5] = 0
        #
        # q_inv[4, 0] = (yh * zf - yf * zh) / 2 * (xh * zf - xf * zh)
        # q_inv[4, 1] = (xh * yf - xf * yh) / 2 * (xh * zf - xf * zh)
        # q_inv[4, 2] = (xf - xh) / 2 * (xh * zf - xf * zh)
        # q_inv[4, 3] = (yf - yh) / 2 * (xh * zf - xf * zh)
        # q_inv[4, 4] = (zf - zh) / 2 * (xh * zf - xf * zh)
        # q_inv[4, 5] = 0
        #
        # q_inv[5, 0] = ((zf + zh) * (yf * zh - yh * zf)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[5, 1] = (yf * xh * (zf - zh) + xf * ((zf + zh) * yh - 2 * yf * zh)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[5, 2] = ((xf + xh) * (zh - zf)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[5, 3] = (zf + zh) / 2 * (xf * zh - xh * zf)
        # q_inv[5, 4] = ((zf + zh) * (zh - zf)) / 2 * (yf - yh) * (xh * zf - xf * zh)
        # q_inv[5, 5] = 0
        q_inv = np.array([[(xf * yf * zh - xf * yh * zf - 2 * xf * yh * zh + xh * yf * zh + xh * yh * zf) / (
                2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           (xf ** 2 * yh - xh ** 2 * yf - xf * xh * yf + xf * xh * yh) / (
                                   2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           -((xf + xh) * (xf - xh)) / (2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           -(xf + xh) / (2 * (xf * zh - xh * zf)),
                           -((zf + zh) * (xf - xh)) / (2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           (xf - xh) / (2 * (yf - yh))],
                          [(yf * zh - yh * zf) / (2 * (xf * zh - xh * zf)),
                           (xf * yh - xh * yf) / (2 * (xf * zh - xh * zf)), -(xf - xh) / (2 * (xf * zh - xh * zf)),
                           -(yf - yh) / (2 * (xf * zh - xh * zf)), -(zf - zh) / (2 * (xf * zh - xh * zf)), 1 / 2],
                          [((yf * zh - yh * zf) * (zf + zh)) / (
                                  2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           -(xh * yf * zf - xf * yh * zf + xf * yh * zh + xh * yf * zh - 2 * xh * yh * zf) / (
                                   2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           -((xf + xh) * (zf - zh)) / (2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           -(zf + zh) / (2 * (xf * zh - xh * zf)),
                           -((zf + zh) * (zf - zh)) / (2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           (zf - zh) / (2 * (yf - yh))],
                          [(xf * yf * zh + xf * yh * zf - 2 * xh * yf * zf - xh * yf * zh + xh * yh * zf) / (
                                  2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           -(xf ** 2 * yh - xh ** 2 * yf - xf * xh * yf + xf * xh * yh) / (
                                   2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           ((xf + xh) * (xf - xh)) / (2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           (xf + xh) / (2 * (xf * zh - xh * zf)),
                           ((zf + zh) * (xf - xh)) / (2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           -(xf - xh) / (2 * (yf - yh))],
                          [(yf * zh - yh * zf) / (2 * (xf * zh - xh * zf)),
                           (xf * yh - xh * yf) / (2 * (xf * zh - xh * zf)), -(xf - xh) / (2 * (xf * zh - xh * zf)),
                           -(yf - yh) / (2 * (xf * zh - xh * zf)), -(zf - zh) / (2 * (xf * zh - xh * zf)), -1 / 2],
                          [-((yf * zh - yh * zf) * (zf + zh)) / (
                                  2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           -(xf * yh * zf - 2 * xf * yf * zh + xh * yf * zf + xf * yh * zh - xh * yf * zh) / (
                                   2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           ((xf + xh) * (zf - zh)) / (2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           (zf + zh) / (2 * (xf * zh - xh * zf)),
                           ((zf + zh) * (zf - zh)) / (2 * (xf * yf * zh - xh * yf * zf - xf * yh * zh + xh * yh * zf)),
                           -(zf - zh) / (2 * (yf - yh))]
                          ])
        return q_inv

    def update_food_touch_sensor(self):
        self.is_touching = all_is_foot_touching()

    def update_theta(self):
        self.theta = get_all_motor_angle()

    # 相位切换, 通过时间和足底传感器确定支撑对角腿和摆动对角腿
    def phase_swap(self):
        if self.time > 0.75 * self.Tf:
            if self.standFoot == self.L:
                if self.is_touching == [1, 1, 1, 1]:
                    self.standFoot = self.R
                    self.swallFoot = self.L
                    self.time = 0
                    # print("L-->R")

            elif self.standFoot == self.R:
                if self.is_touching == [1, 1, 1, 1]:
                    self.standFoot = self.L
                    self.swallFoot = self.R
                    self.time = 0
                    # print("R-->L")
            elif self.standFoot == 4:
                if self.is_touching == [1, 1, 1, 1]:
                    self.standFoot = 3
                    self.swallFoot = 3
                    self.stop = 1
                    self.time = 0
                    # print("悬空-->四脚着地")
            elif self.standFoot == 3:
                if self.is_touching == [1, 1, 1, 1] and self.stop == 0:
                    self.standFoot = self.R
                    self.swallFoot = self.L
                    self.time = 0
                    # print("四脚着地-->行进")
            if self.is_touching == [1, 1, 1, 1] and self.stop == 1:
                self.standFoot = 3
                self.swallFoot = 3
                self.time = 0
                # print("任意-->四脚着地")
            if self.is_touching == [0, 0, 0, 0]:  # and self.stop == 0
                self.fly_time += 0.001 * timestep
                if self.fly_time > 0.09:
                    self.standFoot = 4
                    self.swallFoot = 4
                    self.stop = 1
                    self.fly_time = 0
                    self.time = 0
                    # print("任意-->悬空")

    # 更新全部状态
    def update_robot_state(self):
        self.key_control()
        # 更新IMU及导数
        self.update_IMU()
        # 足底接触传感器更新
        self.update_food_touch_sensor()
        # 更新关节角
        self.update_theta()
        # 更新四条腿的运动学正解
        for leg in range(4):
            for joint in range(3):
                self.pos[leg] = self.forwardkinematics(self.theta[leg])
        self.update_V_P()
        self.phase_swap()
        self.time += timestep * 0.001

    # IMU获得欧拉角
    def update_IMU(self):
        # print("pre roll pitch yaw", self.pre_eulerAngle)
        eulerAngle = get_IMU_Angle()  # Roll Pitch Yaw 当前欧拉角
        # print("roll pitch yaw",eulerAngle)
        self.Roll = eulerAngle[0]  # 获得当前roll
        self.dot_Roll = (eulerAngle[0] - self.pre_eulerAngle[0]) / (0.001 * timestep)  # 求导数 dot_roll
        self.dot_Roll = self.dot_Roll * 0.3 + self.dot_Roll_pre * 0.7
        self.dot_Roll_pre = self.dot_Roll  # 更新记录上次的变量 dot_Roll_pre

        self.Pitch = eulerAngle[1]  # 获得当前pitch
        self.dot_Pitch = (eulerAngle[1] - self.pre_eulerAngle[1]) / (0.001 * timestep)  # 求导数 dot_pitch
        self.dot_Pitch = self.dot_Pitch * 0.3 + self.dot_Pitch_pre * 0.7  # 低通滤波
        self.dot_Pitch_pre = self.dot_Pitch  # 更新记录上次的变量 dot_Pitch_pre

        self.Yaw = eulerAngle[2]  # 获得当前yaw
        self.dot_Yaw = (eulerAngle[2] - self.pre_eulerAngle[2]) / (0.001 * timestep)  # 求导数 dot_yaw
        self.dot_Yaw = self.dot_Yaw * 0.3 + self.dot_Yaw_pre * 0.7  # 低通滤波
        self.dot_Yaw_pre = self.dot_Yaw  # 更新记录上次的变量 dot_Yaw_pre

        self.pre_eulerAngle = copy.deepcopy(eulerAngle)

    # 速度,加速度更新
    def update_V_P(self):
        dot_pos = (((np.array(self.pos) - np.array(self.pre_pos))
                    / (0.001 * timestep)) * 1.0 + np.array(self.pre_dot_pos) * 0).tolist()
        # 上一步坐标
        self.pre_pos = copy.deepcopy(self.pos)
        # 对速度求导 所有腿和关节 加速度
        dot_2_pos = ((np.array(dot_pos) - np.array(self.pre_dot_pos)) / (0.001 * timestep)).tolist()
        # 上一步导数
        self.pre_dot_pos = copy.deepcopy(dot_pos)
        self.dot_pos = copy.deepcopy(dot_pos)
        self.dot_2_pos = copy.deepcopy(dot_2_pos)
        pass

    # 键盘控制
    def key_control(self):
        key = KeyBoard.getKey()
        if key == KeyBoard.UP:
            self.Pitch_des += 0.05 / 180.0 * math.pi
            print(self.Pitch_des)
        elif key == KeyBoard.DOWN:
            self.Pitch_des -= 0.05 / 180.0 * math.pi
            print(self.Pitch_des)
        elif key == KeyBoard.LEFT:
            self.Roll_des -= 0.05 / 180.0 * math.pi
        elif key == KeyBoard.RIGHT:
            self.Roll_des += 0.05 / 180.0 * math.pi
        elif key == ord('M'):
            self.Yaw_des -= 0.05 / 180.0 * math.pi
        elif key == ord('N'):
            self.Yaw_des += 0.05 / 180.0 * math.pi

        elif key == ord('P'):
            self.stop = 1
            self.Pitch_des = 0
            self.Roll_des = 0
            self.Yaw_des = self.Yaw / 180.0 * math.pi
        # 纯平移
        elif key == ord('W'):
            self.stop = 0
            self.Vx_des = self.acc(0.0004, self.Vx_des, -self.Vx)
            # print(self.Vx_des)
        elif key == ord('S'):
            self.stop = 0
            self.Vx_des = self.acc(0.0004, self.Vx_des, self.Vx)
        elif key == ord('A'):
            self.Vx_des = self.acc(0.0004, self.Vx_des, 0)
            self.Vy_des = self.acc(0.04, self.Vy_des, -self.Vy)
            self.stop = 0
        elif key == ord('D'):
            self.Vx_des = self.acc(0.0004, self.Vx_des, 0)
            self.Vy_des = self.acc(0.04, self.Vy_des, self.Vy)
            self.stop = 0
        elif key == ord('Q'):
            self.stop = 0
            self.Vx_des = self.acc(0.0004, self.Vx_des, -self.Vx)
            self.Vy_des = self.acc(0.04, self.Vy_des, -self.Vy)
        elif key == ord('E'):
            self.stop = 0
            self.Vx_des = self.acc(0.0004, self.Vx_des, -self.Vx)
            self.Vy_des = self.acc(0.04, self.Vy_des, self.Vy)

        elif key == ord('Z'):
            self.stop = 0
            self.Vx_des = self.acc(0.0004, self.Vx_des, self.Vx)
            self.Vy_des = self.acc(0.04, self.Vy_des, -self.Vy)
        elif key == ord('C'):
            self.stop = 0
            self.Vx_des = self.acc(0.0004, self.Vx_des, self.Vx)
            self.Vy_des = self.acc(0.04, self.Vy_des, self.Vy)
            # 选装平移
        elif key == ord('J'):
            self.Vx_des = self.acc(0.0004, self.Vx_des, 0)
            self.W_des = self.acc(0.05 / 180.0 * math.pi, self.W_des, -self.W / 180.0 * math.pi)
            self.stop = 0
        elif key == ord('L'):
            self.Vx_des = self.acc(0.0004, self.Vx_des, 0)
            self.W_des = self.acc(0.05 / 180.0 * math.pi, self.W_des, self.W / 180.0 * math.pi)
            self.stop = 0
        elif key == ord('U'):
            self.Vx_des = self.acc(0.0004, self.Vx_des, -self.Vx)
            self.W_des = self.acc(0.05 / 180.0 * math.pi, self.W_des, -self.W / 180.0 * math.pi)

            self.stop = 0
        elif key == ord('O'):
            self.Vx_des = self.acc(0.0004, self.Vx_des, -self.Vx)
            self.W_des = self.acc(0.05 / 180.0 * math.pi, self.W_des, self.W / 180.0 * math.pi)
            self.stop = 0
            # 高度调整
        elif key == ord('Y'):
            self.H_des -= 0.0001 * timestep
            self.zh = self.H_des + 0.12
            print("目标 ", self.H_des, "当前", self.pos[0][2])
            print("当前方位角 ROLL Pitch Yaw ", self.Roll, self.Pitch, self.Yaw)
        elif key == ord('H'):
            self.H_des += 0.0001 * timestep
            self.zh = self.H_des + 0.12
            print(self.H_des)
            print("目标 ", self.H_des, "当前", self.pos[0][2])
        else:
            # self.stop = 0
            self.Vx_des = self.acc(0.0004, self.Vx_des, -0.07)
            # self.Pitch_des = self.acc(0.00004, self.Pitch_des, 0)
            self.W_des = self.acc(0.05, self.W_des, 0)
            self.Vy_des = self.acc(0.04, self.Vy_des, 0)

    def acc(self, acc_value, dot, vel):
        value = dot
        if (dot < vel):
            value += acc_value
            if (dot > vel):
                value = vel
        else:
            value -= acc_value
            if (dot < vel):
                value = vel
        return value

    # 轨迹
    def curve(self, xt, yt, init_pos, init_dotpos):
        ft = [0, 0, 0]  # x,z
        dft = [0, 0, 0]  # x,z
        xT = xt
        yT = yt
        t = self.time
        x0 = init_pos[0]
        y0 = init_pos[1]
        z0 = init_pos[2]
        dx0 = init_dotpos[0]
        dy0 = init_dotpos[1]
        Tf = self.Tf
        zh = self.zh
        # // x, y
        if t < Tf / 4.0:
            ft[0] = -4 * dx0 * t * t / Tf + dx0 * t + x0
            dft[0] = -8 * dx0 * t / Tf + dx0
        elif (t >= Tf / 4.0) and (t < 3.0 * Tf / 4.0):

            ft[0] = (-4 * Tf * dx0 - 16 * xT + 16 * x0) * t * t * t / (Tf * Tf * Tf) + \
                    (7 * Tf * dx0 + 24 * xT - 24 * x0) * t * t / (Tf * Tf) + \
                    (-15 * Tf * dx0 - 36 * xT + 36 * x0) * t / (4 * Tf) + \
                    (9 * Tf * dx0 + 16 * xT) / 16
            dft[0] = (-4 * Tf * dx0 - 16 * xT + 16 * x0) * 3 * t * t / (Tf * Tf * Tf) + \
                     (7 * Tf * dx0 + 24 * xT - 24 * x0) * 2 * t / (Tf * Tf) + \
                     (-15 * Tf * dx0 - 36 * xT + 36 * x0) / (4 * Tf)
        else:
            ft[0] = xT
            dft[0] = 0
        # y
        if t < Tf / 4.0:
            ft[1] = -4 * dy0 * t * t / Tf + dy0 * t + y0
            dft[1] = -8 * dy0 * t / Tf + dy0
        elif (t >= Tf / 4.0) and (t < 3.0 * Tf / 4.0):

            ft[1] = (-4 * Tf * dy0 - 16 * yT + 16 * y0) * t * t * t / (Tf * Tf * Tf) + \
                    (7 * Tf * dy0 + 24 * yT - 24 * y0) * t * t / (Tf * Tf) + \
                    (-15 * Tf * dy0 - 36 * yT + 36 * y0) * t / (4 * Tf) + \
                    (9 * Tf * dy0 + 16 * yT) / 16
            dft[1] = (-4 * Tf * dy0 - 16 * yT + 16 * y0) * 3 * t * t / (Tf * Tf * Tf) + \
                     (7 * Tf * dy0 + 24 * yT - 24 * y0) * 2 * t / (Tf * Tf) + \
                     (-15 * Tf * dy0 - 36 * yT + 36 * y0) / (4 * Tf)
        else:
            ft[1] = yT
            dft[1] = 0

        # // z
        if t < Tf / 2.0:
            ft[2] = 16 * (z0 - zh) * t * t * t / (Tf * Tf * Tf) + 12 * (zh - z0) * t * t / (Tf * Tf) + z0
            dft[2] = 16 * (z0 - zh) * 3 * t * t / (Tf * Tf * Tf) + 12 * (zh - z0) * 2 * t / (Tf * Tf)
        elif (t >= Tf / 2.0) and (t < 3.0 * Tf / 4.0):
            ft[2] = 4 * (z0 - zh) * t * t / (Tf * Tf) - 4 * (z0 - zh) * t / Tf + z0
            dft[2] = 4 * (z0 - zh) * 2 * t / (Tf * Tf) - 4 * (z0 - zh) / Tf
        else:
            ft[2] = 4 * (z0 - zh) * t * t / (Tf * Tf) - 4 * (z0 - zh) * t / Tf + z0
            dft[2] = 4 * (z0 - zh) * 2 * t / (Tf * Tf) - 4 * (z0 - zh) / Tf

        return [ft, dft]

    def run(self):
        init_pos_sw = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]  # 左右前后
        init_dotpos_sw = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]  # 左右前后

        path_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]  # 左右前后
        dot_path_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]  # 左右前后
        webot_device_init()
        switch = 0
        while robot.step(timestep) != -1:
            self.update_robot_state()
            # 获取支撑腿和摆动腿状态
            sw = [0, 0, 0, 0, 0]  # 摆动足 腿序号 左,右,前,后,特殊位
            st = [0, 0, 0, 0, 0]  # 支撑足 腿序号 左,右,前,后,特殊位
            # 左脚着地
            if self.standFoot == self.L:  # 左对角线

                st[0] = 0  # 左
                st[1] = 2  # 右
                st[2] = 0  # 前
                st[3] = 2  # 后

                sw[0] = 3  # 左
                sw[1] = 1  # 右
                sw[2] = 1  # 前
                sw[3] = 3  # 后
            # 右脚着地
            elif self.standFoot == self.R:  # 右对角线
                st[0] = 3  # 左
                st[1] = 1  # 右
                st[2] = 1  # 前
                st[3] = 3  # 后

                sw[0] = 0  # 左
                sw[1] = 2  # 右
                sw[2] = 0  # 前
                sw[3] = 2  # 后
            # 四脚着地
            elif self.standFoot == 3:
                st[0] = 3  # 左
                st[1] = 1  # 右
                st[2] = 1  # 前
                st[3] = 3  # 后

                sw[0] = 0  # 左
                sw[1] = 2  # 右
                sw[2] = 0  # 前
                sw[3] = 2  # 后
                st[4] = 100
            # 四脚悬空
            elif self.standFoot == 4:
                sw[4] = 200
            # print(self.standFoot, 'sw', sw)
            # 对角步态状态控----------------------------------------------------------------------------------对角步态状态控
            if st[4] == 0 and sw[4] == 0:
                # 支撑足 非stop
                # 计算姿态虚拟力
                pi_angle = math.atan2(self.pos[st[2]][2] - self.pos[st[3]][2],
                                      self.pos[st[2]][0] + 0.3 - self.pos[st[3]][
                                          0] + 0.3) - self.Pitch / 180.0 * math.pi
                # print("pi_angle",pi_angle/math.pi*180,"Pitch",self.Pitch)

                if abs(self.pos[st[2]][2] - self.pos[st[3]][2]) >= 0.16 and switch == 0:
                    switch = 1
                if switch == 1:
                    self.Pitch_des = self.acc(0.0002, self.Pitch_des, -pi_angle)
                    if abs(self.pos[st[2]][2] - self.pos[st[3]][2]) <= 0.0001:
                        switch = 0
                else:
                    # self.Pitch_des = 0
                    switch = 0

                F_pitch = self.Kpitch_r * (self.Pitch_des - self.Pitch / 180.0 * math.pi) + \
                          self.Dpitch_r / 2 * (0 - self.dot_Pitch / 180.0 * math.pi)
                F_roll = self.Kroll_r * (self.Roll_des - self.Roll / 180.0 * math.pi) + \
                         self.Droll_r * (0 - self.dot_Roll / 180.0 * math.pi)
                if not self.W_des == 0:
                    F_yaw = (self.Kyaw_r * (
                            self.W_des - (self.dot_Yaw * 0.5 + self.dot_Yaw_pre * 0.5) / 180.0 * math.pi))
                else:
                    F_yaw = 0

                # 高低叠加控制姿态
                K_pi_z = 0.01
                H_des_front = + K_pi_z * F_pitch
                H_des_back = - K_pi_z * F_pitch

                K_roll_z = 0.01  # 0.01
                H_des_left = - K_roll_z * F_roll
                H_des_right = + K_roll_z * F_roll

                Kyaw_x = 0.0003
                Vx_des_left = self.Vx_des - Kyaw_x * F_yaw
                Vx_des_right = self.Vx_des + Kyaw_x * F_yaw

                Kyaw_y = 0.000005  # 0.000001
                Vy_des_front = self.Vy_des + Kyaw_y * F_yaw
                Vy_des_back = self.Vy_des - Kyaw_y * F_yaw

                Vy_left = 0
                Vy_right = 0
                Hz_left = self.H_des
                Hz_right = self.H_des
                # 左前右后对应
                if st.index(st[2]) == 0:
                    Hz_left = self.H_des + H_des_left + H_des_front
                    Hz_right = self.H_des + H_des_right + H_des_back

                    Vy_left = Vy_des_front
                    Vy_right = Vy_des_back
                # 左后右前对应
                elif st.index(st[2]) == 1:
                    Hz_left = self.H_des + H_des_left + H_des_back
                    Hz_right = self.H_des + H_des_right + H_des_front

                    Vy_left = Vy_des_back
                    Vy_right = Vy_des_front

                    # 计算X轴虚拟力
                Fx_left = self.Kx * (Vx_des_left - self.dot_pos[st[0]][0]) \
                          + self.M * 9.8 * math.sin(self.Pitch / 180.0 * math.pi) * self.mass_center
                Fx_right = self.Kx * (Vx_des_right - self.dot_pos[st[1]][0]) \
                           + self.M * 9.8 * math.sin(self.Pitch / 180.0 * math.pi) * (1 - self.mass_center)

                # 支撑腿Y控制
                # init_pos_st[0][1]
                Fy_left = 0 * self.Ky * (0 - self.pos[st[0]][1]) + \
                          self.Dy * (Vy_left - self.dot_pos[st[0]][1]) \
                          + self.M * 9.81 * math.sin(self.Roll / 180.0 * math.pi) * self.mass_center
                Fy_right = 0 * self.Ky * (0 - self.pos[st[1]][1]) + \
                           self.Dy * (Vy_right - self.dot_pos[st[1]][1]) \
                           + self.M * 9.81 * math.sin(self.Roll / 180.0 * math.pi) * (1 - self.mass_center)

                Fz_left = self.Kz * (Hz_left - self.pos[st[0]][2]) + \
                          self.Dz * (0 - self.dot_pos[st[0]][2]) \
                          - self.M * 9.81 * self.mass_center * math.cos(self.Pitch / 180.0 * math.pi)
                Fz_right = self.Kz * (Hz_right - self.pos[st[1]][2]) + \
                           self.Dz * (0 - self.dot_pos[st[1]][2]) \
                           - self.M * 9.81 * (1 - self.mass_center) * math.cos(self.Pitch / 180.0 * math.pi)

                T_left = self.create_transJ(self.theta[st[0]]) @ np.array([[Fx_left], [Fy_left], [Fz_left]])
                T_right = self.create_transJ(self.theta[st[1]]) @ np.array([[Fx_right], [Fy_right], [Fz_right]])
                KR = 1
                set_motor_torque(st[0], 0, T_left[0, 0] - KR * F_roll / 2)
                set_motor_torque(st[0], 1, T_left[1, 0])  # -KR*F_roll/2
                set_motor_torque(st[0], 2, T_left[2, 0])

                set_motor_torque(st[1], 0, T_right[0, 0] - KR * F_roll / 2)
                set_motor_torque(st[1], 1, T_right[1, 0])
                set_motor_torque(st[1], 2, T_right[2, 0])

                # 摆动足--------------------------------------------------------------------------------------------------摆动足

                # 获得初始速度和位置

                if self.time == 0.001 * timestep:  # 刚刚切换过对角腿,记录此时的摆动足即可
                    init_pos_sw[0] = self.pos[sw[0]]
                    init_pos_sw[1] = self.pos[sw[1]]
                    init_pos_sw[2] = self.pos[sw[2]]
                    init_pos_sw[3] = self.pos[sw[3]]

                    init_dotpos_sw[0] = self.dot_pos[sw[0]]
                    init_dotpos_sw[1] = self.dot_pos[sw[1]]
                    init_dotpos_sw[2] = self.dot_pos[sw[2]]
                    init_dotpos_sw[3] = self.dot_pos[sw[3]]
                # print("初始点 初始速度", init_pos, init_dotpos)
                est_dot_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
                if not self.time == 0.001 * timestep:
                    est_dot_pos = (np.array(self.dot_pos) * 0.7 + np.array(self.pre_dot_pos) * 0.3).tolist()
                # print(est_dot_pos[st[2]][1])
                errorL = 0
                error_a = 0
                error_b = 0
                if abs(self.Vx_des - 0) <= 0.02:
                    errorL = 0.1
                elif self.Vx_des > 0.1 :
                    errorL = 0.1+ self.Vx_des * 0.375
                # elif self.Vx_des > 0.4:
                    # errorL =0.05+ self.Vx_des * 0.4
                    # print(errorL)
                else:
                    errorL = self.Vx_des * 0.15
                # 上坡重心修正
                if abs(self.Pitch) > 10 / 180.0 * math.pi:
                    temp = -math.tan(self.Pitch / 180.0 * math.pi) * (self.pos[st[2]][2] + self.pos[st[3]][2]) * 0.5*1.3
                    error_a = self.acc(0.006, error_a, temp)
                if abs(self.Roll) > 10 / 180.0 * math.pi:
                    temp = math.tan(self.Roll / 180.0 * math.pi) * (self.pos[st[2]][2] + self.pos[st[3]][2]) * 0.5
                    error_b = self.acc(0.006, error_b, temp)

                xt = [0.2, 0.2]  # 落足点 前后
                xt[0] = est_dot_pos[st[2]][0] * self.Ts / 2.0 - 1*self.Kvx * (
                        self.dot_pos[st[2]][0] - Vx_des_left) - errorL + error_a
                xt[1] = est_dot_pos[st[3]][0] * self.Ts / 2.0 - 1*self.Kvx * (
                        self.dot_pos[st[3]][0] - Vx_des_right) - errorL + error_a

                yt = [0, 0]  # 落足点 前后
                yt[0] = est_dot_pos[st[2]][1] * self.Ts / 2.0 - self.Kvy * (
                        self.dot_pos[st[2]][1] - Vy_des_front) + error_b
                yt[1] = est_dot_pos[st[3]][1] * self.Ts / 2.0 - self.Kvy * (
                        self.dot_pos[st[3]][1] - Vy_des_back) + error_b

                # 落足点转换
                yT = [0, 0]  # 落足点 左右

                xT = [0, 0]  # 落足点 左右
                if st.index(st[2]) == 0:
                    yT[0] = yt[0]
                    yT[1] = yt[1]
                    xT[0] = xt[0]
                    xT[1] = xt[1]
                # 左后右前对应
                elif st.index(st[2]) == 1:
                    yT[0] = yt[1]
                    yT[1] = yt[0]
                    xT[0] = xt[1]
                    xT[1] = xt[0]

                # 中途摆动触底
                # 左
                if self.is_touching[sw[0]] == 1 and self.time > 0.5 * self.Tf:
                    path_pos[0], dot_path_pos[0] = self.pos[sw[0]], [0, 0, 0]
                    # pass
                else:
                    path_pos[0], dot_path_pos[0] = self.curve(xT[0], yT[0], init_pos_sw[0], init_dotpos_sw[0])
                    # 右
                if self.is_touching[sw[1]] == 1 and self.time > 0.5 * self.Tf:
                    path_pos[1], dot_path_pos[1] = self.pos[sw[1]], [0, 0, 0]
                else:
                    path_pos[1], dot_path_pos[1] = self.curve(xT[1], yT[1], init_pos_sw[1], init_dotpos_sw[1])

                # path_pos = [[0, 0, -0.45], [0, 0, -0.45], [0, 0, -0.45], [0, 0, -0.45]]  # 左右前后
                # dot_path_pos = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]  # 左右前后
                # ax.cla()   # 清除键
                # ax.plot(path_pos[0][0],path_pos[0][2], label='test')
                # ax.legend()
                # 左摆动足 索引值sw[0]
                Fx_left_sw = self.Kxk * (path_pos[0][0] - self.pos[sw[0]][0]) + \
                             self.Dxk * (dot_path_pos[0][0] - self.dot_pos[sw[0]][0]) \
                             + 8 * 9.8 * math.sin(self.Pitch / 180.0 * math.pi)
                # 右摆动足 索引值sw[1]
                Fx_right_sw = self.Kxk * (path_pos[1][0] - self.pos[sw[1]][0]) + \
                              self.Dxk * (dot_path_pos[1][0] - self.dot_pos[sw[1]][0]) \
                              + 8 * 9.8 * math.sin(self.Pitch / 180.0 * math.pi)

                Fy_left_sw = self.Kyk * (path_pos[0][1] - self.pos[sw[0]][1]) + \
                             self.Dyk * (dot_path_pos[0][1] - self.dot_pos[sw[0]][1]) \
                             + 8 * 9.8 * math.sin(self.Roll / 180.0 * math.pi)
                # 后摆动足 索引值sw[3]
                Fy_right_sw = self.Kyk * (path_pos[1][1] - self.pos[sw[1]][1]) + \
                              self.Dyk * (dot_path_pos[1][1] - self.dot_pos[sw[1]][1]) \
                              + 8 * 9.8 * math.sin(self.Roll / 180.0 * math.pi)

                if self.time <= 0.55 * self.Tf:
                    KKZ = self.Kzk
                    KKD = self.Dzk
                else:
                    KKZ = 1000
                    KKD = 100

                Fz_left_sw = KKZ * (path_pos[0][2] - self.pos[sw[0]][2]) + \
                             KKD * (dot_path_pos[0][2] - self.dot_pos[sw[0]][2]) - 8 * 9.81 * math.cos(
                    self.Pitch / 180.0 * math.pi)

                Fz_right_sw = KKZ * (path_pos[1][2] - self.pos[sw[1]][2]) + \
                              KKD * (dot_path_pos[1][2] - self.dot_pos[sw[1]][2]) - 8 * 9.81 * math.cos(
                    self.Pitch / 180.0 * math.pi)

                T_left_sw = self.create_transJ(self.theta[sw[0]]) @ np.array(
                    [[Fx_left_sw], [Fy_left_sw], [Fz_left_sw]])
                T_right_sw = self.create_transJ(self.theta[sw[1]]) @ np.array(
                    [[Fx_right_sw], [Fy_right_sw], [Fz_right_sw]])

                set_motor_torque(sw[0], 0, T_left_sw[0, 0])
                set_motor_torque(sw[0], 1, T_left_sw[1, 0])
                set_motor_torque(sw[0], 2, T_left_sw[2, 0])

                set_motor_torque(sw[1], 0, T_right_sw[0, 0])
                set_motor_torque(sw[1], 1, T_right_sw[1, 0])
                set_motor_torque(sw[1], 2, T_right_sw[2, 0])

            # 四足站立状态控制------------------------------------------------------------------------------------------四足站立状态控制
            if st[4] == 100:
                # print("run")

                T_pitch = self.Kpitch * (self.Pitch_des - self.Pitch / 180.0 * math.pi) + \
                          self.Dpitch / 2 * (0 - self.dot_Pitch / 180.0 * math.pi)
                T_roll = self.Kroll * (self.Roll_des - self.Roll / 180.0 * math.pi) + \
                         self.Droll * (0 - self.dot_Roll / 180.0 * math.pi)
                K_pi_z = 0.01  # 0.02
                H_des_front = + K_pi_z * T_pitch / 2
                H_des_back = - K_pi_z * T_pitch / 2

                K_roll_z = 0.01
                H_des_left = - K_roll_z * T_roll / 2
                H_des_right = + K_roll_z * T_roll / 2

                Fz_left_F = self.Kzs * (self.H_des + H_des_left + H_des_front - self.pos[0][2]) + self.Dzs * (
                        0 - self.dot_pos[0][2])
                Fz_right_F = self.Kzs * (self.H_des + H_des_right + H_des_front - self.pos[1][2]) + self.Dzs * (
                        0 - self.dot_pos[1][2])
                Fz_left_B = self.Kzs * (self.H_des + H_des_left + H_des_back - self.pos[3][2]) + self.Dzs * (
                        0 - self.dot_pos[3][2])
                Fz_right_B = self.Kzs * (self.H_des + H_des_right + H_des_back - self.pos[2][2]) + self.Dzs * (
                        0 - self.dot_pos[2][2])

                Fz_left_F = Fz_left_F - self.M * 10 / 4 * math.cos(self.Pitch / 180.0 * math.pi)
                Fz_right_F = Fz_right_F - self.M * 10 / 4 * math.cos(self.Pitch / 180.0 * math.pi)
                Fz_left_B = Fz_left_B - self.M * 10 / 4 * math.cos(self.Pitch / 180.0 * math.pi)
                Fz_right_B = Fz_right_B - self.M * 10 / 4 * 2 * math.cos(self.Pitch / 180.0 * math.pi)

                T_yaw = self.Kyaw * (self.Yaw_des - self.Yaw / 180.0 * math.pi) + \
                        self.Dyaw * (0 - self.dot_Yaw / 180.0 * math.pi)

                K_y = 0.01
                k_r2y = 0.009
                Y_des_front = - K_y * T_yaw / 2
                Y_des_back = + K_y * T_yaw / 2
                Y_des_left = +k_r2y * T_roll / 2
                Y_des_right = -k_r2y * T_roll / 2

                K_x = 0.002
                k_p2x = 0.001
                X_des_left = + K_x * T_yaw / 2
                X_des_right = - K_x * T_yaw / 2
                X_des_front = 0.07 + k_p2x * T_pitch / 2
                X_des_back = -0.07 - k_p2x * T_pitch / 2

                # print("run3")kpx * (0.0 - x) + kdx * (0 - dx)
                Fx_left_F = self.Kxs * (X_des_left + X_des_front - self.pos[0][0]) \
                            + self.Dxs * (0.0 - self.dot_pos[0][0])
                Fx_right_F = self.Kxs * (X_des_right + X_des_front - self.pos[1][0]) \
                             + self.Dxs * (0.0 - self.dot_pos[1][0])
                Fx_left_B = self.Kxs * (X_des_left + X_des_back - self.pos[3][0]) \
                            + self.Dxs * (0.0 - self.dot_pos[3][0])
                Fx_right_B = self.Kxs * (X_des_right + X_des_back - self.pos[2][0]) \
                             + self.Dxs * (0.0 - self.dot_pos[2][0])

                Fy_left_F = self.Kys * (Y_des_front + Y_des_left - self.pos[0][1]) \
                            + self.Dys * (0.0 - self.dot_pos[0][1])
                Fy_right_F = self.Kys * (Y_des_front + Y_des_right - self.pos[1][1]) \
                             + self.Dys * (0.0 - self.dot_pos[1][1])
                Fy_left_B = self.Kys * (Y_des_back + Y_des_left - self.pos[3][1]) \
                            + self.Dys * (0.0 - self.dot_pos[3][1])
                Fy_right_B = self.Kys * (Y_des_back + Y_des_right - self.pos[2][1]) \
                             + self.Dys * (0.0 - self.dot_pos[2][1])

                T_left_F = self.create_transJ(self.theta[0]) @ np.array([[Fx_left_F], [Fy_left_F], [Fz_left_F]])
                T_left_B = self.create_transJ(self.theta[3]) @ np.array([[Fx_left_B], [Fy_left_B], [Fz_left_B]])
                T_right_F = self.create_transJ(self.theta[1]) @ np.array([[Fx_right_F], [Fy_right_F], [Fz_right_F]])
                T_right_B = self.create_transJ(self.theta[2]) @ np.array([[Fx_right_B], [Fy_right_B], [Fz_right_B]])

                set_motor_torque(0, 0, float(T_left_F[0, 0]))
                set_motor_torque(0, 1, float(T_left_F[1, 0]))
                set_motor_torque(0, 2, float(T_left_F[2, 0]))

                set_motor_torque(1, 0, float(T_right_F[0, 0]))
                set_motor_torque(1, 1, float(T_right_F[1, 0]))
                set_motor_torque(1, 2, float(T_right_F[2, 0]))

                set_motor_torque(2, 0, float(T_right_B[0, 0]))
                set_motor_torque(2, 1, float(T_right_B[1, 0]))
                set_motor_torque(2, 2, float(T_right_B[2, 0]))

                set_motor_torque(3, 0, float(T_left_B[0, 0]))
                set_motor_torque(3, 1, float(T_left_B[1, 0]))
                set_motor_torque(3, 2, float(T_left_B[2, 0]))

                pass
            # 四足悬空状态控制------------------------------------------------------------------------------------------四足悬空状态控制
            elif sw[4] == 200:  # 全悬空
                # print("run3")
                Fx_left_F = self.Kxk * (0.0 - self.pos[0][0]) + self.Dxk * (0.0 - self.dot_pos[0][0])
                Fx_right_F = self.Kxk * (0.0 - self.pos[1][0]) + self.Dxk * (0.0 - self.dot_pos[1][0])
                Fx_left_B = self.Kxk * (0.0 - self.pos[3][0]) + self.Dxk * (0.0 - self.dot_pos[3][0])
                Fx_right_B = self.Kxk * (0.0 - self.pos[2][0]) + self.Dxk * (0.0 - self.dot_pos[2][0])

                Fy_left_F = self.Kxk * (0.0 - self.pos[0][1]) + self.Dxk * (0.0 - self.dot_pos[0][1])
                Fy_right_F = self.Kxk * (0.0 - self.pos[1][1]) + self.Dxk * (0.0 - self.dot_pos[1][1])
                Fy_left_B = self.Kxk * (0.0 - self.pos[3][1]) + self.Dxk * (0.0 - self.dot_pos[3][1])
                Fy_right_B = self.Kxk * (0.0 - self.pos[2][1]) + self.Dxk * (0.0 - self.dot_pos[2][1])

                Fz_left_F = self.Kzk * (self.H_des - self.pos[0][2]) + self.Dzk * (0 - self.dot_pos[0][2])
                Fz_right_F = self.Kzk * (self.H_des - self.pos[1][2]) + self.Dzk * (0 - self.dot_pos[1][2])
                Fz_left_B = self.Kzk * (self.H_des - self.pos[3][2]) + self.Dzk * (0 - self.dot_pos[3][2])
                Fz_right_B = self.Kzk * (self.H_des - self.pos[2][2]) + self.Dzk * (0 - self.dot_pos[2][2])

                T_left_F = self.create_transJ(self.theta[0]) @ np.array([[Fx_left_F], [Fy_left_F], [Fz_left_F]])
                T_left_B = self.create_transJ(self.theta[3]) @ np.array([[Fx_left_B], [Fy_left_B], [Fz_left_B]])
                T_right_F = self.create_transJ(self.theta[1]) @ np.array([[Fx_right_F], [Fy_right_F], [Fz_right_F]])
                T_right_B = self.create_transJ(self.theta[2]) @ np.array([[Fx_right_B], [Fy_right_B], [Fz_right_B]])

                set_motor_torque(0, 0, float(T_left_F[0, 0]))
                set_motor_torque(0, 1, float(T_left_F[1, 0]))
                set_motor_torque(0, 2, float(T_left_F[2, 0]))

                set_motor_torque(1, 0, float(T_right_F[0, 0]))
                set_motor_torque(1, 1, float(T_right_F[1, 0]))
                set_motor_torque(1, 2, float(T_right_F[2, 0]))

                set_motor_torque(2, 0, float(T_right_B[0, 0]))
                set_motor_torque(2, 1, float(T_right_B[1, 0]))
                set_motor_torque(2, 2, float(T_right_B[2, 0]))

                set_motor_torque(3, 0, float(T_left_B[0, 0]))
                set_motor_torque(3, 1, float(T_left_B[1, 0]))
                set_motor_torque(3, 2, float(T_left_B[2, 0]))


if __name__ == '__main__':
    q = Quadruped_robot_mix()
    # webot_device_init()
    q.run()

  • 36
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值