Mujoco是一个跨平台的机器人建模软件。
官方的介绍是这样的:
MuJoCo is a physics engine that aims to facilitate research and development in robotics, biomechanics, graphics and animation, and other areas where fast and accurate simulation is needed.
不同于webots的1G多的大小,Mujoco windows的程序包只有5.7M,让我差点以为眼花了。
下载地址:https://mujoco.org/
windows/linux直接双击/bin目录下的Simulate打开程序
然后将模型的xml文件拖到界面里面,就可以看到模型了
Mujoco需要通过编写程序来实现控制。
在没有提供控制器的情况下,看起来Mujoco会给你的模型给一个默认的控制程序
控制程序的开发是基于C接口的,比如,一个简单的控制程序例子:
#include //for bool
//#include //for usleep
#include
#include "mujoco.h"
#include "glfw3.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
char filename[] = "../myproject/projectile/ball.xml";
// MuJoCo data structures
mjModel* m = NULL; // MuJoCo model
mjData* d = NULL; // MuJoCo data
mjvCamera cam; // abstract camera
mjvOption opt; // visualization options
mjvScene scn; // abstract scene
mjrContext con; // custom GPU context
// mouse interaction
bool button_left = false;
bool button_middle = false;
bool button_right = false;
double lastx = 0;
double lasty = 0;
// holders of one step history of time and position to calculate dertivatives
mjtNum position_history = 0;
mjtNum previous_time = 0;
// controller related variables
float_t ctrl_update_freq = 100;
mjtNum last_update = 0.0;
mjtNum ctrl;
// keyboard callback
void keyboard(GLFWwindow* window, int key, int scancode, int act, int mods)
{
// backspace: reset simulation
if( act==GLFW_PRESS && key==GLFW_KEY_BACKSPACE )
{
mj_resetData(m, d);
mj_forward(m, d);
}
}
// mouse button callback
void mouse_button(GLFWwindow* window, int button, int act, int mods)
{
// update button state
button_left = (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT)==GLFW_PRESS);
button_middle = (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_MIDDLE)==GLFW_PRESS);
button_right = (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT)==GLFW_PRESS);
// update mouse position
glfwGetCursorPos(window, &lastx, &lasty);
}
// mouse move callback
void mouse_move(GLFWwindow* window, double xpos, double ypos)
{
// no buttons down: nothing to do
if( !button_left && !button_middle && !button_right )
return;
// compute mouse displacement, save
double dx = xpos - lastx;
double dy = ypos - lasty;
lastx = xpos;
lasty = ypos;
// get current window size
int width, height;
glfwGetWindowSize(window, &width, &height);
// get shift key state
bool mod_shift = (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT)==GLFW_PRESS ||
glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT)==GLFW_PRESS);
// determine action based on mouse button
mjtMouse action;
if( button_right )
action = mod_shift ? mjMOUSE_MOVE_H : mjMOUSE_MOVE_V;
else if( button_left )
action = mod_shift ? mjMOUSE_ROTATE_H : mjMOUSE_ROTATE_V;
else
action = mjMOUSE_ZOOM;
// move camera
mjv_moveCamera(m, action, dx/height, dy/height, &scn, &cam);
}
// scroll callback
void scroll(GLFWwindow* window, double xoffset, double yoffset)
{
// emulate vertical mouse motion = 5% of window height
mjv_moveCamera(m, mjMOUSE_ZOOM, 0, -0.05*yoffset, &scn, &cam);
}
// main function
int main(int argc, const char** argv)
{
// activate software
mj_activate("mjkey.txt");
// load and compile model
char error[1000] = "Could not load binary model";
// check command-line arguments
if( argc<2 )
m = mj_loadXML(filename, 0, error, 1000);
else
if( strlen(argv[1])>4 && !strcmp(argv[1]+strlen(argv[1])-4, ".mjb") )
m = mj_loadModel(argv[1], 0);
else
m = mj_loadXML(argv[1], 0, error, 1000);
if( !m )
mju_error_s("Load model error: %s", error);
// make data
d = mj_makeData(m);
// init GLFW
if( !glfwInit() )
mju_error("Could not initialize GLFW");
// create window, make OpenGL context current, request v-sync
GLFWwindow* window = glfwCreateWindow(1244, 700, "Demo", NULL, NULL);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
// initialize visualization data structures
mjv_defaultCamera(&cam);
mjv_defaultOption(&opt);
mjv_defaultScene(&scn);
mjr_defaultContext(&con);
mjv_makeScene(m, &scn, 2000); // space for 2000 objects
mjr_makeContext(m, &con, mjFONTSCALE_150); // model-specific context
// install GLFW mouse and keyboard callbacks
glfwSetKeyCallback(window, keyboard);
glfwSetCursorPosCallback(window, mouse_move);
glfwSetMouseButtonCallback(window, mouse_button);
glfwSetScrollCallback(window, scroll);
double arr_view[] = {90,-45, 4, 0.000000, 0.000000, 0.000000};
cam.azimuth = arr_view[0];
cam.elevation = arr_view[1];
cam.distance = arr_view[2];
cam.lookat[0] = arr_view[3];
cam.lookat[1] = arr_view[4];
cam.lookat[2] = arr_view[5];
//m->opt.gravity[2]=-1;
//qpos is dim nqx1 = 7x1; 3 translations + 4 quaternions
d->qpos[2]=0.1;
d->qvel[2]=5;
d->qvel[0]=2;
// use the first while condition if you want to simulate for a period.
while( !glfwWindowShouldClose(window))
{
// advance interactive simulation for 1/60 sec
// Assuming MuJoCo can simulate faster than real-time, which it usually can,
// this loop will finish on time for the next frame to be rendered at 60 fps.
// Otherwise add a cpu timer and exit this loop when it is time to render.
mjtNum simstart = d->time;
while( d->time - simstart < 1.0/60.0 )
{
mj_step(m, d);
//drag force = -c*v^2*unit_vector(v); v = sqrt(vx^2+vy^2+vz^2)
// vector (v) = vx i + vy j + vz k
//unit_vector(v) = vector(v)/v
//fx = -c*v*vx;
//fy = -c*v*vy;
//fz = -c*v*vz;
double vx, vy, vz;
vx = d->qvel[0]; vy = d->qvel[1]; vz = d->qvel[2];
double v;
v = sqrt(vx*vx+vy*vy+vz*vz);
double fx, fy, fz;
double c = 1;
fx = -c*v*vx;
fy = -c*v*vy;
fz = -c*v*vz;
d->qfrc_applied[0]=fx;
d->qfrc_applied[1]=fy;
d->qfrc_applied[2]=fz;
}
// get framebuffer viewport
mjrRect viewport = {0, 0, 0, 0};
glfwGetFramebufferSize(window, &viewport.width, &viewport.height);
// update scene and render
opt.frame = mjFRAME_WORLD;
cam.lookat[0] = d->qpos[0];
mjv_updateScene(m, d, &opt, NULL, &cam, mjCAT_ALL, &scn);
mjr_render(viewport, &scn, &con);
//printf("{%f, %f, %f, %f, %f, %f};\n",cam.azimuth,cam.elevation, cam.distance,cam.lookat[0],cam.lookat[1],cam.lookat[2]);
// swap OpenGL buffers (blocking call due to v-sync)
glfwSwapBuffers(window);
// process pending GUI events, call GLFW callbacks
glfwPollEvents();
}
// free visualization storage
mjv_freeScene(&scn);
mjr_freeContext(&con);
// free MuJoCo model and data, deactivate
mj_deleteData(d);
mj_deleteModel(m);
mj_deactivate();
// terminate GLFW (crashes with Linux NVidia drivers)
#if defined(__APPLE__) || defined(_WIN32)
glfwTerminate();
#endif
return 1;
}
这种形式的控制,很容易就可以跟你的控制系统结合在一起,比如构建一个数据管道,将
系统的数据实时传递到Mujoco里面,它甚至不需要跟你的系统耦合起来。
有两种方法,一种是xml,另外一种是Mujoco特有的
另外,支持stl导入。
一个用stl来渲染的双足机器人例子:
<mujoco model="darwin v1.31">
<compiler angle="radian" inertiafromgeom="true" meshdir="meshes/"/>
<size nconmax="100" njmax="500" nstack="-1"/>
<default>
<geom material="MatFrame" margin='0.001' />
<joint limited='true' frictionloss="0.2" damping="1.06" armature="0.011" axis="0 0 1" pos="0 0 0"/>
<position ctrllimited='true' kp='2.65'/>
default>
<asset>
<mesh file="body_coll.stl"/>
<mesh file="neck_coll.stl"/>
<mesh file="head_coll.stl"/>
<mesh file="shoulder_l_coll.stl"/>
<mesh file="arm_high_l_coll.stl"/>
<mesh file="shoulder_r_coll.stl"/>
<mesh file="arm_high_r_coll.stl"/>
<mesh file="pelvis_l_coll.stl"/>
<mesh file="thigh1_l_coll.stl"/>
<mesh file="thigh2_l_coll.stl"/>
<mesh file="tibia_l_coll.stl"/>
<mesh file="ankle1_l_coll.stl"/>
<mesh file="ankle2_l_coll.stl"/>
<mesh file="pelvis_r_coll.stl"/>
<mesh file="thigh1_r_coll.stl"/>
<mesh file="thigh2_r_coll.stl"/>
<mesh file="tibia_r_coll.stl"/>
<mesh file="tibia_naked.stl" scale="0.001 0.001 0.001"/>
<mesh file="ankle1_r_coll.stl"/>
<mesh file="ankle2_r_coll.stl"/>
<mesh file="arm_metal_lowres.stl" scale="0.001 0.001 0.001"/>
<texture type="skybox" builtin="gradient" rgb1="1 1 1" rgb2="0 0 0" width="100" height="100"/>
<texture name="groundplane" type="2d" builtin="checker" rgb1=".7 .7 .75"
rgb2=".9 .9 .95" width="500" height="500" mark="edge" markrgb=".1 .1 .1"/>
<material name="MatPlastic" specular=".8" shininess=".6" reflectance="0.5" rgba=".4 .41 .4 1"/>
<material name="MatFrame" specular="1.2" shininess=".1" reflectance="0.5" rgba=".21 .2 .2 1"/>
<material name="MatGnd" texture="groundplane" texrepeat="5 5" specular=".5" shininess=".01" reflectance="0.1"/>
asset>
<contact>
<exclude body1="head" body2="torso"/>
<exclude body1="foot_l" body2="tibia_l"/>
<exclude body1="foot_r" body2="tibia_r"/>
contact>
<worldbody>
<light directional="false" cutoff="60" exponent="1" diffuse=".5 .5 .5" specular=".1 .1 .1" pos="0.5 0.1 0.8" dir="-0.5 -0.1 -0.8"/>
<geom name="ground" pos="0 0 0" size="2 2 1" material="MatGnd" type="plane"/>
<body name="torso" pos="0 0 0.4">
<inertial diaginertia="6.53693 6.39822 1.88344" mass="0.975599" pos="-0.003053 -0.038651 -0.019268" quat="-0.00879356 0.867004 0.0524199 0.495458"/>
<joint type="free" limited='false' damping="0" stiffness="0" armature="0"/>
<geom mesh="body_coll" type="mesh" material="MatPlastic"/>
<body name="neck" pos="0 0 0.0235" quat="0.707107 0 0 0.707107">
<inertial diaginertia="0.00482356 0.00482356 0.00482356" mass="0.0243577" pos="0.001424 -0.016567 -0.007128" quat="0.640564 0.00150549 0.00338323 0.767896"/>
<joint name="head_pan" range="-3.141592 3.141592" type="hinge"/>
<geom mesh="neck_coll" type="mesh" contype='0' conaffinity='0'/>
<body name="head" pos="0 0 0.02715" quat="0.5 -0.5 -0.5 0.5">
<inertial diaginertia="0.158397 0.123969 0.1178" mass="0.158042" pos="6.4e-005 -0.018565 -0.007667" quat="0.504401 0.495706 -0.489128 0.510499"/>
<joint name="head_tilt" range="-.4363323 .959931089" type="hinge"/>
<geom mesh="head_coll" type="mesh" material="MatPlastic"/>
body>
body>
<body name="shoulder_l" pos="0 0.06035 0" quat=".5 -.5 -.5 -.5">
<inertial diaginertia="0.0118742 0.00851644 0.00537304" mass="0.013" pos="-0.0135226 0.0102641 0.00139357" quat="0.89853 0.0814684 0.0409894 0.429332"/>
<joint name="l_shoulder_pitch" range="-2.61799 2.61799" type="hinge"/>
<geom mesh="shoulder_l_coll" type="mesh" contype='0' conaffinity='0'/>
<body name="arm_high_l" pos="-0.016 0 0.025" quat="0.5 0.5 0.5 -0.5">
<inertial diaginertia="0.122178 0.113353 0.0379938" mass="0.17837715" pos="-0.036239 0.000734 0.00066" quat="0.713991 0.698029 0.0283632 -0.0465622"/>
<joint name="l_shoulder_roll" range="-1.308997 2.356194" type="hinge"/>
<geom mesh="arm_high_l_coll" type="mesh" material="MatPlastic"/>
<body name="arm_low_l" pos="-.06 0 -.016" quat="0 0 0.707107 0.707107">
<inertial diaginertia="0.0875091 0.0872503 0.0201335" mass="0.037" pos=".013 -.015 0" quat=".707107 0 0 .315"/>
<joint name="l_elbow" range="-1.3 1.57" type="hinge"/>
<geom mesh="shoulder_l_coll" pos='.016 -.025 0' euler='-1.57 0 0' type="mesh"/>
<geom mesh="arm_metal_lowres" pos='.021 0.0055 -0.081' euler='0 -1.57 0' type="mesh"/>
body>
body>
body>
<body name="shoulder_r" pos="0 -0.06035 0" euler='1.57 0 1.57'>
<inertial diaginertia="0.0118742 0.00851644 0.00537304" mass="0.013" pos="-0.013523 0.010264 0.001394" quat="0.89853 0.0814684 0.0409894 0.429332"/>
<joint name="r_shoulder_pitch" range="-3.141592 3.141592" type="hinge"/>
<geom mesh="shoulder_r_coll" type="mesh" contype='0' conaffinity='0'/>
<body name="arm_high_r" pos="-0.017 0 0.02478" quat='.5 -.5 .5 .5' >
<inertial diaginertia="0.122178 0.113353 0.0379938" mass="0.168377" pos="-0.036239 0.000734 -0.00066" quat="0.713991 0.698029 0.0283632 -0.0465622"/>
<joint name="r_shoulder_roll" range="-2.356194 1.308997" type="hinge"/>
<geom mesh="arm_high_r_coll" type="mesh" material="MatPlastic"/>
<body name="arm_low_r" pos="-0.06 0 0.016" quat="9.38186e-007 -9.38186e-007 0.707107 0.707107">
<inertial diaginertia="0.0875091 0.0872503 0.0201335" mass="0.0592885" pos="0 0 0" quat="0.362962 0.448533 -0.589325 0.565485"/>
<joint name="r_elbow" range="-1.57 1.3" type="hinge"/>
<geom mesh="shoulder_l_coll" pos='.017 -.0575 0' euler='-1.57 0 0' type="mesh"/>
<geom mesh="arm_metal_lowres" pos='.012 -0.027 0.081' euler='0 1.57 0' type="mesh"/>
body>
body>
body>
<body name="pelvis_l" pos="-0.005 0.037 -0.09355" quat="0 0.707107 0.707107 0">
<inertial diaginertia="0.122641 0.11137 0.0411301" mass="0.027069" pos="0 0.00048 0.018437" quat="0.998273 -0.0514899 -0.00396715 0.0279885"/>
<joint name="l_hip_yaw" range="-.9250245036 2.14675498" type="hinge"/>
<geom mesh="pelvis_l_coll" type="mesh" contype='0' conaffinity='0'/>
<body name="thigh1_l" pos="0 0 0.028652" quat="0.707107 0.707107 0 0">
<inertial diaginertia="0.114985 0.0979692 0.0327798" mass="0.167107" pos="7.9e-005 0.018242 0.013873" quat="0.485806 0.506867 -0.504884 0.502165"/>
<joint name="l_hip_roll" range="-1.0297442587 .7853981634" type="hinge"/>
<geom mesh="thigh1_l_coll" type="mesh"/>
<body name="thigh2_l" pos="0 0 0" quat="0.5 0.5 -0.5 -0.5">
<inertial diaginertia="0.114985 0.0979692 0.0327798" mass="0.119043" pos="-0.062965 -0.000323 0.000692" quat="0.485806 0.506867 -0.504884 0.502165"/>
<joint name="l_hip_pitch" range="-.5061454831 1.745329252" type="hinge"/>
<geom mesh="thigh2_l_coll" type="mesh" material="MatPlastic"/>
<body name="tibia_l" pos="-0.093 0 0">
<inertial diaginertia="0.115891 0.0933882 0.043901" mass="0.0703098" pos="-0.053955 0.006548 -0.000592" quat="0.456916 0.538297 -0.548699 0.447654"/>
<joint name="l_knee" range="-2.2689280276 .1047197551" type="hinge"/>
<geom mesh="tibia_naked" pos='0.145 0 0.037' euler='1.57 0 -1.57' type="mesh"/>
<body name="ankle1_l" pos="-0.093 0 0" quat="0 1 0 0">
<inertial diaginertia="0.120855 0.109532 0.0411304" mass="0.167108" pos="-0.000214 -0.018536 0.013873" quat="0.997965 0.0519065 0.00385358 -0.0368208"/>
<joint name="l_ankle_pitch" range="-1.3962634016 1.2566370614" type="hinge"/>
<geom mesh="ankle1_l_coll" type="mesh"/>
<body name="foot_l" pos="0 0 0" quat="0.707107 -0.707107 0 0">
<inertial diaginertia="0.120855 0.109532 0.0411304" mass="0.0794462" pos="-0.025995 -0.009506 -0.000503" quat="0.997965 0.0519065 0.00385358 -0.0368208"/>
<joint name="l_ankle_roll" range="-1.0995574288 .7679448709" type="hinge"/>
<geom mesh="ankle2_l_coll" type="mesh" material="MatPlastic" contype='0' conaffinity='0'/>
<geom type="box" pos="-.027 -.01 0" size=".007 .032 .052" material="MatPlastic"/>
body>
body>
body>
body>
body>
body>
<body name="pelvis_r" pos="-0.005 -0.037 -0.09355" quat="0 -0.707107 0.707107 0">
<inertial diaginertia="0.122641 0.11137 0.0411301" mass="0.027069" pos="0 0.00048 0.018437" quat="0.998273 -0.0514899 -0.00396715 0.0279885"/>
<joint name="r_hip_yaw" range="-2.14675498 .9250245036" type="hinge"/>
<geom mesh="pelvis_r_coll" type="mesh" contype='0' conaffinity='0'/>
<body name="thigh1_r" pos="0 0 0.028652" quat="0.707107 -0.707107 0 0">
<inertial diaginertia="0.114985 0.0979692 0.0327798" mass="0.167107" pos="7.9e-005 -0.018242 0.0138735" quat="0.485806 0.506867 -0.504884 0.502165"/>
<joint name="r_hip_roll" range="-.7853981634 1.0297442587" type="hinge"/>
<geom mesh="thigh1_r_coll" type="mesh"/>
<body name="thigh2_r" pos="0 0 0" quat="0.5 0.5 -0.5 -0.5">
<inertial diaginertia="0.114985 0.0979692 0.0327798" mass="0.119043" pos="0.062965 -0.000323 0.000692" quat="0.485806 0.506867 -0.504884 0.502165"/>
<joint name="r_hip_pitch" range="-1.745329252 .5061454831" type="hinge"/>
<geom mesh="thigh2_r_coll" type="mesh" material="MatPlastic"/>
<body name="tibia_r" pos="0.093 0 0">
<inertial diaginertia="0.115891 0.0933882 0.043901" mass="0.0703098" pos="0.053955 0.006548 -0.000592" quat="0.456916 0.538297 -0.548699 0.447654"/>
<joint name="r_knee" range="-.1047197551 2.2689280276" type="hinge"/>
<geom mesh="tibia_naked" pos='-0.145 0 -0.037' euler='1.57 0 1.57' type="mesh"/>
<body name="ankle1_r" pos="0.093 0 0" quat="0 1 0 0">
<inertial diaginertia="0.120855 0.109532 0.0411304" mass="0.167108" pos="-0.000214 -0.018536 -0.013873" quat="0.997965 0.0519065 0.00385358 -0.0368208"/>
<joint name="r_ankle_pitch" range="-1.2566370614 1.3962634016" type="hinge"/>
<geom mesh="ankle1_r_coll" type="mesh" />
<body name="foot_r" pos="0 0 0" quat="0.707107 -0.707107 0 0">
<inertial diaginertia="0.120855 0.109532 0.0411304" mass="0.0794462" pos="0.025995 -0.009506 -0.000503" quat="0.997965 0.0519065 0.00385358 -0.0368208"/>
<joint name="r_ankle_roll" range="-.7679448709 1.0995574288" type="hinge"/>
<geom mesh="ankle2_r_coll" type="mesh" material="MatPlastic" contype='0' conaffinity='0'/>
<geom type="box" pos=".027 -.01 0" size=".007 .032 .052" material="MatPlastic"/>
body>
body>
body>
body>
body>
body>
body>
worldbody>
<actuator>
<position name='r_shoulder_pitch' joint='r_shoulder_pitch'ctrlrange='-1.5 1.5' />
<position name='r_shoulder_roll' joint='r_shoulder_roll' ctrlrange='-.85 1.3' />
<position name='r_elbow' joint='r_elbow' ctrlrange='-1.55 1.25' />
<position name='r_hip_yaw' joint='r_hip_yaw' ctrlrange='-1 .9' />
<position name='r_hip_roll' joint='r_hip_roll' ctrlrange='-.7 .45' />
<position name='r_hip_pitch' joint='r_hip_pitch' ctrlrange='-1.7 .45' />
<position name='r_knee' joint='r_knee' ctrlrange='-0.05 2.2' />
<position name='r_ankle_pitch' joint='r_ankle_pitch' ctrlrange='-1.2 1.35' />
<position name='r_ankle_roll' joint='r_ankle_roll' ctrlrange='-.7 .95' />
<position name='l_shoulder_pitch' joint='l_shoulder_pitch'ctrlrange='-1.5 1.5' />
<position name='l_shoulder_roll' joint='l_shoulder_roll' ctrlrange='-1.25 .85' />
<position name='l_elbow' joint='l_elbow' ctrlrange='-1.25 1.55' />
<position name='l_hip_yaw' joint='l_hip_yaw' ctrlrange='-.9 1' />
<position name='l_hip_roll' joint='l_hip_roll' ctrlrange='-.45 .7' />
<position name='l_hip_pitch' joint='l_hip_pitch' ctrlrange='-.45 1.7' />
<position name='l_knee' joint='l_knee' ctrlrange='-2.2 .05' />
<position name='l_ankle_pitch' joint='l_ankle_pitch' ctrlrange='-1.35 1.2' />
<position name='l_ankle_roll' joint='l_ankle_roll' ctrlrange='-.95 .7' />
<position name='head_pan' joint='head_pan' ctrlrange='-2 2' />
<position name='head_tilt' joint='head_tilt' ctrlrange='-.4 .9' />
actuator>
mujoco>