当前位置:网站首页>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)
边栏推荐
- What is web penetration testing_ Infiltration practice
- Why should a complete knapsack be traversed in sequence? Briefly explain
- Encryption algorithm - password security
- 准备好在CI/CD中自动化持续部署了吗?
- Operation test of function test basis
- Three sentences to briefly introduce subnet mask
- JWT signature does not match locally computed signature. JWT validity cannot be asserted and should
- Leecode brush question record sword finger offer 58 - ii Rotate string left
- How to use vector_ How to use vector pointer
- @TableId can‘t more than one in Class: “com.example.CloseContactSearcher.entity.Activity“.
猜你喜欢

uniapp实现从本地上传头像并显示,同时将头像转化为base64格式存储在mysql数据库中

Core knowledge of distributed cache

37頁數字鄉村振興智慧農業整體規劃建設方案

基於GO語言實現的X.509證書

Racher integrates LDAP to realize unified account login

互动滑轨屏演示能为企业展厅带来什么

DAY FOUR

1000字精选 —— 接口测试基础

DAY ONE

Data analysis course notes (III) array shape and calculation, numpy storage / reading data, indexing, slicing and splicing
随机推荐
Devops can help reduce technology debt in ten ways
DAY TWO
GPIO簡介
DAY FIVE
VTK volume rendering program design of 3D scanned volume data
Data analysis course notes (V) common statistical methods, data and spelling, index and composite index
【精品】pinia 基于插件pinia-plugin-persist的 持久化
Use package FY in Oracle_ Recover_ Data. PCK to recover the table of truncate misoperation
What is web penetration testing_ Infiltration practice
JS import excel & Export Excel
Introduction to GPIO
[automated testing framework] what you need to know about unittest
What is a responsive object? How to create a responsive object?
DAY ONE
DAY THREE
If the college entrance examination goes well, I'm already graying out at the construction site at the moment
SQL的一种写法,匹配就更新,否则就是插入
The programmer resigned and was sentenced to 10 months for deleting the code. Jingdong came home and said that it took 30000 to restore the database. Netizen: This is really a revenge
2022/2/11 summary
Things like random