【MUJOCO控制篇-2】控制一个简单的机械臂
本篇博客将逐步分析和解释如何通过Python代码使用MuJoCo库来控制一个机械臂模型。我们将从加载模型开始,逐步深入到PID控制器的实现,最后讨论如何实现轨迹跟踪功能。上期内容为如何建模一个简单的机械臂模型,本篇文章将基于上篇内容进行深入探讨如何实现一个简单的控制。
目录
基础设置与模型加载
首先,需要导入必要的库,并初始化两个关节的长度。然后加载MuJoCo模型,并创建模拟器(MjSim)和视图器(MjViewer)对象。
import math
import time
import mujoco_py
from mujoco_py import load_model_from_path, MjSim, MjViewer
import glfw # 用于检查窗口关闭事件
import os
L1 = 0.7
L2 = 0.5
# 加载模型
model_path = '/home/fang/xml_demo/arm.xml' # 更新为你的模型文件路径
model = load_model_from_path(model_path)
sim = MjSim(model)
viewer = MjViewer(sim)
model_path是模型文件的路径。MjSim创建一个模拟实例。MjViewer用于渲染和查看模拟。
PID控制器的实现
接下来,定义了一个 PIDController 类来实现PID控制逻辑。该控制器根据目标角度和当前角度来计算所需的扭矩。
# 定义PID控制器类
class PIDController:
def __init__(self, Kp, Ki, Kd):
self.Kp = Kp
self.Ki = Ki
self.Kd = Kd
self.integral_error = 0
self.prev_error = 0
self.dt = 0.01 # 控制周期,需要与模拟步长相匹配
def calculate(self, target, current):
error = target - current
self.integral_error += error * self.dt
derivative = (error - self.prev_error) / self.dt
output = (self.Kp * error) + (self.Ki * self.integral_error) + (self.Kd * derivative)
self.prev_error = error
return output
Kp,Ki,Kd是PID控制器的比例、积分和微分系数。calculate方法计算并返回控制输出。
逆运动学的计算
此处定义了一个 inverse_kinematics 函数来计算给定末端点位置时两个关节的角度。
def inverse_kinematics(x, z, L1, L2, base_height=1.2):
"""
根据末端点坐标在X-Z平面上计算两个关节的角度(逆解算)。
参数:
- x: 末端点的X坐标。
- z: 末端点的Z坐标。
- L1: 第一节长度。
- L2: 第二节长度。
- base_height: 基座的高度。
返回:
- theta1: 第一个关节的角度(弧度)。
- theta2: 第二个关节的角度(弧度)。
"""
# 计算末端点到基座的相对高度
z_rel = z - base_height
D = math.sqrt(x**2 + z_rel**2) # 末端点到原点的距离在X-Z平面上计算
# 使用余弦定理计算第二个关节的角度
cos_theta2 = (D**2 - L1**2 - L2**2) / (2 * L1 * L2)
theta2 = math.acos(min(1, max(cos_theta2, -1))) # 确保acos的参数在合法范围内
# 计算第一个关节的角度
sin_theta2 = math.sqrt(1 - cos_theta2**2)
theta1 = math.atan2(z_rel, x) - math.atan2(L2 * sin_theta2, L1 + L2 * cos_theta2)
# print('D=',D,'theta1=',theta1,'theta2=',theta2)
return theta1, theta2
这个函数通过数学计算得出每个关节应达到的角度,以便机械臂的末端达到目标位置。
轨迹跟踪
轨迹跟踪功能通过 trajectory_tracking 函数实现,它使用 segment_trajectory 函数来逐段处理轨迹,每一段都使用三次插值来平滑运动。插值法可以在别的博客中找到具体的算法与解释,此处不再做过多赘述。
def trajectory_tracking(points, duration):
"""
轨迹跟踪函数,控制机械臂依次沿多个点移动。
points: 点列表,每个点为(x, z)格式。
duration: 每段轨迹的持续时间。
"""
for i in range(len(points) - 1):
start_pos = points[i]
end_pos = points[i + 1]
segment_trajectory(start_pos, end_pos, duration)
points是机械臂应通过的点列表。duration是每段轨迹的持续时间。
逻辑部分
综合以上函数代码,结合解算逻辑,包括UI显示等功能以及PID控制器功能,实现总体的控制效果。
def sim_run(target_x, target_z):
while not glfw.window_should_close(viewer.window):
theta1, theta2 = inverse_kinematics(target_x, target_z, L1, L2)
joint_targets = {'joint1': -(math.pi/2 + theta1), 'joint2': theta2}
for joint_name, target_angle in joint_targets.items():
pid_control(joint_name, target_angle)
sim.step()
viewer.render()
time.sleep(0.01)
主程序
最后,在主程序中,通过设置机械臂需要通过的点列表和每段轨迹的持续时间,然后调用 trajectory_tracking 函数来执行轨迹跟踪。
if __name__ == "__main__":
# 设置通过的点列表和每段轨迹的持续时间
points = [(0.0,0.0),(1.2, 1.2),(0.0, 2.4),(-1.2, 1.2)]
duration = 5 # 每段持续3秒
trajectory_tracking(points, duration)
通过上述步骤,我们能够通过Python和MuJoCo库来控制机械臂沿预定轨迹移动。这种方式不仅适用于机械臂模型,还可以扩展到其他类型的机器人和动态系统的模拟控制。
本文只介绍了一个基础的平面的机械臂控制,涉及简单的解算与PID控制,更深入的部分可以自行探索或关注并等待后续更新。整体代码附在文章内,需要的可以下载并尝试。
转载需要注明出处,违者必究
3005

被折叠的 条评论
为什么被折叠?



