• V-REP和Python的联合仿真


    机器人仿真软件 各类免费的的机器人仿真软件优缺点汇总_robot 仿真 软件收费么_dyannacon的博客-CSDN博客

    课程地址 https://class.guyuehome.com/p/t_pc/course_pc_detail/column/p_605af87be4b007b4183a42e7

    课程资料 guyueclass: 古月学院课程代码

    旋转变换 旋转的左乘与右乘 - 知乎

    四足机器人站立控制原理 【基础知识】四足机器人的站立姿态控制原理 - 知乎

    单腿逆解参考 https://github.com/richardbloemenkamp/Robotdog

    Vrep文档

    Vrep放大object

    Vrep 导入模型步骤:

    1. plugins-->urdf import导入机器人URDF文件

    2. 删除机器人对象中的world_joint和world_link_visual

    3. 双击设置机器人参数

    碰撞参数设置:body参数设置,自身碰撞勾选前四个勾,leg参数设置,自身碰撞勾选后四个勾,即不计算与自身的碰撞关系

    设置关节参数

    调节颜色

    python联合仿真

    remote API路径:C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\programming\remoteApiBindings

    1. 选择仿真器

    2. 创建Vrep脚本用于远程连接

    3. 绑定脚本到机器人

    4. 编辑脚本,添加远程连接代码

    4. 编写python脚本并测试(将腿部足端位置转换为关节的角度)

    连接V-REP需要从remote API路径拷贝相关文件

    1. """
    2. 连接VREP Server并测试控制四足机器人
    3. """
    4. try:
    5. import sim
    6. except ImportError:
    7. print('--------------------------------------------------------------')
    8. print('"sim.py" could not be imported. This means very probably that')
    9. print('either "sim.py" or the remoteApi library could not be found.')
    10. print('Make sure both are in the same folder as this file,')
    11. print('or appropriately adjust the file "sim.py"')
    12. print('--------------------------------------------------------------')
    13. print('')
    14. sim = None
    15. import time
    16. import numpy as np
    17. def start_simulation():
    18. sim.simxFinish(-1)
    19. # 开启套接字与server进行通信
    20. clientID = sim.simxStart('127.0.0.1', 19999, True, True, 5000, 5)
    21. if clientID != -1:
    22. print('Connected to remote API server with ClientID ', clientID)
    23. # 开始模拟
    24. sim.simxStartSimulation(clientID, sim.simx_opmode_oneshot)
    25. return clientID
    26. else:
    27. return -1
    28. def get_joints(client_id):
    29. # 机器人电机力矩参数
    30. rotation_forces = [
    31. # RB
    32. [500, 500, 500],
    33. # RF
    34. [500, 500, 500],
    35. # LB
    36. [500, 500, 500],
    37. # LF
    38. [500, 500, 500]
    39. ]
    40. # 获取机器人关节对象句柄
    41. rec, rb_rot_1 = sim.simxGetObjectHandle(client_id, 'rb_rot_1', sim.simx_opmode_blocking)
    42. rec, rb_rot_2 = sim.simxGetObjectHandle(client_id, 'rb_rot_2', sim.simx_opmode_blocking)
    43. rec, rb_rot_3 = sim.simxGetObjectHandle(client_id, 'rb_rot_3', sim.simx_opmode_blocking)
    44. rec, rf_rot_1 = sim.simxGetObjectHandle(client_id, 'rf_rot_1', sim.simx_opmode_blocking)
    45. rec, rf_rot_2 = sim.simxGetObjectHandle(client_id, 'rf_rot_2', sim.simx_opmode_blocking)
    46. rec, rf_rot_3 = sim.simxGetObjectHandle(client_id, 'rf_rot_3', sim.simx_opmode_blocking)
    47. rec, lb_rot_1 = sim.simxGetObjectHandle(client_id, 'lb_rot_1', sim.simx_opmode_blocking)
    48. rec, lb_rot_2 = sim.simxGetObjectHandle(client_id, 'lb_rot_2', sim.simx_opmode_blocking)
    49. rec, lb_rot_3 = sim.simxGetObjectHandle(client_id, 'lb_rot_3', sim.simx_opmode_blocking)
    50. rec, lf_rot_1 = sim.simxGetObjectHandle(client_id, 'lf_rot_1', sim.simx_opmode_blocking)
    51. rec, lf_rot_2 = sim.simxGetObjectHandle(client_id, 'lf_rot_2', sim.simx_opmode_blocking)
    52. rec, lf_rot_3 = sim.simxGetObjectHandle(client_id, 'lf_rot_3', sim.simx_opmode_blocking)
    53. # 设置电机力矩
    54. rec = sim.simxSetJointForce(client_id, rb_rot_1, rotation_forces[0][0], sim.simx_opmode_blocking)
    55. rec = sim.simxSetJointForce(client_id, rb_rot_2, rotation_forces[0][1], sim.simx_opmode_blocking)
    56. rec = sim.simxSetJointForce(client_id, rb_rot_3, rotation_forces[0][2], sim.simx_opmode_blocking)
    57. rec = sim.simxSetJointForce(client_id, rf_rot_1, rotation_forces[1][0], sim.simx_opmode_blocking)
    58. rec = sim.simxSetJointForce(client_id, rf_rot_2, rotation_forces[1][1], sim.simx_opmode_blocking)
    59. rec = sim.simxSetJointForce(client_id, rf_rot_3, rotation_forces[1][2], sim.simx_opmode_blocking)
    60. rec = sim.simxSetJointForce(client_id, lb_rot_1, rotation_forces[2][0], sim.simx_opmode_blocking)
    61. rec = sim.simxSetJointForce(client_id, lb_rot_2, rotation_forces[2][1], sim.simx_opmode_blocking)
    62. rec = sim.simxSetJointForce(client_id, lb_rot_3, rotation_forces[2][2], sim.simx_opmode_blocking)
    63. rec = sim.simxSetJointForce(client_id, lf_rot_1, rotation_forces[3][0], sim.simx_opmode_blocking)
    64. rec = sim.simxSetJointForce(client_id, lf_rot_2, rotation_forces[3][1], sim.simx_opmode_blocking)
    65. rec = sim.simxSetJointForce(client_id, lf_rot_3, rotation_forces[3][2], sim.simx_opmode_blocking)
    66. return [rb_rot_1, rb_rot_2, rb_rot_3], \
    67. [rf_rot_1, rf_rot_2, rf_rot_3], \
    68. [lb_rot_1, lb_rot_2, lb_rot_3], \
    69. [lf_rot_1, lf_rot_2, lf_rot_3]
    70. def leg_inverse_kine(x, y, z):
    71. # h,hu和hl分别是单条腿杆件的长度
    72. h = 0.15
    73. hu = 0.35
    74. hl = 0.382
    75. dyz = np.sqrt(y**2 + z**2)
    76. lyz = np.sqrt(dyz**2 - h**2)
    77. gamma_yz = -np.arctan(y/z)
    78. gamma_h_offset = -np.arctan(h/lyz)
    79. gamma = gamma_yz - gamma_h_offset
    80. lxzp = np.sqrt(lyz**2 + x**2)
    81. n = (lxzp**2 - hl**2 - hu**2) / (2 * hu)
    82. beta = -np.arccos(n / hl)
    83. alfa_xzp = -np.arctan(x/lyz)
    84. alfa_off = np.arccos((hu + n) / lxzp)
    85. alfa = alfa_xzp + alfa_off
    86. return gamma, alfa, beta
    87. if __name__ == '__main__':
    88. # 机器人电机角度参数
    89. rb_poses = [40*np.pi/180, 0, 0]
    90. rf_poses = [0, 0, 0]
    91. lb_poses = [0, 0, 0]
    92. lf_poses = [0, 0, 0]
    93. client_id = start_simulation()
    94. if client_id != -1:
    95. joints = get_joints(client_id)
    96. rb_joints = joints[0]
    97. rf_joints = joints[1]
    98. lb_joints = joints[2]
    99. lf_joints = joints[3]
    100. time.sleep(1)
    101. timeout = 60
    102. start_time = time.time()
    103. curr_time = time.time()
    104. # 初始关节角度
    105. rb_poses = leg_inverse_kine(0, -0.3, -0.632)
    106. rf_poses = leg_inverse_kine(0, -0.3, -0.632)
    107. lb_poses = leg_inverse_kine(0, -0.3, -0.632)
    108. lf_poses = leg_inverse_kine(0, -0.3, -0.632)
    109. while curr_time - start_time < timeout:
    110. # 设置关节角度
    111. rec = sim.simxSetJointTargetPosition(client_id, rb_joints[0], -rb_poses[0], sim.simx_opmode_oneshot)
    112. rec = sim.simxSetJointTargetPosition(client_id, rb_joints[1], rb_poses[1], sim.simx_opmode_oneshot)
    113. rec = sim.simxSetJointTargetPosition(client_id, rb_joints[2], rb_poses[2], sim.simx_opmode_oneshot)
    114. rec = sim.simxSetJointTargetPosition(client_id, rf_joints[0], rf_poses[0], sim.simx_opmode_oneshot)
    115. rec = sim.simxSetJointTargetPosition(client_id, rf_joints[1], rf_poses[1], sim.simx_opmode_oneshot)
    116. rec = sim.simxSetJointTargetPosition(client_id, rf_joints[2], rf_poses[2], sim.simx_opmode_oneshot)
    117. rec = sim.simxSetJointTargetPosition(client_id, lb_joints[0], -lb_poses[0], sim.simx_opmode_oneshot)
    118. rec = sim.simxSetJointTargetPosition(client_id, lb_joints[1], lb_poses[1], sim.simx_opmode_oneshot)
    119. rec = sim.simxSetJointTargetPosition(client_id, lb_joints[2], lb_poses[2], sim.simx_opmode_oneshot)
    120. rec = sim.simxSetJointTargetPosition(client_id, lf_joints[0], lf_poses[0], sim.simx_opmode_oneshot)
    121. rec = sim.simxSetJointTargetPosition(client_id, lf_joints[1], lf_poses[1], sim.simx_opmode_oneshot)
    122. rec = sim.simxSetJointTargetPosition(client_id, lf_joints[2], lf_poses[2], sim.simx_opmode_oneshot)
    123. curr_time = time.time()
    124. # print("curr time :", curr_time - start_time)
    125. # 完成模拟
    126. sim.simxStopSimulation(client_id, sim.simx_opmode_blocking)
    127. sim.simxFinish(client_id)
    128. else:
    129. print('Failed connecting to remote API server')

    显示足端轨迹

    1. 打开shape编辑模式,并在vertex编辑模式下选择节点,在添加dummy

    将dummy移动到腿部object下

    2. 添加图用于创建curve

    3. 设置3D Curve

    4. 修改位置控制速度上限(将速度上限修改为500)

    步态控制

    utils.py

    1. import sim
    2. import numpy as np
    3. def start_simulation():
    4. sim.simxFinish(-1)
    5. # 开启套接字与server进行通信
    6. clientID = sim.simxStart('127.0.0.1', 19999, True, True, 5000, 5)
    7. if clientID != -1:
    8. print('Connected to remote API server with ClientID ', clientID)
    9. # 开始模拟
    10. sim.simxStartSimulation(clientID, sim.simx_opmode_oneshot)
    11. return clientID
    12. else:
    13. return -1
    14. def get_joints(client_id):
    15. # 机器人电机力矩参数
    16. rotation_forces = [
    17. # RB
    18. [500, 500, 500],
    19. # RF
    20. [500, 500, 500],
    21. # LB
    22. [500, 500, 500],
    23. # LF
    24. [500, 500, 500]
    25. ]
    26. # 获取机器人关节对象句柄
    27. rec, rb_rot_1 = sim.simxGetObjectHandle(client_id, 'rb_rot_1', sim.simx_opmode_blocking)
    28. rec, rb_rot_2 = sim.simxGetObjectHandle(client_id, 'rb_rot_2', sim.simx_opmode_blocking)
    29. rec, rb_rot_3 = sim.simxGetObjectHandle(client_id, 'rb_rot_3', sim.simx_opmode_blocking)
    30. rec, rf_rot_1 = sim.simxGetObjectHandle(client_id, 'rf_rot_1', sim.simx_opmode_blocking)
    31. rec, rf_rot_2 = sim.simxGetObjectHandle(client_id, 'rf_rot_2', sim.simx_opmode_blocking)
    32. rec, rf_rot_3 = sim.simxGetObjectHandle(client_id, 'rf_rot_3', sim.simx_opmode_blocking)
    33. rec, lb_rot_1 = sim.simxGetObjectHandle(client_id, 'lb_rot_1', sim.simx_opmode_blocking)
    34. rec, lb_rot_2 = sim.simxGetObjectHandle(client_id, 'lb_rot_2', sim.simx_opmode_blocking)
    35. rec, lb_rot_3 = sim.simxGetObjectHandle(client_id, 'lb_rot_3', sim.simx_opmode_blocking)
    36. rec, lf_rot_1 = sim.simxGetObjectHandle(client_id, 'lf_rot_1', sim.simx_opmode_blocking)
    37. rec, lf_rot_2 = sim.simxGetObjectHandle(client_id, 'lf_rot_2', sim.simx_opmode_blocking)
    38. rec, lf_rot_3 = sim.simxGetObjectHandle(client_id, 'lf_rot_3', sim.simx_opmode_blocking)
    39. # 设置电机力矩
    40. rec = sim.simxSetJointForce(client_id, rb_rot_1, rotation_forces[0][0], sim.simx_opmode_blocking)
    41. rec = sim.simxSetJointForce(client_id, rb_rot_2, rotation_forces[0][1], sim.simx_opmode_blocking)
    42. rec = sim.simxSetJointForce(client_id, rb_rot_3, rotation_forces[0][2], sim.simx_opmode_blocking)
    43. rec = sim.simxSetJointForce(client_id, rf_rot_1, rotation_forces[1][0], sim.simx_opmode_blocking)
    44. rec = sim.simxSetJointForce(client_id, rf_rot_2, rotation_forces[1][1], sim.simx_opmode_blocking)
    45. rec = sim.simxSetJointForce(client_id, rf_rot_3, rotation_forces[1][2], sim.simx_opmode_blocking)
    46. rec = sim.simxSetJointForce(client_id, lb_rot_1, rotation_forces[2][0], sim.simx_opmode_blocking)
    47. rec = sim.simxSetJointForce(client_id, lb_rot_2, rotation_forces[2][1], sim.simx_opmode_blocking)
    48. rec = sim.simxSetJointForce(client_id, lb_rot_3, rotation_forces[2][2], sim.simx_opmode_blocking)
    49. rec = sim.simxSetJointForce(client_id, lf_rot_1, rotation_forces[3][0], sim.simx_opmode_blocking)
    50. rec = sim.simxSetJointForce(client_id, lf_rot_2, rotation_forces[3][1], sim.simx_opmode_blocking)
    51. rec = sim.simxSetJointForce(client_id, lf_rot_3, rotation_forces[3][2], sim.simx_opmode_blocking)
    52. return [rb_rot_1, rb_rot_2, rb_rot_3], \
    53. [rf_rot_1, rf_rot_2, rf_rot_3], \
    54. [lb_rot_1, lb_rot_2, lb_rot_3], \
    55. [lf_rot_1, lf_rot_2, lf_rot_3]
    56. def leg_inverse_kine(x, y, z):
    57. """
    58. 求四足机器人单条腿的逆运动学,输入足端位置,返回单腿关节的旋转的角度
    59. """
    60. # h,hu和hl分别是单条腿杆件的长度
    61. h = 0.15
    62. hu = 0.35
    63. hl = 0.382
    64. dyz = np.sqrt(y ** 2 + z ** 2)
    65. lyz = np.sqrt(dyz ** 2 - h ** 2)
    66. gamma_yz = -np.arctan(y / z)
    67. gamma_h_offset = -np.arctan(h / lyz)
    68. gamma = gamma_yz - gamma_h_offset
    69. lxzp = np.sqrt(lyz ** 2 + x ** 2)
    70. n = (lxzp ** 2 - hl ** 2 - hu ** 2) / (2 * hu)
    71. beta = -np.arccos(n / hl)
    72. alfa_xzp = -np.arctan(x / lyz)
    73. alfa_off = np.arccos((hu + n) / lxzp)
    74. alfa = alfa_xzp + alfa_off
    75. return gamma, alfa, beta
    76. def pose_control(roll, pitch, yaw, pos_x, pos_y, pos_z):
    77. """
    78. 输入
    79. """
    80. b = 0.4
    81. l = 0.8
    82. w = 0.7
    83. # 基座的高度
    84. h = 0.732
    85. # 转换角度
    86. R = roll * np.pi / 180
    87. P = pitch * np.pi / 180
    88. Y = yaw * np.pi / 180
    89. pos = np.mat([pos_x, pos_y, pos_z]).T
    90. # 定义旋转矩阵
    91. rotx = np.mat([[1, 0, 0],
    92. [0, np.cos(R), -np.sin(R)],
    93. [0, np.sin(R), np.cos(R)]])
    94. roty = np.mat([[np.cos(P), 0, -np.sin(P)],
    95. [0, 1, 0],
    96. [np.sin(P), 0, np.cos(P)]])
    97. rotz = np.mat([[np.cos(Y), -np.sin(Y), 0],
    98. [np.sin(Y), np.cos(Y), 0],
    99. [0, 0, 1]])
    100. rot_mat = rotx * roty * rotz
    101. # 基座位置
    102. body_struct = np.mat([[l / 2, b / 2, h],
    103. [l / 2, -b / 2, h],
    104. [-l / 2, b / 2, h],
    105. [-l / 2, -b / 2, h]]).T
    106. # 足端位置
    107. footpoint_struct = np.mat([[l / 2, w / 2, 0],
    108. [l / 2, -w / 2, 0],
    109. [-l / 2, w / 2, 0],
    110. [-l / 2, -w / 2, 0]]).T
    111. leg_pose = np.mat(np.zeros((3, 4)))
    112. for i in range(4):
    113. leg_pose[:, i] = -pos - rot_mat * body_struct[:, i] + footpoint_struct[:, i]
    114. return np.squeeze(np.array(leg_pose[:, 3])), np.squeeze(np.array(leg_pose[:, 0])), \
    115. np.squeeze(np.array(leg_pose[:, 1])), np.squeeze(np.array(leg_pose[:, 2]))
    116. def cycloid(dt: float, period: float = 1.0, xs: float = -0.1, xf: float = 0.1, zs: float = -0.582, h: float = 0.1):
    117. """
    118. 计算摆线上在给定时间t处的坐标。
    119. 参数:
    120. t (float): 当前时间点
    121. Ts (float): 摆线运动总时间,默认为1.0
    122. xs (float): 起始x坐标,默认为-0.1
    123. xf (float): 终点x坐标,默认为0.1
    124. zs (float): 起始z坐标,默认为-0.582
    125. h (float): 摆线垂直位移,默认为0.1
    126. 返回:
    127. tuple[float, float]: xep和zep的坐标值
    128. """
    129. sigma = 2 * np.pi * dt / period
    130. x_p = (xf - xs) * ((sigma - np.sin(sigma)) / (2 * np.pi)) + xs
    131. y_p = h * (1 - np.cos(sigma)) / 2 + zs
    132. return x_p, y_p
    133. if __name__ == '__main__':
    134. for pos in pose_control(30, 0, 0, 0, 0, 0.732):
    135. print(pos)

    main.py

    1. import time
    2. from utils import *
    3. walk_period = 1.0
    4. trot_period = 0.4
    5. gait = 1
    6. def cal_phase(dt, T, factor, zs = -0.482, h = 0.15):
    7. if dt < T * factor:
    8. return cycloid(dt, period=T * factor, zs=zs, h=h)
    9. else:
    10. return 0.1 - 0.2 / (T * (1 - factor)) * (dt - T * factor), zs
    11. def walk_gait(dt):
    12. zs = -0.482
    13. h = 0.15
    14. lb_dt = dt % walk_period
    15. rf_dt = (dt + 0.25) % walk_period
    16. rb_dt = (dt + 0.5) % walk_period
    17. lf_dt = (dt + 0.75) % walk_period
    18. lb_pos = cal_phase(lb_dt, T=walk_period, factor=0.25, zs=zs, h=h)
    19. rf_pos = cal_phase(rf_dt, T=walk_period, factor=0.25, zs=zs, h=h)
    20. rb_pos = cal_phase(rb_dt, T=walk_period, factor=0.25, zs=zs, h=h)
    21. lf_pos = cal_phase(lf_dt, T=walk_period, factor=0.25, zs=zs, h=h)
    22. return lb_pos, rf_pos, rb_pos, lf_pos
    23. def trot_gait(dt):
    24. zs = -0.482
    25. h = 0.1
    26. dt_1 = dt % trot_period
    27. dt_2 = (dt + 0.2) % trot_period
    28. pos_1 = cal_phase(dt_1, T=trot_period, factor=0.5, zs=zs, h=h)
    29. pos_2 = cal_phase(dt_2, T=trot_period, factor=0.5, zs=zs, h=h)
    30. return pos_1, pos_2
    31. if __name__ == '__main__':
    32. # 连接到V-REP服务器
    33. clientID = start_simulation()
    34. # 检查连接是否成功
    35. if clientID != -1:
    36. joints = get_joints(clientID)
    37. rb_joints = joints[0]
    38. rf_joints = joints[1]
    39. lb_joints = joints[2]
    40. lf_joints = joints[3]
    41. timeout = 60
    42. start_time = time.time()
    43. curr_time = start_time
    44. sim_start_time, sim_curr_time = None, None
    45. lb_pos, rf_pos, rb_pos, lf_pos = None, None, None, None
    46. # 获取仿真时间
    47. while curr_time - start_time < timeout:
    48. res, sim_curr_time = sim.simxGetFloatSignal(clientID, 'time', sim.simx_opmode_oneshot)
    49. if res == sim.simx_return_ok:
    50. if sim_start_time is None:
    51. sim_start_time = sim_curr_time
    52. print("time ", sim_curr_time - sim_start_time)
    53. if sim_start_time:
    54. dt = sim_curr_time - sim_start_time
    55. if gait == 0:
    56. # dt = (sim_curr_time - sim_start_time) % walk_period
    57. lb_pos, rf_pos, rb_pos, lf_pos = walk_gait(dt)
    58. elif gait == 1:
    59. # dt = (sim_curr_time - sim_start_time) % trot_period
    60. pos_1, pos_2 = trot_gait(dt)
    61. lb_pos = pos_1
    62. rf_pos = pos_1
    63. rb_pos = pos_2
    64. lf_pos = pos_2
    65. # 从足端位置求解关节角度
    66. rb_pose = leg_inverse_kine(rb_pos[0], -0.15, rb_pos[1])
    67. rf_pose = leg_inverse_kine(rf_pos[0], -0.15, rf_pos[1])
    68. lb_pose = leg_inverse_kine(lb_pos[0], -0.15, lb_pos[1])
    69. lf_pose = leg_inverse_kine(lf_pos[0], -0.15, lf_pos[1])
    70. rec = sim.simxSetJointTargetPosition(clientID, rb_joints[0], -rb_pose[0], sim.simx_opmode_oneshot)
    71. rec = sim.simxSetJointTargetPosition(clientID, rb_joints[1], rb_pose[1], sim.simx_opmode_oneshot)
    72. rec = sim.simxSetJointTargetPosition(clientID, rb_joints[2], rb_pose[2], sim.simx_opmode_oneshot)
    73. rec = sim.simxSetJointTargetPosition(clientID, rf_joints[0], rf_pose[0], sim.simx_opmode_oneshot)
    74. rec = sim.simxSetJointTargetPosition(clientID, rf_joints[1], rf_pose[1], sim.simx_opmode_oneshot)
    75. rec = sim.simxSetJointTargetPosition(clientID, rf_joints[2], rf_pose[2], sim.simx_opmode_oneshot)
    76. rec = sim.simxSetJointTargetPosition(clientID, lb_joints[0], -lb_pose[0], sim.simx_opmode_oneshot)
    77. rec = sim.simxSetJointTargetPosition(clientID, lb_joints[1], lb_pose[1], sim.simx_opmode_oneshot)
    78. rec = sim.simxSetJointTargetPosition(clientID, lb_joints[2], lb_pose[2], sim.simx_opmode_oneshot)
    79. rec = sim.simxSetJointTargetPosition(clientID, lf_joints[0], lf_pose[0], sim.simx_opmode_oneshot)
    80. rec = sim.simxSetJointTargetPosition(clientID, lf_joints[1], lf_pose[1], sim.simx_opmode_oneshot)
    81. rec = sim.simxSetJointTargetPosition(clientID, lf_joints[2], lf_pose[2], sim.simx_opmode_oneshot)
    82. # 停止仿真并断开与V-REP的连接
    83. sim.simxStopSimulation(clientID, sim.simx_opmode_oneshot)
    84. sim.simxFinish(clientID)
    85. else:
    86. print("无法连接到V-REP")

    walk步态

    trot步态

  • 相关阅读:
    别再当大冤种了,揭开3D建模报班6个常见套路
    macOS 系统 Kafka 快速入门
    JS 的 apply 方法
    redis在实践中的一些常见问题以及优化思路(包含linux内核参数优化)
    K线形态识别_双飞乌鸦
    通过Vue自带服务器实现Ajax请求跨域(vue-cli)
    基于Java的图书管理系统(附:源码和课件)
    Shell 脚本常用语法总结
    Notepad2 v4.22.11r4478 开源轻量级文本编辑软件
    如果你想跨行转做数据分析师,劝你慎重
  • 原文地址:https://blog.csdn.net/weixin_40679158/article/details/134252751