当前位置:网站首页>Mujoco produces analog video
Mujoco produces analog video
2022-07-07 00:28:00 【Feisy】
This code sample simulates the passive dynamics of a given model, renders it offscreen, reads the color and depth pixel values, and saves them into a raw data file that can then be converted into a movie file with tools such as ffmpeg. The rendering is simplified compared to simulate.cc because there is no user interaction, visualization options or timing; instead we simply render with the default settings as fast as possible. The dimensions and number of multi-samples for the offscreen buffer are specified in the MuJoCo model, while the simulation duration, frames-per-second to be rendered (usually much less than the physics simulation rate), and output file name are specified as command-line arguments. For example, a 5 second animation at 60 frames per second is created with:
render humanoid.xml 5 60 rgb.out
The default humanoid.xml model specifies offscreen rendering with 800x800 resolution. With this information in hand, we can compress the (large) raw date file into a playable movie file:
ffmpeg -f rawvideo -pixel_format rgb24 -video_size 800x800
-framerate 60 -i rgb.out -vf "vflip" video.mp4
But I failed several times , Find out ffmpeg There are size requirements inside , We will
Make a size setting for the model :
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
In this way, the video is successfully produced
take record.cc The problem of compiling to your own project
For the moment , I can't embed the recording function directly into the project , Feel the recording function
Eat resources very much , And when recording OPENGL To do it , The test found that it would follow mujoco Of UI
A little conflict , Lead to mujoco Of UI No display .
Possible problems
Use Mujoco Self contained record.cc Just change it
But be careful , use g++ compile , If you use gcc compile ,
May report cstdio Can't find such a mistake .
in addition , The file name cannot be too long , Otherwise std::fopen It won't open
record.cc Useful to mujoco Of array_safe.h, This is the source code , It can be copied directly
Into your own project
Example : The test can pass
Mujoco Record analog video
// Copyright 2021 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "mujoco.h"
// select EGL, OSMESA or GLFW
#if defined(MJ_EGL)
#include <EGL/egl.h>
#elif defined(MJ_OSMESA)
#include <GL/osmesa.h>
OSMesaContext ctx;
unsigned char buffer[10000000];
#else
#include <GLFW/glfw3.h>
#endif
#include "array_safety.h"
namespace mju = ::mujoco::sample_util;
//-------------------------------- global data ------------------------------------------
char xmlpath[] = "./dbpendulum/doublependulum.xml";
char rgb_file[] = "./rgb.out";
// MuJoCo model and data
mjModel* m = 0;
mjData* d = 0;
// MuJoCo visualization
mjvScene scn;
mjvCamera cam;
mjvOption opt;
mjrContext con;
//-------------------------------- utility functions ------------------------------------
// load model, init simulation and rendering
void initMuJoCo(const char* filename) {
// load and compile
char error[1000] = "Could not load binary model";
if (std::strlen(filename)>4 && !std::strcmp(filename+std::strlen(filename)-4, ".mjb")) {
m = mj_loadModel(filename, 0);
} else {
m = mj_loadXML(filename, 0, error, 1000);
}
if (!m) {
mju_error_s("Load model error: %s", error);
}
// make data, run one computation to initialize all fields
d = mj_makeData(m);
mj_forward(m, d);
// initialize visualization data structures
mjv_defaultCamera(&cam);
mjv_defaultOption(&opt);
mjv_defaultScene(&scn);
mjr_defaultContext(&con);
// create scene and context
mjv_makeScene(m, &scn, 2000);
mjr_makeContext(m, &con, 200);
// center and scale view
double arr_view[] = {
89.608063, -11.588379, 5, 0.000000, 0.000000, 2.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];
}
// deallocate everything
void closeMuJoCo(void) {
mj_deleteData(d);
mj_deleteModel(m);
mjr_freeContext(&con);
mjv_freeScene(&scn);
}
// create OpenGL context/window
void initOpenGL(void) {
//------------------------ EGL
#if defined(MJ_EGL)
// desired config
const EGLint configAttribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_STENCIL_SIZE, 8,
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
};
// get default display
EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (eglDpy==EGL_NO_DISPLAY) {
mju_error_i("Could not get EGL display, error 0x%x\n", eglGetError());
}
// initialize
EGLint major, minor;
if (eglInitialize(eglDpy, &major, &minor)!=EGL_TRUE) {
mju_error_i("Could not initialize EGL, error 0x%x\n", eglGetError());
}
// choose config
EGLint numConfigs;
EGLConfig eglCfg;
if (eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs)!=EGL_TRUE) {
mju_error_i("Could not choose EGL config, error 0x%x\n", eglGetError());
}
// bind OpenGL API
if (eglBindAPI(EGL_OPENGL_API)!=EGL_TRUE) {
mju_error_i("Could not bind EGL OpenGL API, error 0x%x\n", eglGetError());
}
// create context
EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT, NULL);
if (eglCtx==EGL_NO_CONTEXT) {
mju_error_i("Could not create EGL context, error 0x%x\n", eglGetError());
}
// make context current, no surface (let OpenGL handle FBO)
if (eglMakeCurrent(eglDpy, EGL_NO_SURFACE, EGL_NO_SURFACE, eglCtx)!=EGL_TRUE) {
mju_error_i("Could not make EGL context current, error 0x%x\n", eglGetError());
}
//------------------------ OSMESA
#elif defined(MJ_OSMESA)
// create context
ctx = OSMesaCreateContextExt(GL_RGBA, 24, 8, 8, 0);
if (!ctx) {
mju_error("OSMesa context creation failed");
}
// make current
if (!OSMesaMakeCurrent(ctx, buffer, GL_UNSIGNED_BYTE, 800, 800)) {
mju_error("OSMesa make current failed");
}
//------------------------ GLFW
#else
// init GLFW
if (!glfwInit()) {
mju_error("Could not initialize GLFW");
}
// create invisible window, single-buffered
glfwWindowHint(GLFW_VISIBLE, 0);
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 800, "Invisible window", NULL, NULL);
if (!window) {
mju_error("Could not create GLFW window");
}
// make context current
glfwMakeContextCurrent(window);
#endif
}
// close OpenGL context/window
void closeOpenGL(void) {
//------------------------ EGL
#if defined(MJ_EGL)
// get current display
EGLDisplay eglDpy = eglGetCurrentDisplay();
if (eglDpy==EGL_NO_DISPLAY) {
return;
}
// get current context
EGLContext eglCtx = eglGetCurrentContext();
// release context
eglMakeCurrent(eglDpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
// destroy context if valid
if (eglCtx!=EGL_NO_CONTEXT) {
eglDestroyContext(eglDpy, eglCtx);
}
// terminate display
eglTerminate(eglDpy);
//------------------------ OSMESA
#elif defined(MJ_OSMESA)
OSMesaDestroyContext(ctx);
//------------------------ GLFW
#else
// terminate GLFW (crashes with Linux NVidia drivers)
#if defined(__APPLE__) || defined(_WIN32)
glfwTerminate();
#endif
#endif
}
//-------------------------------- main function ----------------------------------------
int main(int argc, const char** argv) {
// parse numeric arguments
double duration = 10, fps = 60;
// initialize OpenGL and MuJoCo
initOpenGL();
initMuJoCo(xmlpath);
// set rendering to offscreen buffer
mjr_setBuffer(mjFB_OFFSCREEN, &con);
if (con.currentBuffer!=mjFB_OFFSCREEN) {
std::printf("Warning: offscreen rendering not supported, using default/window framebuffer\n");
}
// get size of active renderbuffer
mjrRect viewport = mjr_maxViewport(&con);
int W = viewport.width;
int H = viewport.height;
// allocate rgb and depth buffers
unsigned char* rgb = (unsigned char*)std::malloc(3*W*H);
float* depth = (float*)std::malloc(sizeof(float)*W*H);
if (!rgb || !depth) {
mju_error("Could not allocate buffers");
}
// create output rgb file
std::FILE* fp = std::fopen(rgb_file, "wb");
if (!fp) {
mju_error("Could not open rgbfile for writing");
}
d->qpos[0] = 0.5;
// main loop
double frametime = 0;
int framecount = 0;
while (d->time<duration) {
// render new frame if it is time (or first frame)
if ((d->time-frametime)>1/fps || frametime==0) {
// update abstract scene
mjv_updateScene(m, d, &opt, NULL, &cam, mjCAT_ALL, &scn);
// render scene in offscreen buffer
mjr_render(viewport, &scn, &con);
// add time stamp in upper-left corner
char stamp[50];
mju::sprintf_arr(stamp, "Time = %.3f", d->time);
mjr_overlay(mjFONT_NORMAL, mjGRID_TOPLEFT, viewport, stamp, NULL, &con);
// read rgb and depth buffers
mjr_readPixels(rgb, depth, viewport, &con);
// insert subsampled depth image in lower-left corner of rgb image
const int NS = 3; // depth image sub-sampling
for (int r=0; r<H; r+=NS)
for (int c=0; c<W; c+=NS) {
int adr = (r/NS)*W + c/NS;
rgb[3*adr] = rgb[3*adr+1] = rgb[3*adr+2] = (unsigned char)((1.0f-depth[r*W+c])*255.0f);
}
// write rgb image to file
std::fwrite(rgb, 3, W*H, fp);
// print every 10 frames: '.' if ok, 'x' if OpenGL error
if (((framecount++)%10)==0) {
if (mjr_getError()) {
std::printf("x");
} else {
std::printf(".");
}
}
// save simulation time
frametime = d->time;
}
// advance simulation
mj_step(m, d);
}
std::printf("\n");
// close file, free buffers
std::fclose(fp);
std::free(rgb);
std::free(depth);
// close MuJoCo and OpenGL
closeMuJoCo();
closeOpenGL();
return 1;
}
#MAC
#COMMON=-O2 -I../../include -L../../bin -mavx -pthread
#LIBS = -w -lmujoco200 -lglfw.3
#CC = gcc
#LINUX
#COMMON=-O2 -I../../include -L../../bin -mavx -pthread -Wl,-rpath,'$$ORIGIN'
#LIBS = -lmujoco200 -lGL -lm -lglew ../../bin/libglfw.so.3
COMMON=-O2 -I../include -L../bin -mavx -pthread -Wl,-rpath,'$$ORIGIN'
LIBS = ../bin/libmujoco.so -lGL -lm ../bin/libglew.so ../bin/libglfw.so.3
CC = g++
#WINDOWS
#COMMON=/O2 /MT /EHsc /arch:AVX /I../../include /Fe../../bin/
#LIBS = ../../bin/glfw3.lib ../../bin/mujoco200.lib
#CC = cl
ROOT = dbpendulum
RECORD=db_record
all:
$(CC) $(COMMON) main.c $(LIBS) -o ../bin/$(ROOT)
$(CC) $(COMMON) record.c $(LIBS) -o ../bin/$(RECORD)
main.o:
$(CC) $(COMMON) -c main.c
record.o:
$(CC) $(COMMON) -c record.c
clean:
rm *.o ../../bin/$(ROOT)
边栏推荐
- openresty ngx_lua子请求
- 1000 words selected - interface test basis
- Liuyongxin report | microbiome data analysis and science communication (7:30 p.m.)
- Uniapp uploads and displays avatars locally, and converts avatars into Base64 format and stores them in MySQL database
- Understand the misunderstanding of programmers: Chinese programmers in the eyes of Western programmers
- vector的使用方法_vector指针如何使用
- 刘永鑫报告|微生物组数据分析与科学传播(晚7点半)
- Use package FY in Oracle_ Recover_ Data. PCK to recover the table of truncate misoperation
- JWT signature does not match locally computed signature. JWT validity cannot be asserted and should
- 基于SSM框架的文章管理系统
猜你喜欢

Jenkins' user credentials plug-in installation

iMeta | 华南农大陈程杰/夏瑞等发布TBtools构造Circos图的简单方法

Imeta | Chen Chengjie / Xia Rui of South China Agricultural University released a simple method of constructing Circos map by tbtools

How can computers ensure data security in the quantum era? The United States announced four alternative encryption algorithms

DAY FIVE

DAY ONE

JWT signature does not match locally computed signature. JWT validity cannot be asserted and should

【vulnhub】presidential1

48页数字政府智慧政务一网通办解决方案

Win10 startup error, press F9 to enter how to repair?
随机推荐
华为mate8电池价格_华为mate8换电池后充电巨慢
Testers, how to prepare test data
Operation test of function test basis
48 page digital government smart government all in one solution
DAY FIVE
What is web penetration testing_ Infiltration practice
Are you ready to automate continuous deployment in ci/cd?
Random类的那些事
C language input / output stream and file operation [II]
1000字精选 —— 接口测试基础
What is AVL tree?
什么是响应式对象?响应式对象的创建过程?
Leecode brush questions record sword finger offer 44 A digit in a sequence of numbers
【vulnhub】presidential1
Jenkins' user credentials plug-in installation
Data analysis course notes (III) array shape and calculation, numpy storage / reading data, indexing, slicing and splicing
Command line kills window process
2022年PMP项目管理考试敏捷知识点(9)
uniapp中redirectTo和navigateTo的区别
48页数字政府智慧政务一网通办解决方案