From bd30ba30ce52ac08cb42a39518fe61b6803afb3b Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 22 Feb 2017 09:33:30 -0800 Subject: [PATCH] Replace large timeout (1024*1024*1024) using real-time clock timeout (10 seconds default) Change SHARED_MEMORY_MAGIC_NUMBER to make sure server/client are using the same version (shared memory) add --realtimesimulation to physics server (GUI, VR) remove --G Xcode from build_cmake_pybullet_double.sh --- build_cmake_pybullet_double.sh | 2 +- examples/SharedMemory/PhysicsClientC_API.cpp | 10 +- .../PhysicsClientSharedMemory.cpp | 8 +- examples/SharedMemory/PhysicsClientTCP.cpp | 11 +- examples/SharedMemory/PhysicsClientUDP.cpp | 14 ++- examples/SharedMemory/PhysicsDirect.cpp | 57 +++++++--- .../SharedMemory/PhysicsServerExample.cpp | 6 ++ examples/SharedMemory/SharedMemoryBlock.h | 2 +- examples/SharedMemory/SharedMemoryPublic.h | 3 + examples/SharedMemory/tcp/main.cpp | 100 +++++++++++------- examples/pybullet/pybullet.c | 9 +- test/SharedMemory/CMakeLists.txt | 22 ++-- test/SharedMemory/premake4.lua | 8 +- 13 files changed, 172 insertions(+), 80 deletions(-) diff --git a/build_cmake_pybullet_double.sh b/build_cmake_pybullet_double.sh index d1520da705..0bddae1a5c 100755 --- a/build_cmake_pybullet_double.sh +++ b/build_cmake_pybullet_double.sh @@ -2,7 +2,7 @@ rm CMakeCache.txt mkdir build_cmake cd build_cmake -cmake -DBUILD_PYBULLET=ON -DBUILD_PYBULLET_NUMPY=OFF -DUSE_DOUBLE_PRECISION=ON -DCMAKE_BUILD_TYPE=Release -G Xcode .. +cmake -DBUILD_PYBULLET=ON -DBUILD_PYBULLET_NUMPY=OFF -DUSE_DOUBLE_PRECISION=ON -DCMAKE_BUILD_TYPE=Release .. make -j12 cd examples cd pybullet diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp index b89d618f5c..58f3c7c973 100644 --- a/examples/SharedMemory/PhysicsClientC_API.cpp +++ b/examples/SharedMemory/PhysicsClientC_API.cpp @@ -1033,9 +1033,15 @@ int b3SubmitClientCommand(b3PhysicsClientHandle physClient, const b3SharedMemory } +#include "../Utils/b3Clock.h" + + b3SharedMemoryStatusHandle b3SubmitClientCommandAndWaitStatus(b3PhysicsClientHandle physClient, const b3SharedMemoryCommandHandle commandHandle) { - int timeout = 1024 * 1024 * 1024; + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + b3SharedMemoryStatusHandle statusHandle = 0; b3Assert(commandHandle); b3Assert(physClient); @@ -1043,7 +1049,7 @@ b3SharedMemoryStatusHandle b3SubmitClientCommandAndWaitStatus(b3PhysicsClientHan { b3SubmitClientCommand(physClient, commandHandle); - while ((statusHandle == 0) && (timeout-- > 0)) + while ((statusHandle == 0) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { statusHandle = b3ProcessServerStatus(physClient); } diff --git a/examples/SharedMemory/PhysicsClientSharedMemory.cpp b/examples/SharedMemory/PhysicsClientSharedMemory.cpp index b9b187b923..c1b82b7406 100644 --- a/examples/SharedMemory/PhysicsClientSharedMemory.cpp +++ b/examples/SharedMemory/PhysicsClientSharedMemory.cpp @@ -268,11 +268,13 @@ bool PhysicsClientSharedMemory::connect() { command.m_type = CMD_REQUEST_BODY_INFO; command.m_sdfRequestInfoArgs.m_bodyUniqueId = 37; submitClientCommand(command); - int timeout = 1024 * 1024 * 1024; - + + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + const SharedMemoryStatus* status = 0; - while ((status == 0) && (timeout-- > 0)) + while ((status == 0) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { status = processServerStatus(); diff --git a/examples/SharedMemory/PhysicsClientTCP.cpp b/examples/SharedMemory/PhysicsClientTCP.cpp index 9ad9fdab94..4961dad01f 100644 --- a/examples/SharedMemory/PhysicsClientTCP.cpp +++ b/examples/SharedMemory/PhysicsClientTCP.cpp @@ -64,7 +64,14 @@ struct TcpNetworkedInternalData m_tcpSocket.Initialize(); m_isConnected = m_tcpSocket.Open(m_hostName.c_str(),m_port); - + if (m_isConnected) + { + m_tcpSocket.SetSendTimeout(5,0); + m_tcpSocket.SetReceiveTimeout(5,0); + } + int key = SHARED_MEMORY_MAGIC_NUMBER; + m_tcpSocket.Send((uint8*)&key,4); + return m_isConnected; } @@ -243,6 +250,8 @@ bool TcpNetworkedPhysicsProcessor::connect() void TcpNetworkedPhysicsProcessor::disconnect() { + const char msg[16]="disconnect"; + m_data->m_tcpSocket.Send((const uint8 *)msg,10); m_data->m_tcpSocket.Close(); m_data->m_isConnected = false; } diff --git a/examples/SharedMemory/PhysicsClientUDP.cpp b/examples/SharedMemory/PhysicsClientUDP.cpp index a578dd81f7..4da08895ab 100644 --- a/examples/SharedMemory/PhysicsClientUDP.cpp +++ b/examples/SharedMemory/PhysicsClientUDP.cpp @@ -464,26 +464,32 @@ bool UdpNetworkedPhysicsProcessor::processCommand(const struct SharedMemoryComma printf("PhysicsClientUDP::processCommand\n"); } // int sz = sizeof(SharedMemoryCommand); - int timeout = 1024 * 1024 * 1024; + + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; m_data->m_cs->lock(); m_data->m_clientCmd = clientCmd; m_data->m_hasCommand = true; m_data->m_cs->unlock(); - while (m_data->m_hasCommand && (timeout-- > 0)) + while ((m_data->m_hasCommand) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { b3Clock::usleep(0); } #if 0 - timeout = 1024 * 1024 * 1024; bool hasStatus = false; + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + const SharedMemoryStatus* stat = 0; - while ((!hasStatus) && (timeout-- > 0)) + while ((!hasStatus) && (clock.getTimeInSeconds() - startTime < timeOutInSeconds)) { hasStatus = receiveStatus(serverStatusOut, bufferServerToClient, bufferSizeInBytes); b3Clock::usleep(100); diff --git a/examples/SharedMemory/PhysicsDirect.cpp b/examples/SharedMemory/PhysicsDirect.cpp index bd54f02e6e..892f6682bb 100644 --- a/examples/SharedMemory/PhysicsDirect.cpp +++ b/examples/SharedMemory/PhysicsDirect.cpp @@ -4,7 +4,7 @@ #include "../CommonInterfaces/CommonGUIHelperInterface.h" #include "SharedMemoryCommands.h" #include "PhysicsCommandProcessorInterface.h" - +#include "../Utils/b3Clock.h" #include "LinearMath/btHashMap.h" #include "LinearMath/btAlignedObjectArray.h" @@ -137,8 +137,10 @@ bool PhysicsDirect::connect() } else { - int timeout = 1024 * 1024 * 1024; - while ((!hasStatus) && (timeout-- > 0)) + b3Clock clock; + double timeSec = clock.getTimeInSeconds(); + + while ((!hasStatus) && (clock.getTimeInSeconds()-timeSec <10 )) { const SharedMemoryStatus* stat = processServerStatus(); if (stat) @@ -226,8 +228,11 @@ bool PhysicsDirect::processDebugLines(const struct SharedMemoryCommand& orgComma bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - int timeout = 1024 * 1024 * 1024; - while ((!hasStatus) && (timeout-- > 0)) + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + + while ((!hasStatus) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { const SharedMemoryStatus* stat = processServerStatus(); if (stat) @@ -308,8 +313,11 @@ bool PhysicsDirect::processVisualShapeData(const struct SharedMemoryCommand& org { bool hasStatus = m_data->m_commandProcessor->processCommand(command, m_data->m_serverStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - int timeout = 1024 * 1024 * 1024; - while ((!hasStatus) && (timeout-- > 0)) + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + + while ((!hasStatus) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { const SharedMemoryStatus* stat = processServerStatus(); if (stat) @@ -359,8 +367,11 @@ bool PhysicsDirect::processOverlappingObjects(const struct SharedMemoryCommand& { bool hasStatus = m_data->m_commandProcessor->processCommand(command, m_data->m_serverStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - int timeout = 1024 * 1024 * 1024; - while ((!hasStatus) && (timeout-- > 0)) + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + + while ((!hasStatus) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { const SharedMemoryStatus* stat = processServerStatus(); if (stat) @@ -414,8 +425,11 @@ bool PhysicsDirect::processContactPointData(const struct SharedMemoryCommand& or { bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - int timeout = 1024 * 1024 * 1024; - while ((!hasStatus) && (timeout-- > 0)) + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + + while ((!hasStatus) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { const SharedMemoryStatus* stat = processServerStatus(); if (stat) @@ -475,8 +489,11 @@ bool PhysicsDirect::processCamera(const struct SharedMemoryCommand& orgCommand) bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - int timeout = 1024 * 1024 * 1024; - while ((!hasStatus) && (timeout-- > 0)) + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + + while ((!hasStatus) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { const SharedMemoryStatus* stat = processServerStatus(); if (stat) @@ -735,8 +752,11 @@ void PhysicsDirect::postProcessStatus(const struct SharedMemoryStatus& serverCmd bool hasStatus = m_data->m_commandProcessor->processCommand(infoRequestCommand, infoStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - int timeout = 1024 * 1024 * 1024; - while ((!hasStatus) && (timeout-- > 0)) + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + + while ((!hasStatus) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { hasStatus = m_data->m_commandProcessor->receiveStatus(infoStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); } @@ -759,8 +779,11 @@ void PhysicsDirect::postProcessStatus(const struct SharedMemoryStatus& serverCmd bool hasStatus = m_data->m_commandProcessor->processCommand(infoRequestCommand, infoStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - int timeout = 1024 * 1024 * 1024; - while ((!hasStatus) && (timeout-- > 0)) + b3Clock clock; + double startTime = clock.getTimeInSeconds(); + double timeOutInSeconds = 10; + + while ((!hasStatus) && (clock.getTimeInSeconds()-startTime < timeOutInSeconds)) { hasStatus = m_data->m_commandProcessor->receiveStatus(infoStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); } diff --git a/examples/SharedMemory/PhysicsServerExample.cpp b/examples/SharedMemory/PhysicsServerExample.cpp index cb05ce921d..f84cc8df1d 100644 --- a/examples/SharedMemory/PhysicsServerExample.cpp +++ b/examples/SharedMemory/PhysicsServerExample.cpp @@ -1153,6 +1153,12 @@ class PhysicsServerExample : public SharedMemoryCommon gCreateDefaultRobotAssets = true; } + if (args.CheckCmdLineFlag("realtimesimulation")) + { + //gEnableRealTimeSimVR = true; + m_physicsServer.enableRealTimeSimulation(true); + } + if (args.CheckCmdLineFlag("norobotassets")) { gCreateDefaultRobotAssets = false; diff --git a/examples/SharedMemory/SharedMemoryBlock.h b/examples/SharedMemory/SharedMemoryBlock.h index f266db496e..f00a907a1e 100644 --- a/examples/SharedMemory/SharedMemoryBlock.h +++ b/examples/SharedMemory/SharedMemoryBlock.h @@ -1,9 +1,9 @@ #ifndef SHARED_MEMORY_BLOCK_H #define SHARED_MEMORY_BLOCK_H -#define SHARED_MEMORY_MAGIC_NUMBER 64738 #define SHARED_MEMORY_MAX_COMMANDS 4 + #include "SharedMemoryCommands.h" struct SharedMemoryBlock diff --git a/examples/SharedMemory/SharedMemoryPublic.h b/examples/SharedMemory/SharedMemoryPublic.h index 7fa2098562..131c4049a2 100644 --- a/examples/SharedMemory/SharedMemoryPublic.h +++ b/examples/SharedMemory/SharedMemoryPublic.h @@ -2,6 +2,9 @@ #define SHARED_MEMORY_PUBLIC_H #define SHARED_MEMORY_KEY 12347 +///increase the SHARED_MEMORY_MAGIC_NUMBER whenever incompatible changes are made in the structures +///my convention is year/month/day/rev +#define SHARED_MEMORY_MAGIC_NUMBER 201702220 enum EnumSharedMemoryClientCommand { diff --git a/examples/SharedMemory/tcp/main.cpp b/examples/SharedMemory/tcp/main.cpp index 3eb0b3c02b..6c2df155de 100644 --- a/examples/SharedMemory/tcp/main.cpp +++ b/examples/SharedMemory/tcp/main.cpp @@ -44,11 +44,8 @@ int main(int argc, char *argv[]) sm->setGuiHelper(&guiHelper); int port = 6667; - if (parseArgs.GetCmdLineArgument("port",port)) - { - printf("Using TCP port %d\n", port); - } - + parseArgs.GetCmdLineArgument("port",port); + gVerboseNetworkMessagesServer = parseArgs.CheckCmdLineFlag("verbose"); #ifndef NO_SHARED_MEMORY @@ -64,7 +61,9 @@ int main(int argc, char *argv[]) if (isPhysicsClientConnected) { - + + printf("Starting TCP server using port %d\n", port); + CPassiveSocket socket; CActiveSocket *pClient = NULL; @@ -74,7 +73,7 @@ int main(int argc, char *argv[]) socket.Initialize(); socket.Listen("localhost", port); - socket.SetBlocking(); + //socket.SetBlocking(); int curNumErr = 0; @@ -89,7 +88,20 @@ int main(int argc, char *argv[]) int clientPort = socket.GetClientPort(); printf("connected from %s:%d\n", socket.GetClientAddr(),clientPort); - + + if (pClient->Receive(4)) + { + int clientKey = *(int*)pClient->GetData(); + + if (clientKey==SHARED_MEMORY_MAGIC_NUMBER) + { + printf("Client version OK %d\n", clientKey); + } else + { + printf("Server version (%d) mismatches Client Version (%d)\n", SHARED_MEMORY_MAGIC_NUMBER,clientKey); + continue; + } + } //---------------------------------------------------------------------- // Receive request from the client. @@ -102,25 +114,27 @@ int main(int argc, char *argv[]) int maxLen = 4 + sizeof(SharedMemoryStatus)+SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE; - //heuristic to detect disconnected clients - CSimpleSocket::CSocketError err = pClient->GetSocketError(); - if (err != CSimpleSocket::SocketSuccess) - { - b3Clock::usleep(100); - - curNumErr++; - - if (curNumErr>100) - { - printf("TCP Connection error = %d, curNumErr = %d\n", (int)err, curNumErr); - - break; - } - } if (pClient->Receive(maxLen)) { + + //heuristic to detect disconnected clients + CSimpleSocket::CSocketError err = pClient->GetSocketError(); + if (err != CSimpleSocket::SocketSuccess || !pClient->IsSocketValid()) + { + b3Clock::usleep(100); + + curNumErr++; + + if (curNumErr>100) + { + printf("TCP Connection error = %d, curNumErr = %d\n", (int)err, curNumErr); + + break; + } + } + curNumErr = 0; char* msg2 = (char*) pClient->GetData(); int numBytesRec2 = pClient->GetBytesReceived(); @@ -132,9 +146,26 @@ int main(int argc, char *argv[]) bytesReceived[curSize+i] = msg2[i]; } - if (bytesReceived.size() == 4 || bytesReceived.size()==sizeof(SharedMemoryCommand)) + if (bytesReceived.size() >= 4) { int numBytesRec = bytesReceived.size(); + if (numBytesRec>=10) + { + if (strncmp(&bytesReceived[0],"disconnect",10)==0) + { + printf("Disconnect request received\n"); + bytesReceived.clear(); + break; + } + + if (strncmp(&bytesReceived[0],"terminateserver",10)==0) + { + printf("Terminate server request received\n"); + exitRequested = true; + bytesReceived.clear(); + break; + } + } if (gVerboseNetworkMessagesServer) { @@ -143,15 +174,6 @@ int main(int argc, char *argv[]) receivedData = true; - if (strncmp(&bytesReceived[0],"stop",4)==0) - { - printf("Stop request received\n"); - exitRequested = true; - bytesReceived.clear(); - break; - } - - SharedMemoryCommand cmd; SharedMemoryCommand* cmdPtr = 0; @@ -233,12 +255,15 @@ int main(int argc, char *argv[]) pClient->Send( &packetData[0], packetData.size() ); } } + + bytesReceived.clear(); + } else { - printf("received packet with unknown contents\n"); + //likely an incomplete packet, let's append more bytes + //printf("received packet with unknown contents\n"); } - bytesReceived.clear(); } } @@ -256,7 +281,10 @@ int main(int argc, char *argv[]) socket.Close(); socket.Shutdown(CSimpleSocket::Both); - } + } else + { + printf("Error: cannot connect to shared memory physics server."); + } delete sm; diff --git a/examples/pybullet/pybullet.c b/examples/pybullet/pybullet.c index 6cd50d1292..206273f587 100644 --- a/examples/pybullet/pybullet.c +++ b/examples/pybullet/pybullet.c @@ -377,10 +377,11 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); statusType = b3GetStatusType(statusHandle); #if 0 - if (statusType != CMD_BODY_INFO_COMPLETED) { - PyErr_SetString(SpamError, "b3InitSyncBodyInfoCommand failed."); - return NULL; - } + if (statusType != CMD_BODY_INFO_COMPLETED) + { + PyErr_SetString(SpamError, "b3InitSyncBodyInfoCommand failed."); + return NULL; + } #endif } diff --git a/test/SharedMemory/CMakeLists.txt b/test/SharedMemory/CMakeLists.txt index 25161a4e86..6ae0aea3ed 100644 --- a/test/SharedMemory/CMakeLists.txt +++ b/test/SharedMemory/CMakeLists.txt @@ -56,17 +56,19 @@ ENDIF() ../../examples/SharedMemory/PosixSharedMemory.h ../../examples/Utils/b3ResourcePath.cpp ../../examples/Utils/b3ResourcePath.h - ../../examples/Utils/RobotLoggingUtil.cpp + ../../examples/Utils/b3Clock.cpp + ../../examples/Utils/b3Clock.h + ../../examples/Utils/RobotLoggingUtil.cpp ../../examples/Utils/RobotLoggingUtil.h - ../../examples/SharedMemory/TinyRendererVisualShapeConverter.cpp - ../../examples/SharedMemory/TinyRendererVisualShapeConverter.h - ../../examples/OpenGLWindow/SimpleCamera.cpp - ../../examples/OpenGLWindow/SimpleCamera.h - ../../examples/TinyRenderer/geometry.cpp - ../../examples/TinyRenderer/model.cpp - ../../examples/TinyRenderer/tgaimage.cpp - ../../examples/TinyRenderer/our_gl.cpp - ../../examples/TinyRenderer/TinyRenderer.cpp + ../../examples/SharedMemory/TinyRendererVisualShapeConverter.cpp + ../../examples/SharedMemory/TinyRendererVisualShapeConverter.h + ../../examples/OpenGLWindow/SimpleCamera.cpp + ../../examples/OpenGLWindow/SimpleCamera.h + ../../examples/TinyRenderer/geometry.cpp + ../../examples/TinyRenderer/model.cpp + ../../examples/TinyRenderer/tgaimage.cpp + ../../examples/TinyRenderer/our_gl.cpp + ../../examples/TinyRenderer/TinyRenderer.cpp ../../examples/ThirdPartyLibs/tinyxml/tinystr.cpp ../../examples/ThirdPartyLibs/tinyxml/tinyxml.cpp ../../examples/ThirdPartyLibs/tinyxml/tinyxmlerror.cpp diff --git a/test/SharedMemory/premake4.lua b/test/SharedMemory/premake4.lua index cfe86780eb..ac525b6b9c 100644 --- a/test/SharedMemory/premake4.lua +++ b/test/SharedMemory/premake4.lua @@ -25,6 +25,8 @@ project ("Test_SharedMemoryPhysicsClient") "../../examples/SharedMemory/Win32SharedMemory.h", "../../examples/SharedMemory/PosixSharedMemory.cpp", "../../examples/SharedMemory/PosixSharedMemory.h", + "../../examples/Utils/b3Clock.cpp", + "../../examples/Utils/b3Clock.h", "../../examples/Utils/b3ResourcePath.cpp", "../../examples/Utils/b3ResourcePath.h", } @@ -200,6 +202,8 @@ project ("Test_PhysicsServerLoopBack") "../../examples/Utils/b3ResourcePath.h", "../../examples/Utils/RobotLoggingUtil.cpp", "../../examples/Utils/RobotLoggingUtil.h", + "../../examples/Utils/b3Clock.cpp", + "../../examples/Utils/b3Clock.h", "../../examples/ThirdPartyLibs/tinyxml/tinystr.cpp", "../../examples/ThirdPartyLibs/tinyxml/tinyxml.cpp", "../../examples/ThirdPartyLibs/tinyxml/tinyxmlerror.cpp", @@ -275,7 +279,9 @@ project ("Test_PhysicsServerLoopBack") "../../examples/Utils/b3ResourcePath.cpp", "../../examples/Utils/b3ResourcePath.h", "../../examples/Utils/RobotLoggingUtil.cpp", - "../../examples/Utils/RobotLoggingUtil.h", + "../../examples/Utils/RobotLoggingUtil.h", + "../../examples/Utils/b3Clock.cpp", + "../../examples/Utils/b3Clock.h", "../../examples/ThirdPartyLibs/tinyxml/tinystr.cpp", "../../examples/ThirdPartyLibs/tinyxml/tinyxml.cpp", "../../examples/ThirdPartyLibs/tinyxml/tinyxmlerror.cpp",