Mujoco 蒙特卡洛采样统计机械臂可达工作空间(非Matlab)

视频讲解:Mujoco 蒙特卡洛采样统计机械臂可达工作空间(非Matlab)_哔哩哔哩_bilibili

代码仓库:https://github.com/LitchiCheng/mujoco-learning

前面总是提到机械臂的可达空间,那怎么计算,有什么公式吗?

使用蒙特卡洛采样,通过大样本概率统计替代精确推导,生成随机分布的关节空间(限制关节范围),再进行正运动学 fk 即可求得机械臂末端的可达空间

复制代码
self.ee_body_name = "ee_center_body"
self.kine = kdl_ik.Kinematics(self.ee_body_name)
self.kine.buildFromURDF(self.urdf_path, "link0")
workspace = []
for _ in range(self.sample_num):
q = PyKDL.JntArray(self.model.nq)
for i in range(self.model.nq):
    q[i] = np.random.uniform(self.model.jnt_range[i][0], self.model.jnt_range[i][1])
# fk
mat = self.kine.fk(q)
x, y, z, _, _, _ = utils.mat2transform(mat)
workspace.append([x, y, z])

最后将x,y,z的集合通过散点图画出来,同时打印下分别的最大最小值,但这个值通常也不是无脑使用,除非只关心某一个维度,不然还是要一起考虑,一般控制前可以通过ik是否可以得到解来判断是否最终控制是有效的。

完整代码如下:

复制代码
import src.kdl_kinematic as kdl_kinematic
import PyKDL
import numpy as np
import os
import mujoco_viewer
import mujoco
import utils

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

class GetWorkspace(mujoco_viewer.CustomViewer):
    def __init__(self, scene_path, urdf_path, sample_num = int(10e4)):
        super().__init__(scene_path, 3, azimuth=-45, elevation=-30)
        self.path = scene_path
        self.urdf_path = urdf_path
        self.sample_num = sample_num

    def runBefore(self):
        self.ee_body_name = "ee_center_body"
        self.kine = kdl_kinematic.Kinematics(self.ee_body_name)
        self.kine.buildFromURDF(self.urdf_path, "link0")
        workspace = []
        for _ in range(self.sample_num):
            q = PyKDL.JntArray(self.model.nq)
            for i in range(self.model.nq):
                q[i] = np.random.uniform(self.model.jnt_range[i][0], self.model.jnt_range[i][1])
            # fk
            mat = self.kine.fk(q)
            x, y, z, _, _, _ = utils.mat2transform(mat)
            workspace.append([x, y, z])
        self.plotWorkspace(np.array(workspace))
        
    def plotWorkspace(self, workspace):
        # X轴
        x_max = workspace[:, 0].max()
        x_min = workspace[:, 0].min()
        x_max_idx = np.argmax(workspace[:, 0])
        x_min_idx = np.argmin(workspace[:, 0])
        x_max_point = workspace[x_max_idx]
        x_min_point = workspace[x_min_idx]
        
        # Y轴
        y_max = workspace[:, 1].max()
        y_min = workspace[:, 1].min()
        y_max_idx = np.argmax(workspace[:, 1])
        y_min_idx = np.argmin(workspace[:, 1])
        y_max_point = workspace[y_max_idx]
        y_min_point = workspace[y_min_idx]
        
        # Z轴
        z_max = workspace[:, 2].max()
        z_min = workspace[:, 2].min()
        z_max_idx = np.argmax(workspace[:, 2])
        z_min_idx = np.argmin(workspace[:, 2])
        z_max_point = workspace[z_max_idx]
        z_min_point = workspace[z_min_idx]

        print(f"X轴:最大值 {x_max:.4f} m | 最小值 {x_min:.4f} m")
        print(f"Y轴:最大值 {y_max:.4f} m | 最小值 {y_min:.4f} m")
        print(f"Z轴:最大值 {z_max:.4f} m | 最小值 {z_min:.4f} m")

        fig = plt.figure(figsize=(12, 10))
        ax = fig.add_subplot(111, projection='3d')
        ax.scatter(workspace[:,0], workspace[:,1], workspace[:,2], s=1, alpha=0.5, c='lightblue', label='workspace')
        
        ax.scatter(x_max_point[0], x_max_point[1], x_max_point[2], 
                s=300, c='red', marker='*', label=f'X Maximum ({x_max:.4f} m)')
        ax.scatter(x_min_point[0], x_min_point[1], x_min_point[2], 
                s=300, c='red', marker='d', label=f'X Minimum ({x_min:.4f} m)')
        
        ax.scatter(y_max_point[0], y_max_point[1], y_max_point[2], 
                s=300, c='green', marker='*', label=f'Y Maximum ({y_max:.4f} m)')
        ax.scatter(y_min_point[0], y_min_point[1], y_min_point[2], 
                s=300, c='green', marker='d', label=f'Y Minimum ({y_min:.4f} m)')
        
        ax.scatter(z_max_point[0], z_max_point[1], z_max_point[2], 
                s=300, c='blue', marker='*', label=f'Z Maximum ({z_max:.4f} m)')
        ax.scatter(z_min_point[0], z_min_point[1], z_min_point[2], 
                s=300, c='blue', marker='d', label=f'Z Minimum ({z_min:.4f} m)')

        ax.set_xlabel('X (m)', fontsize=12)
        ax.set_ylabel('Y (m)', fontsize=12)
        ax.set_zlabel('Z (m)', fontsize=12)
        ax.set_title('workspace', fontsize=14)
        ax.legend(fontsize=10)
        # plt.tight_layout()
        # plt.show()

    def runFunc(self):  
        plt.tight_layout()
        plt.show(block=False)
        plt.pause(0.001)

if __name__ == "__main__":
    urdf_file = "model/franka_panda_urdf/robots/panda_arm.urdf"
    SCENE_XML_PATH = 'model/franka_emika_panda/scene_pos.xml'
    robot = GetWorkspace(SCENE_XML_PATH, urdf_file, sample_num=int(5e4))
    robot.run_loop()
相关推荐
醇氧8 小时前
【Linux】Java 服务生产级部署指南:实现常驻后台、开机自启与系统服务化管理
java·开发语言
凡人叶枫8 小时前
Effective C++ 条款16:成对使用 new 和 delete 时要采取相同形式
开发语言·c++·effective c++
不吃土豆的马铃薯8 小时前
C++ 高性能网络缓冲区 Buffer 源码解析
linux·服务器·开发语言·网络·c++
数据法师9 小时前
QuickSay :基于 Qt 的轻量级快捷短语管理工具
开发语言·qt
caimouse9 小时前
Reactos 第1章 概述
c语言·开发语言·架构
.千余9 小时前
【C++】C++继承入门(下):友元、静态成员与菱形继承的底层逻辑
开发语言·c++·笔记·学习·其他
小短腿的代码世界9 小时前
行情快照与增量更新引擎:Qt在高频交易数据分发中的核心架构——你的行情推送为什么延迟了500ms?
开发语言·qt·架构
初中就开始混世的大魔王9 小时前
6 Fast DDS-传输层
开发语言·c++·中间件·信息与通信
啊森要自信10 小时前
【GUI自动化测试】控件、鼠标键盘操作与多场景自动化
c语言·开发语言·python·adb·ipython
花北城10 小时前
【C#】ABP框架服务端开发
开发语言·c#·abp