expose video capture as logging command in b3RobotSimulatorClientAPI (C++) and pybullet (use STATE_LOGGING_VIDEO_MP4)

This commit is contained in:
Erwin Coumans
2017-03-16 09:13:33 -07:00
parent b7b46b12d3
commit 59d16b2c42
16 changed files with 180 additions and 22 deletions

View File

@@ -85,6 +85,9 @@ struct GUIHelperInterface
virtual void removeAllUserDebugItems( ){}; virtual void removeAllUserDebugItems( ){};
virtual void setVisualizerFlagCallback(VisualizerFlagCallback callback){} virtual void setVisualizerFlagCallback(VisualizerFlagCallback callback){}
//empty name stops dumping video
virtual void dumpFramesToVideo(const char* mp4FileName) {};
}; };

View File

@@ -191,6 +191,8 @@ SET(BulletExampleBrowser_SRCS
../SharedMemory/PhysicsLoopBackC_API.h ../SharedMemory/PhysicsLoopBackC_API.h
../SharedMemory/PhysicsServerCommandProcessor.cpp ../SharedMemory/PhysicsServerCommandProcessor.cpp
../SharedMemory/PhysicsServerCommandProcessor.h ../SharedMemory/PhysicsServerCommandProcessor.h
../SharedMemory/SharedMemoryCommands.h
../SharedMemory/SharedMemoryPublic.h
../BasicDemo/BasicExample.cpp ../BasicDemo/BasicExample.cpp
../BasicDemo/BasicExample.h ../BasicDemo/BasicExample.h
../InverseDynamics/InverseDynamicsExample.cpp ../InverseDynamics/InverseDynamicsExample.cpp

View File

@@ -371,6 +371,7 @@ void OpenGLExampleBrowserVisualizerFlagCallback(int flag, bool enable)
if (flag == COV_ENABLE_GUI) if (flag == COV_ENABLE_GUI)
{ {
renderGui = enable; renderGui = enable;
renderGrid = enable;
} }
if (flag == COV_ENABLE_WIREFRAME) if (flag == COV_ENABLE_WIREFRAME)
@@ -868,8 +869,8 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
} }
int width = 1024; int width = 1280;
int height=768; int height=640;
#ifndef NO_OPENGL3 #ifndef NO_OPENGL3
SimpleOpenGL3App* simpleApp=0; SimpleOpenGL3App* simpleApp=0;
sUseOpenGL2 =args.CheckCmdLineFlag("opengl2"); sUseOpenGL2 =args.CheckCmdLineFlag("opengl2");

View File

@@ -568,3 +568,10 @@ struct CommonGraphicsApp* OpenGLGuiHelper::getAppInterface()
return m_data->m_glApp; return m_data->m_glApp;
} }
void OpenGLGuiHelper::dumpFramesToVideo(const char* mp4FileName)
{
if (m_data->m_glApp)
{
m_data->m_glApp->dumpFramesToVideo(mp4FileName);
}
}

View File

@@ -85,6 +85,8 @@ struct OpenGLGuiHelper : public GUIHelperInterface
virtual void setVisualizerFlagCallback(VisualizerFlagCallback callback); virtual void setVisualizerFlagCallback(VisualizerFlagCallback callback);
virtual void dumpFramesToVideo(const char* mp4FileName);
}; };
#endif //OPENGL_GUI_HELPER_H #endif //OPENGL_GUI_HELPER_H

View File

@@ -88,6 +88,8 @@ project "App_BulletExampleBrowser"
"../SharedMemory/PhysicsServerCommandProcessor.h", "../SharedMemory/PhysicsServerCommandProcessor.h",
"../SharedMemory/TinyRendererVisualShapeConverter.cpp", "../SharedMemory/TinyRendererVisualShapeConverter.cpp",
"../SharedMemory/TinyRendererVisualShapeConverter.h", "../SharedMemory/TinyRendererVisualShapeConverter.h",
"../SharedMemory/SharedMemoryCommands.h",
"../SharedMemory/SharedMemoryPublic.h",
"../MultiThreading/MultiThreadingExample.cpp", "../MultiThreading/MultiThreadingExample.cpp",
"../MultiThreading/b3PosixThreadSupport.cpp", "../MultiThreading/b3PosixThreadSupport.cpp",
"../MultiThreading/b3Win32ThreadSupport.cpp", "../MultiThreading/b3Win32ThreadSupport.cpp",

View File

@@ -781,6 +781,8 @@ void SimpleOpenGL3App::swapBuffer()
// see also http://blog.mmacklin.com/2013/06/11/real-time-video-capture-with-ffmpeg/ // see also http://blog.mmacklin.com/2013/06/11/real-time-video-capture-with-ffmpeg/
void SimpleOpenGL3App::dumpFramesToVideo(const char* mp4FileName) void SimpleOpenGL3App::dumpFramesToVideo(const char* mp4FileName)
{ {
if (mp4FileName)
{
int width = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenWidth(); int width = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenWidth();
int height = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenHeight(); int height = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenHeight();
char cmd[8192]; char cmd[8192];
@@ -813,6 +815,16 @@ void SimpleOpenGL3App::dumpFramesToVideo(const char* mp4FileName)
m_data->m_frameDumpPngFileName = mp4FileName; m_data->m_frameDumpPngFileName = mp4FileName;
} }
} else
{
if (m_data->m_ffmpegFile)
{
fflush(m_data->m_ffmpegFile);
pclose(m_data->m_ffmpegFile);
m_data->m_frameDumpPngFileName = 0;
}
m_data->m_ffmpegFile = 0;
}
} }
void SimpleOpenGL3App::dumpNextFrameToPng(const char* filename) void SimpleOpenGL3App::dumpNextFrameToPng(const char* filename)
{ {

View File

@@ -16,7 +16,7 @@ int main(int argc, char* argv[])
//sim->connect(eCONNECT_UDP, "localhost", 1234); //sim->connect(eCONNECT_UDP, "localhost", 1234);
sim->configureDebugVisualizer( COV_ENABLE_GUI, 0); sim->configureDebugVisualizer( COV_ENABLE_GUI, 0);
// sim->configureDebugVisualizer( COV_ENABLE_SHADOWS, 0);//COV_ENABLE_WIREFRAME // sim->configureDebugVisualizer( COV_ENABLE_SHADOWS, 0);//COV_ENABLE_WIREFRAME
sim->setTimeOut(10);
//syncBodies is only needed when connecting to an existing physics server that has already some bodies //syncBodies is only needed when connecting to an existing physics server that has already some bodies
sim->syncBodies(); sim->syncBodies();
b3Scalar fixedTimeStep = 1./240.; b3Scalar fixedTimeStep = 1./240.;
@@ -59,6 +59,8 @@ int main(int argc, char* argv[])
} }
#endif #endif
sim->setRealTimeSimulation(false); sim->setRealTimeSimulation(false);
int vidLogId = -1;
int minitaurLogId = -1;
while (sim->canSubmitCommand()) while (sim->canSubmitCommand())
{ {
@@ -67,14 +69,48 @@ int main(int argc, char* argv[])
if (keyEvents.m_numKeyboardEvents) if (keyEvents.m_numKeyboardEvents)
{ {
printf("num key events = %d]\n", keyEvents.m_numKeyboardEvents); //printf("num key events = %d]\n", keyEvents.m_numKeyboardEvents);
//m_keyState is a flag combination of eButtonIsDown,eButtonTriggered, eButtonReleased //m_keyState is a flag combination of eButtonIsDown,eButtonTriggered, eButtonReleased
for (int i=0;i<keyEvents.m_numKeyboardEvents;i++) for (int i=0;i<keyEvents.m_numKeyboardEvents;i++)
{ {
printf("keyEvent[%d].m_keyCode = %d, state = %d\n", i,keyEvents.m_keyboardEvents[i].m_keyCode,keyEvents.m_keyboardEvents[i].m_keyState); if (keyEvents.m_keyboardEvents[i].m_keyCode=='0')
{
if ( keyEvents.m_keyboardEvents[i].m_keyState&eButtonTriggered)
{
if (vidLogId < 0)
{
vidLogId = sim->startStateLogging(STATE_LOGGING_VIDEO_MP4,"video.mp4");
}
else
{
sim->stopStateLogging(vidLogId);
vidLogId=-1;
}
}
}
if (keyEvents.m_keyboardEvents[i].m_keyCode=='m')
{
if ( minitaurLogId<0 && keyEvents.m_keyboardEvents[i].m_keyState&eButtonTriggered)
{
minitaurLogId = sim->startStateLogging(STATE_LOGGING_MINITAUR,"simlog.bin");
}
if (minitaurLogId>=0 && keyEvents.m_keyboardEvents[i].m_keyState&eButtonReleased)
{
sim->stopStateLogging(minitaurLogId);
minitaurLogId=-1;
}
}
//printf("keyEvent[%d].m_keyCode = %d, state = %d\n", i,keyEvents.m_keyboardEvents[i].m_keyCode,keyEvents.m_keyboardEvents[i].m_keyState);
} }
} }
sim->stepSimulation(); sim->stepSimulation();
static double yaw=0;
double distance = 10.5+9 * b3Sin(yaw);
yaw+=0.008;
sim->resetDebugVisualizerCamera(distance,yaw,20,b3MakeVector3(0,0,0.1));
b3Clock::usleep(1000.*1000.*fixedTimeStep); b3Clock::usleep(1000.*1000.*fixedTimeStep);
} }

View File

@@ -134,6 +134,18 @@ bool b3RobotSimulatorClientAPI::isConnected() const
return (m_data->m_physicsClientHandle != 0); return (m_data->m_physicsClientHandle != 0);
} }
void b3RobotSimulatorClientAPI::setTimeOut(double timeOutInSec)
{
if (!isConnected())
{
b3Warning("Not connected");
return;
}
b3SetTimeOut(m_data->m_physicsClientHandle,timeOutInSec);
}
void b3RobotSimulatorClientAPI::disconnect() void b3RobotSimulatorClientAPI::disconnect()
{ {
if (!isConnected()) if (!isConnected())
@@ -853,3 +865,18 @@ void b3RobotSimulatorClientAPI::stopStateLogging(int stateLoggerUniqueId)
b3StateLoggingStop(commandHandle, stateLoggerUniqueId); b3StateLoggingStop(commandHandle, stateLoggerUniqueId);
statusHandle = b3SubmitClientCommandAndWaitStatus(m_data->m_physicsClientHandle, commandHandle); statusHandle = b3SubmitClientCommandAndWaitStatus(m_data->m_physicsClientHandle, commandHandle);
} }
void b3RobotSimulatorClientAPI::resetDebugVisualizerCamera(double cameraDistance, double cameraPitch, double cameraYaw, const b3Vector3& targetPos)
{
b3SharedMemoryCommandHandle commandHandle = b3InitConfigureOpenGLVisualizer(m_data->m_physicsClientHandle);
if (commandHandle)
{
if ((cameraDistance >= 0))
{
b3Vector3FloatData camTargetPos;
targetPos.serializeFloat(camTargetPos);
b3ConfigureOpenGLVisualizerSetViewMatrix(commandHandle, cameraDistance, cameraPitch, cameraYaw, camTargetPos.m_floats);
}
b3SubmitClientCommandAndWaitStatus(m_data->m_physicsClientHandle, commandHandle);
}
}

View File

@@ -130,6 +130,8 @@ public:
bool isConnected() const; bool isConnected() const;
void setTimeOut(double timeOutInSec);
void syncBodies(); void syncBodies();
void resetSimulation(); void resetSimulation();
@@ -181,8 +183,9 @@ public:
bool getLinkState(int bodyUniqueId, int linkIndex, b3LinkState* linkState); bool getLinkState(int bodyUniqueId, int linkIndex, b3LinkState* linkState);
void configureDebugVisualizer(enum b3ConfigureDebugVisualizerEnum flag, int enable); void configureDebugVisualizer(enum b3ConfigureDebugVisualizerEnum flag, int enable);
void resetDebugVisualizerCamera(double cameraDistance, double cameraPitch, double cameraYaw, const b3Vector3& targetPos);
int startStateLogging(b3StateLoggingType loggingType, const std::string& fileName, const b3AlignedObjectArray<int>& objectUniqueIds, int maxLogDof = -1); int startStateLogging(b3StateLoggingType loggingType, const std::string& fileName, const b3AlignedObjectArray<int>& objectUniqueIds=b3AlignedObjectArray<int>(), int maxLogDof = -1);
void stopStateLogging(int stateLoggerUniqueId); void stopStateLogging(int stateLoggerUniqueId);
void getVREvents(b3VREventsData* vrEventsData); void getVREvents(b3VREventsData* vrEventsData);

View File

@@ -38,6 +38,8 @@ SET(SharedMemory_SRCS
PhysicsServerCommandProcessor.h PhysicsServerCommandProcessor.h
TinyRendererVisualShapeConverter.cpp TinyRendererVisualShapeConverter.cpp
TinyRendererVisualShapeConverter.h TinyRendererVisualShapeConverter.h
SharedMemoryCommands.h
SharedMemoryPublic.h
../TinyRenderer/geometry.cpp ../TinyRenderer/geometry.cpp
../TinyRenderer/model.cpp ../TinyRenderer/model.cpp
../TinyRenderer/tgaimage.cpp ../TinyRenderer/tgaimage.cpp

View File

@@ -438,6 +438,31 @@ struct InternalStateLogger
}; };
struct VideoMP4Loggger : public InternalStateLogger
{
struct GUIHelperInterface* m_guiHelper;
std::string m_fileName;
VideoMP4Loggger(int loggerUid,const char* fileName,GUIHelperInterface* guiHelper)
:m_guiHelper(guiHelper)
{
m_fileName = fileName;
m_loggingUniqueId = loggerUid;
m_loggingType = STATE_LOGGING_VIDEO_MP4;
m_guiHelper->dumpFramesToVideo(fileName);
}
virtual void stop()
{
m_guiHelper->dumpFramesToVideo(0);
}
virtual void logState(btScalar timeStamp)
{
//dumping video frames happens in another thread
//we could add some overlay of timestamp here, if needed/wanted
}
};
struct MinitaurStateLogger : public InternalStateLogger struct MinitaurStateLogger : public InternalStateLogger
{ {
int m_loggingTimeStamp; int m_loggingTimeStamp;
@@ -1797,6 +1822,17 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
if (clientCmd.m_updateFlags & STATE_LOGGING_START_LOG) if (clientCmd.m_updateFlags & STATE_LOGGING_START_LOG)
{ {
if (clientCmd.m_stateLoggingArguments.m_logType == STATE_LOGGING_VIDEO_MP4)
{
if (clientCmd.m_stateLoggingArguments.m_fileName)
{
int loggerUid = m_data->m_stateLoggersUniqueId++;
VideoMP4Loggger* logger = new VideoMP4Loggger(loggerUid,clientCmd.m_stateLoggingArguments.m_fileName,this->m_data->m_guiHelper);
m_data->m_stateLoggers.push_back(logger);
serverStatusOut.m_type = CMD_STATE_LOGGING_START_COMPLETED;
serverStatusOut.m_stateLoggingResultArgs.m_loggingUniqueId = loggerUid;
}
}
if (clientCmd.m_stateLoggingArguments.m_logType == STATE_LOGGING_MINITAUR) if (clientCmd.m_stateLoggingArguments.m_logType == STATE_LOGGING_MINITAUR)
{ {

View File

@@ -179,8 +179,10 @@ enum MultiThreadedGUIHelperCommunicationEnums
eGUIUserDebugAddParameter, eGUIUserDebugAddParameter,
eGUIUserDebugRemoveItem, eGUIUserDebugRemoveItem,
eGUIUserDebugRemoveAllItems, eGUIUserDebugRemoveAllItems,
eGUIDumpFramesToVideo,
}; };
#include <stdio.h> #include <stdio.h>
//#include "BulletMultiThreaded/PlatformDefinitions.h" //#include "BulletMultiThreaded/PlatformDefinitions.h"
@@ -489,7 +491,7 @@ void MotionThreadFunc(void* userPtr,void* lsMemory)
args->m_cs->unlock(); args->m_cs->unlock();
} }
args->m_physicsServerPtr->disconnectSharedMemory(true);
//do nothing //do nothing
} }
@@ -959,6 +961,16 @@ public:
} }
const char* m_mp4FileName;
virtual void dumpFramesToVideo(const char* mp4FileName)
{
m_cs->lock();
m_mp4FileName = mp4FileName;
m_cs->setSharedParam(1, eGUIDumpFramesToVideo);
workerThreadWait();
m_mp4FileName = 0;
}
}; };
@@ -1614,6 +1626,14 @@ void PhysicsServerExample::updateGraphics()
m_multiThreadedHelper->mainThreadRelease(); m_multiThreadedHelper->mainThreadRelease();
break; break;
} }
case eGUIDumpFramesToVideo:
{
m_multiThreadedHelper->m_childGuiHelper->dumpFramesToVideo(m_multiThreadedHelper->m_mp4FileName);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperIdle: case eGUIHelperIdle:
{ {
break; break;

View File

@@ -188,6 +188,8 @@ bool PhysicsServerSharedMemory::connectSharedMemory( struct GUIHelperInterface*
void PhysicsServerSharedMemory::disconnectSharedMemory(bool deInitializeSharedMemory) void PhysicsServerSharedMemory::disconnectSharedMemory(bool deInitializeSharedMemory)
{ {
m_data->m_commandProcessor->deleteDynamicsWorld();
m_data->m_commandProcessor->setGuiHelper(0); m_data->m_commandProcessor->setGuiHelper(0);
if (m_data->m_verboseOutput) if (m_data->m_verboseOutput)

View File

@@ -330,7 +330,8 @@ enum b3StateLoggingType
STATE_LOGGING_MINITAUR = 0, STATE_LOGGING_MINITAUR = 0,
STATE_LOGGING_GENERIC_ROBOT = 1, STATE_LOGGING_GENERIC_ROBOT = 1,
STATE_LOGGING_VR_CONTROLLERS = 2, STATE_LOGGING_VR_CONTROLLERS = 2,
STATE_LOGGING_COMMANDS = 3, STATE_LOGGING_VIDEO_MP4 = 3,
STATE_LOGGING_COMMANDS = 4,
}; };

View File

@@ -125,6 +125,8 @@ if not _OPTIONS["no-enet"] then
"../../examples/SharedMemory/Win32SharedMemory.h", "../../examples/SharedMemory/Win32SharedMemory.h",
"../../examples/SharedMemory/PosixSharedMemory.cpp", "../../examples/SharedMemory/PosixSharedMemory.cpp",
"../../examples/SharedMemory/PosixSharedMemory.h", "../../examples/SharedMemory/PosixSharedMemory.h",
"../../examples/SharedMemory/SharedMemoryCommands.h",
"../../examples/SharedMemory/SharedMemoryPublic.h",
"../../examples/Utils/b3ResourcePath.cpp", "../../examples/Utils/b3ResourcePath.cpp",
"../../examples/Utils/b3ResourcePath.h", "../../examples/Utils/b3ResourcePath.h",
"../../examples/Utils/RobotLoggingUtil.cpp", "../../examples/Utils/RobotLoggingUtil.cpp",