Mujoco & robosuite 机器人模型

import ctypes
import os

# 获取当前脚本所在的目录
script_dir = os.path.dirname(os.path.abspath(__file__))

# 构建库文件的相对路径
lib_relative_path = os.path.join('dynamic_models', 'UR5e', 'Jb.so')

# 拼接成完整的路径
lib_path = os.path.join(script_dir, lib_relative_path)

try:
    fun_grav = ctypes.CDLL(lib_path)
    print("库文件加载成功!")
except OSError as e:
    print(f"加载库文件时出错: {e}")

<mujoco model="ur5">
    <compiler angle="radian" meshdir="ur5/collision/" />
    <size njmax="500" nconmax="100" />
    <asset>
        <mesh name="base" file="base.stl" />
        <mesh name="shoulder" file="shoulder.stl" />
        <mesh name="upperarm" file="upperarm.stl" />
        <mesh name="forearm" file="forearm.stl" />
        <mesh name="wrist1" file="wrist1.stl" />
        <mesh name="wrist2" file="wrist2.stl" />
        <mesh name="wrist3" file="wrist3.stl" />
    </asset>
    <worldbody>
        <geom type="mesh" contype="0" conaffinity="0" group="1" rgba="0.7 0.7 0.7 1" mesh="base" />
        <geom type="mesh" rgba="0.7 0.7 0.7 1" mesh="base" />
        <body name="shoulder_link" pos="0 0 0.089159">
            <inertial pos="0 0 0" mass="3.7" diaginertia="0.0102675 0.0102675 0.00666" />
            <joint name="shoulder_pan_joint" pos="0 0 0" axis="0 0 1" limited="true" range="-3.14159 3.14159" />
            <geom type="mesh" contype="0" conaffinity="0" group="1" rgba="0.7 0.7 0.7 1" mesh="shoulder" />
            <geom type="mesh" rgba="0.7 0.7 0.7 1" mesh="shoulder" />
            <body name="upper_arm_link" pos="0 0.13585 0" quat="0.707107 0 0.707107 0">
                <inertial pos="0 0 0.28" mass="8.393" diaginertia="0.226891 0.226891 0.0151074" />
                <joint name="shoulder_lift_joint" pos="0 0 0" axis="0 1 0" limited="true" range="-3.14159 3.14159" />
                <geom type="mesh" contype="0" conaffinity="0" group="1" rgba="0.7 0.7 0.7 1" mesh="upperarm" />
                <geom type="mesh" rgba="0.7 0.7 0.7 1" mesh="upperarm" />
                <body name="forearm_link" pos="0 -0.1197 0.425">
                    <inertial pos="0 0 0.196125" mass="2.275" diaginertia="0.0312168 0.0312168 0.004095" />
                    <joint name="elbow_joint" pos="0 0 0" axis="0 1 0" limited="true" range="-3.14159 3.14159" />
                    <geom type="mesh" contype="0" conaffinity="0" group="1" rgba="0.7 0.7 0.7 1" mesh="forearm" />
                    <geom type="mesh" rgba="0.7 0.7 0.7 1" mesh="forearm" />
                    <body name="wrist_1_link" pos="0 0 0.39225" quat="0.707107 0 0.707107 0">
                        <inertial pos="0 0.093 0" mass="1.219" diaginertia="0.0025599 0.0025599 0.0021942" />
                        <joint name="wrist_1_joint" pos="0 0 0" axis="0 1 0" limited="true" range="-3.14159 3.14159" />
                        <geom type="mesh" contype="0" conaffinity="0" group="1" rgba="0.7 0.7 0.7 1" mesh="wrist1" />
                        <geom type="mesh" rgba="0.7 0.7 0.7 1" mesh="wrist1" />
                        <body name="wrist_2_link" pos="0 0.093 0">
                            <inertial pos="0 0 0.09465" mass="1.219" diaginertia="0.0025599 0.0025599 0.0021942" />
                            <joint name="wrist_2_joint" pos="0 0 0" axis="0 0 1" limited="true" range="-3.14159 3.14159" />
                            <geom type="mesh" contype="0" conaffinity="0" group="1" rgba="0.7 0.7 0.7 1" mesh="wrist2" />
                            <geom type="mesh" rgba="0.7 0.7 0.7 1" mesh="wrist2" />
                            <body name="wrist_3_link" pos="0 0 0.09465">
                                <inertial pos="0 0.06505 0" quat="1.73123e-12 0.707107 -0.707107 1.73123e-12" mass="0.1879" diaginertia="0.000132117 8.46959e-05 8.46959e-05" />
                                <joint name="wrist_3_joint" pos="0 0 0" axis="0 1 0" limited="true" range="-3.14159 3.14159" />
                                <geom type="mesh" contype="0" conaffinity="0" group="1" rgba="0.7 0.7 0.7 1" mesh="wrist3" />
                                <geom type="mesh" rgba="0.7 0.7 0.7 1" mesh="wrist3" />
                                <site name="ee" pos="0 0 0" rgba="1 0 0 1" size="0.01" type="sphere"/>
                            </body>
                        </body>
                    </body>
                </body>
            </body>
        </body>
    </worldbody>
    <actuator>
        <motor name='motor1' ctrllimited="true" ctrlrange="-100 100" joint='shoulder_pan_joint' gear="1"/>
        <motor name='motor2' ctrllimited="true" ctrlrange="-100 100" joint='shoulder_lift_joint' gear="1"/>
        <motor name='motor3' ctrllimited="true" ctrlrange="-100 100" joint='elbow_joint' gear="1"/>
        <motor name='motor4' ctrllimited="true" ctrlrange="-100 100" joint='wrist_1_joint' gear="1"/>
        <motor name='motor5' ctrllimited="true" ctrlrange="-100 100" joint='wrist_2_joint' gear="1"/>
        <motor name='motor6' ctrllimited="true" ctrlrange="-100 100" joint='wrist_3_joint' gear="1"/>
    </actuator>
</mujoco>

雅克比

from dm_control.mujoco.wrapper import mjbindings
import numpy as np

mjlib = mjbindings.mjlib

def get_site_jac(model, data, site_id):
    """Return the Jacobian' translational component of the end-effector of
    the corresponding site id.
    """
    jacp = np.zeros((3, model.nv))
    jacr = np.zeros((3, model.nv))
    mjlib.mj_jacSite(model, data, jacp, jacr, site_id)
    jac = np.vstack([jacp, jacr])

    return jac

def get_fullM(model, data):
    M = np.zeros((model.nv, model.nv))
    mjlib.mj_fullM(model, M, data.qM)
    return M

任务空间惯量矩阵

def task_space_inertia_matrix(M, J, threshold=1e-3):
    """Generate the task-space inertia matrix

    Parameters
    ----------
    M: np.array
        the generalized coordinates inertia matrix
    J: np.array
        the task space Jacobian
    threshold: scalar, optional (Default: 1e-3)
        singular value threshold, if the detminant of Mx_inv is less than
        this value then Mx is calculated using the pseudo-inverse function
        and all singular values < threshold * .1 are set = 0
    """

    # calculate the inertia matrix in task space
    M_inv = np.linalg.inv(M)
    Mx_inv = np.dot(J, np.dot(M_inv, J.T))
    if abs(np.linalg.det(Mx_inv)) >= threshold:
        # do the linalg inverse if matrix is non-singular
        # because it's faster and more accurate
        Mx = np.linalg.inv(Mx_inv)
    else:
        # using the rcond to set singular values < thresh to 0
        # singular values < (rcond * max(singular_values)) set to 0
        Mx = np.linalg.pinv(Mx_inv, rcond=threshold * 0.1)

    return Mx, M_inv
def set_state(model, data, qpos, qvel):
    assert qpos.shape == (model.nq, ) and qvel.shape == (model.nv, )
    # old_state = data.get_state()
    # new_state = mujoco.MjSimState(old_state.time, qpos, qvel, old_state.act,
    #                                  old_state.udd_state)
    # data.set_state(new_state)
    # model.forward()
    data.qpos[:] = qpos
    data.qvel[:] = qvel


def get_contact_force(mj_model, mj_data, body_name):
    bodyId = mujoco.mj_name2id(mj_model, MJ_BODY_OBJ, body_name)
    force_com = mj_data.cfrc_ext[bodyId, :]
    trn_force = force_com.copy()

    return np.hstack((trn_force[3:], trn_force[:3]))


def get_geom_pose(model, geom_name):
    """Return the geom pose (relative to parent body).

    :param mujoco_py.MjModel model:
    :param str geom_name:
    :return: position, quaternion
    :rtype: tuple(np.array(3), np.array(4))
    """
    geom_id = mujoco.mj_name2id(model, MJ_GEOM_OBJ, geom_name)
    pos = model.geom_pos[geom_id, :]
    quat = model.geom_quat[geom_id, :]
    return pos, quat


def get_geom_size(model, geom_name):
    """Return the geom size.

    :param mujoco_py.MjModel model:
    :param str geom_name:
    :return: (radius, half-length, _) for cylinder geom, and
             (X half-size; Y half-size; Z half-size) for box geom
    :rtype: np.array(3)
    """
    geom_id = mujoco.mj_name2id(model, MJ_GEOM_OBJ, geom_name)
    if model.geom_type[geom_id] == MJ_BOX or model.geom_type[
            geom_id] == MJ_CYLINDER:
        return model.geom_size[geom_id, :]
    else:
        return None


def get_geom_friction(model, geom_name):
    geom_id = mujoco.mj_name2id(model, MJ_GEOM_OBJ, geom_name)
    return model.geom_friction[geom_id, :]

def get_body_mass(model, body_name):
    body_id = mujoco.mj_name2id(model, MJ_BODY_OBJ, body_name)
    return model.body_mass[body_id]


def get_body_pose(model, body_name):
    body_id = mujoco.mj_name2id(model, MJ_BODY_OBJ, body_name)
    return model.body_pos[body_id], model.body_quat[body_id]


def get_mesh_vertex_pos(model, geom_name):
    geom_id = mujoco.mj_name2id(model, MJ_GEOM_OBJ, geom_name)
    assert model.geom_type[geom_id] == MJ_MESH
    mesh_id = model.geom_dataid[geom_id]
    first_vertex_id = model.mesh_vertadr[mesh_id]
    no_vertex = model.mesh_vertnum[mesh_id]
    vertex_pos = model.mesh_vert[first_vertex_id:first_vertex_id + no_vertex]
    return vertex_pos


def set_geom_size(model, geom_name, size):
    geom_id = mujoco.mj_name2id(model, MJ_GEOM_OBJ, geom_name)
    model.geom_size[geom_id, :] = size


def set_body_mass(model, body_name, mass):
    body_id = mujoco.mj_name2id(model, MJ_BODY_OBJ, body_name)
    model.body_mass[body_id] = mass


def set_geom_friction(model, geom_name, friction):
    geom_id = mujoco.mj_name2id(model, MJ_GEOM_OBJ, geom_name)
    model.geom_friction[geom_id, :] = friction


def set_body_pose(model, body_name, pos, quat):
    body_id = mujoco.mj_name2id(model, MJ_BODY_OBJ, body_name)
    model.body_pos[body_id, :] = pos
    model.body_quat[body_id, :] = quat

def set_body_pose_rotm(model, body_name, pos, R):
    quat = mat2quat(R)
    body_id = mujoco.mj_name2id(model, MJ_BODY_OBJ, body_name)
    model.body_pos[body_id, :] = pos
    model.body_quat[body_id, :] = quat


# -------- GEOMETRY TOOLs
def quat_error(q1, q2):
    """Compute the rotation vector (expressed in the base frame), that if follow
        in a unit time, will transform a body with orientation `q1` to
        orientation `q2`

    :param list/np.ndarray q1: Description of parameter `q1`.
    :param list/np.ndarray q2: Description of parameter `q2`.
    :return: a 3D rotation vector
    :rtype: np.ndarray

    """
    if isinstance(q1, list):
        q1 = np.array(q1)

    if isinstance(q2, list):
        q2 = np.array(q2)

    dtype = q1.dtype
    neg_q1 = np.zeros(4, dtype=dtype)
    err_rot_quat = np.zeros(4, dtype=dtype)
    err_rot = np.zeros(3, dtype=dtype)

    if q1.dot(q2) < 0:
        q1 = -q1

    mujoco.mju_negQuat(neg_q1, q1)
    mujoco.mju_mulQuat(err_rot_quat, q2, neg_q1)
    mujoco.mju_quat2Vel(err_rot, err_rot_quat, 1)
    return err_rot


def quat2mat(q):
    """Tranform a quaternion to rotation amtrix.

    :param type q: Description of parameter `q`.
    :return: 3x3 rotation matrix
    :rtype: np.array
    """
    mat = np.zeros(9)
    mujoco.mju_quat2Mat(mat, q)
    return mat.reshape((3, 3))


def pose_transform(p1, q1, p21, q21):
    """Coordinate transformation between 2 frames

    :param np.ndarray p1: position in frame 1
    :param np.ndarray q1: orientation (quaternion) in frame 1
    :param np.ndarray p21: relative position between frame 1 and 2
    :param np.ndarray q21: relative orientation between frame 1 and 2
    :return: position and orientation in frame 2
    :rtype: type

    """
    # quat to rotation matrix
    R21 = quat2mat(q21)

    p2 = p21 + R21.dot(p1)
    q2 = np.zeros_like(q1)
    mujoco.mju_mulQuat(q2, q21, q1)  # q2 = q21*q1
    return p2, q2


def integrate_quat(q, r, dt):
    """Integrate quaternion by a fixed angular velocity over the duration dt.

    :param np.array(4) q: quaternion.
    :param np.array(3) r: angular velocity.
    :param float dt: duration.
    :return: result quaternion.
    :rtype: np.array(4)
    """
    qres = np.zeros(4)
    qe = np.zeros(4)
    r = r * dt
    angle = np.linalg.norm(r)
    if angle < 1e-9:
        # if angle too small then return current q
        return q.copy()
    axis = r / angle
    mujoco.mju_axisAngle2Quat(qe, axis, angle)
    mujoco.mju_mulQuat(qres, qe, q)
    return qres


def transform_spatial(v1, q21):
    """Coordinate transformation of a spatial vector. The spatial vector can be either
    twist (linear + angular velocity) or wrench (force + torque)

    :param type v1: Spatial vector in frame 1
    :param type q21: transformation matrix (in terms of quaternion)
    :return: Description of returned object.
    :rtype: type
    """
    R21 = quat2mat(q21)
    R = np.block([[R21, np.zeros((3, 3))], [np.zeros((3, 3)), R21]])
    return R.dot(v1)


def similarity_transform(A1, q21):
    """Similarity transformation of a matrix from frame 1 to frame 2
            A2 = R21 * A1 * R12

    :param np.array((3, 3)) A1: 3x3 matrix.
    :param np.array(4) q21: quaternion representation.
    :return: 3x3 matrix
    :rtype: np.array

    """
    R21 = quat2mat(q21)
    return R21.dot(A1.dot(R21.T))


# NOTE: there are infinite rotation vector solutions for a particular
# orientation, the `ref` is to find the closest solution to a reference.
# Is there another minimal representation that could avoid this?
def quat2vec(q, ref=None):
    """Transform quaternion representation to rotation vector representation"""
    r = np.zeros(3)
    scale = 1
    mujoco.mju_quat2Vel(r, q, scale)
    if ref is not None:
        if r.dot(ref) < 0:
            angle = np.linalg.norm(r)
            r = r / angle
            angle = angle - 2 * np.pi
            r = r * angle
    return r


def inverse_frame(p, q):
    pi, qi = np.zeros(3), np.zeros(4)
    mujoco.mju_negPose(pi, qi, p, q)
    return pi, qi


def mat2quat(R):
    R = R.flatten()
    q = np.zeros(4)
    mujoco.mju_mat2Quat(q, R)
    return q


def mul_quat(q1, q2):
    q = np.zeros(4)
    mujoco.mju_mulQuat(q, q1, q2)
    return q

https://github.com/google-deepmind/mujoco_menageriehttps://github.com/google-deepmind/mujoco_menagerie

https://github.com/ARISE-Initiative/robosuitehttps://github.com/ARISE-Initiative/robosuite

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值