From eb6663ed4bc1521044d85efc224a22e833ab7abe Mon Sep 17 00:00:00 2001 From: = <=> Date: Sun, 2 Aug 2015 14:00:43 -0700 Subject: [PATCH] further work on shared memory API fix dependency of BulletDynamics to Bullet3Common (b3Printf) --- data/slope.bullet | Bin 135920 -> 79960 bytes .../GwenGUISupport/gwenUserInterface.cpp | 2 +- examples/SharedMemory/PhysicsClient.cpp | 46 ++++-- examples/SharedMemory/PhysicsClient.h | 4 +- examples/SharedMemory/PhysicsClientC_API.cpp | 145 ++++++++++++++---- examples/SharedMemory/PhysicsClientC_API.h | 31 +++- .../SharedMemory/PhysicsClientExample.cpp | 8 +- examples/SharedMemory/PhysicsServer.cpp | 133 +++++++++++++--- examples/SharedMemory/RobotControlExample.cpp | 46 +++--- examples/SharedMemory/SharedMemoryCommands.h | 51 +++++- src/Bullet3Common/b3Logging.h | 10 +- .../CollisionShapes/btConvexShape.cpp | 8 +- .../CollisionShapes/btConvexShape.h | 3 +- .../Featherstone/btMultiBody.cpp | 5 +- test/SharedMemory/test.c | 112 +++++++++++++- 15 files changed, 492 insertions(+), 112 deletions(-) diff --git a/data/slope.bullet b/data/slope.bullet index eb5c34e29bf78b5892b1ebcbe50c4df8f422fae7..df44889da9831359e218409bc267a7fcc684efa3 100644 GIT binary patch literal 79960 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

Ctu*oNJ-b-`}UiwDOK28@V)O2z(E2>H=Ey)WZ z`;bSohxQ#AiAJJP{BKM0KmPrr3!|Gs7e?C+-5fm;P2t~KUkdIqaGr>s$M+rh-=)z3 zqcx82J0N`w^C$4V9rFC&g_s|UzB+Q@$Y-NZ;{Pr0q3By9FP<}Q)*`IX(zDUh$k(G! zjyyN=)o6U=D=SQRXH#_GT-d1q7M(0KsfOkIr=H>a(STq5dv1mM+#C071dtEZW zFqvP3>jWe(#&r_cOQ3rZtW3b_r5Im~@g&BthwUw}yag+x;Ecl3W$-b9s3)MY1(I8! zy#-nkq%X(XB-SRCwJQ*>v#|wMu7uqQXiVVlCotO*y#aI;=#8K^LE_C=xf)itV}1?j zEs(eXwl4==0UFe~JkfFT)V&IRqv%@bzZKW(VEtV1-Ugp<2VIXm-C$yWQ-*&d`0s$u zJ7IAYayMcAE=0q~-VNT(80|3jwj+mIqMeA4DBB6%E=0=lEoOWzMv)ociU`JG>o&xG zJ0iOSa_>Q8?}hIBVB=2E`w<}{y$f=8V>AWb>k#djiTS!{H|}~GdDw&K_nH`^Xdmuk z6f*mv^LE?~D{>FyiQR*cxi`8IBi{23(R~;lGJ5YoUU)BCqQl0=JNxq^W`0wDZr9%h z$t}@Q=pF;z4>}HSlig=?6HyJ;=O8~1`8u+FC6F3}7H}_%;9U#UErA-4dlK{%sEG_OgIb_AXa)2% zr~~SPda$<&S_7Q~odTT(Jpw>qei-yT z?(I(iZI>a3AHfs*QTTio^qrvZ0)02=!=Ud0eGK%ypzlMjo&$Xx^!=b80R157hd`eI z{V>SdWzOD%__stq0{T&)c>?$FW1v52YP2Q#Q{ew;&?iAJAf8Ww{tU){7WC&Z{&8IY zJf46FJOMuj8cy&1i1rTX-I1d=4u9h*f8&Y2C_00u>>T+033&cV(5Lalor5RvCt&d> zL7&FcXV=}FNTvLx(O&@lMa2D=Kz|wZQ@D@60{W|R`zYX%TkAr_Nb~4@nS@?em^m))PfPNA5 zOQ2r{eF5|`=vP3$iu?FSpf7^H1p3FIe*$_DYxW){qE|5fr=WiZ`sbj30s5Dqe+Bw7 z=qsRq4f;3G`?sK91N}Pa-+}%;?&Yi4ZEwiA|FgLNmq4Ef{Q~G0LB9n0WzZKuFN1ys zlpm+d;UwamM4Xd|a}se*BF;&~If*zY5$7c0oJ5?H1#un{^&CT;#!#m*!9BS{T}EWpx+1m0q74we+0_6eGFd4qW=o|Z=i2sb`)>Lt#~{B zcii*;0R2zU{{sDQ(Eou9_vvp#E*jZ_9sf8+l*M^&WGos5@0=07NhxdjTfjeeWENTz z(Rm}5HwNA~=zP#tW9I>!xh{&fjo>^7x?tqaXaf96vwp&ysa}Wig&^kOB3v&9T>`ok z^m@=`pvys5fUX3+0dy7Uji5Jy-VC}Lv>kK}=q<2+E$FSF>p*VLYI0pfW3$VJih zpc@d&ji7fx{+(FA3G^<|yFoXDH;(JAI3-+#J!A*ucY<~$I=A3@E9f@R?Vvj#`yS}L z7uWZJ?gYIb^SeNIV>|`gjqx;S4`?rFA80@59;_Vz9R%Gw@-SjNKe}(^{OAzu9>)3+ z5HWBR>&L*mAJ^lc8PF`~R-9liG4JCCqX$rf6C?LW4~`s<9zv}iMr}SY@<8;+$V1Vi zu>Bb1KL}!ckAt27)j)Hgc~E`iL==xaf-GGaEsRV?i=ZV?1N7tw{skJSIf6g^!n`$t zX8}4ZAja`Dr~_UX)B~-KJPJFngPjT3nSh-M*unXvZwG&XhIz~A0{ggHTR5NKo_nBG zWAiaQLHIA>Bd&+w`{c-__+2s?oyOYZ@be7pU58T}{}s;~d_FX?6Ec@TW&$!}Sf||o E1x(<#V*mgE literal 135920 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 K*i55c?EW8{3?|Y5 diff --git a/examples/ExampleBrowser/GwenGUISupport/gwenUserInterface.cpp b/examples/ExampleBrowser/GwenGUISupport/gwenUserInterface.cpp index d952a853a..568ce4328 100644 --- a/examples/ExampleBrowser/GwenGUISupport/gwenUserInterface.cpp +++ b/examples/ExampleBrowser/GwenGUISupport/gwenUserInterface.cpp @@ -295,7 +295,7 @@ void GwenUserInterface::init(int width, int height,Gwen::Renderer::Base* rendere //tab->SetHeight(300); tab->SetWidth(140); - tab->SetHeight(250); + tab->SetHeight(1250); //tab->Dock(Gwen::Pos::Left); tab->Dock( Gwen::Pos::Fill ); //tab->SetMargin( Gwen::Margin( 2, 2, 2, 2 ) ); diff --git a/examples/SharedMemory/PhysicsClient.cpp b/examples/SharedMemory/PhysicsClient.cpp index b0e2a2c83..e068b409a 100644 --- a/examples/SharedMemory/PhysicsClient.cpp +++ b/examples/SharedMemory/PhysicsClient.cpp @@ -22,7 +22,7 @@ struct PhysicsClientSharedMemoryInternalData SharedMemoryBlock* m_testBlock1; btAlignedObjectArray m_robotMultiBodyData; - btAlignedObjectArray m_poweredJointInfo; + btAlignedObjectArray m_jointInfo; int m_counter; bool m_serverLoadUrdfOK; @@ -51,14 +51,14 @@ struct PhysicsClientSharedMemoryInternalData }; -int PhysicsClientSharedMemory::getNumPoweredJoints() const +int PhysicsClientSharedMemory::getNumJoints() const { - return m_data->m_poweredJointInfo.size(); + return m_data->m_jointInfo.size(); } -void PhysicsClientSharedMemory::getPoweredJointInfo(int index, PoweredJointInfo& info) const +void PhysicsClientSharedMemory::getJointInfo(int index, b3JointInfo& info) const { - info = m_data->m_poweredJointInfo[index]; + info = m_data->m_jointInfo[index]; } @@ -147,7 +147,7 @@ bool PhysicsClientSharedMemory::processServerStatus(SharedMemoryStatus& serverSt const SharedMemoryStatus& serverCmd =m_data->m_testBlock1->m_serverCommands[0]; hasStatus = true; serverStatus = serverCmd; - + EnumSharedMemoryServerStatus s = (EnumSharedMemoryServerStatus)serverCmd.m_type; //consume the command switch (serverCmd.m_type) { @@ -183,10 +183,9 @@ bool PhysicsClientSharedMemory::processServerStatus(SharedMemoryStatus& serverSt } for (int link=0;linkm_numLinks;link++) { - if ((mb->m_links[link].m_jointType == eRevoluteType)|| - (mb->m_links[link].m_jointType == ePrismaticType)) { - PoweredJointInfo info; + b3JointInfo info; + info.m_flags = 0; info.m_qIndex = qOffset; info.m_uIndex = uOffset; @@ -201,7 +200,12 @@ bool PhysicsClientSharedMemory::processServerStatus(SharedMemoryStatus& serverSt info.m_jointName = mb->m_links[link].m_jointName; info.m_jointType = mb->m_links[link].m_jointType; } - m_data->m_poweredJointInfo.push_back(info); + if ((mb->m_links[link].m_jointType == eRevoluteType)|| + (mb->m_links[link].m_jointType == ePrismaticType)) + { + info.m_flags |= JOINT_HAS_MOTORIZED_POWER; + } + m_data->m_jointInfo.push_back(info); } qOffset+= mb->m_links[link].m_posVarCount; uOffset+= mb->m_links[link].m_dofCount; @@ -217,10 +221,9 @@ bool PhysicsClientSharedMemory::processServerStatus(SharedMemoryStatus& serverSt } for (int link=0;linkm_numLinks;link++) { - if ((mb->m_links[link].m_jointType == eRevoluteType)|| - (mb->m_links[link].m_jointType == ePrismaticType)) { - PoweredJointInfo info; + b3JointInfo info; + info.m_flags = 0; info.m_qIndex = qOffset; info.m_uIndex = uOffset; @@ -235,7 +238,12 @@ bool PhysicsClientSharedMemory::processServerStatus(SharedMemoryStatus& serverSt info.m_jointName = mb->m_links[link].m_jointName; info.m_jointType = mb->m_links[link].m_jointType; } - m_data->m_poweredJointInfo.push_back(info); + if ((mb->m_links[link].m_jointType == eRevoluteType)|| + (mb->m_links[link].m_jointType == ePrismaticType)) + { + info.m_flags |= JOINT_HAS_MOTORIZED_POWER; + } + m_data->m_jointInfo.push_back(info); } qOffset+= mb->m_links[link].m_posVarCount; uOffset+= mb->m_links[link].m_dofCount; @@ -338,7 +346,7 @@ bool PhysicsClientSharedMemory::processServerStatus(SharedMemoryStatus& serverSt } default: { - b3Error("Unknown server command\n"); + b3Error("Unknown server status\n"); btAssert(0); } }; @@ -355,7 +363,11 @@ bool PhysicsClientSharedMemory::processServerStatus(SharedMemoryStatus& serverSt { m_data->m_waitingForServer = true; } - } + } else + { + b3Printf("m_numServerStatus = %d, processed = %d\n", m_data->m_testBlock1->m_numServerCommands, + m_data->m_testBlock1->m_numProcessedServerCommands); + } return hasStatus; } @@ -368,6 +380,8 @@ bool PhysicsClientSharedMemory::submitClientCommand(const SharedMemoryCommand& c { ///at the moment we allow a maximum of 1 outstanding command, so we check for this //once the server processed the command and returns a status, we clear the flag "m_data->m_waitingForServer" and allow submitting the next command + btAssert(!m_data->m_waitingForServer); + if (!m_data->m_waitingForServer) { m_data->m_testBlock1->m_clientCommands[0] = command; diff --git a/examples/SharedMemory/PhysicsClient.h b/examples/SharedMemory/PhysicsClient.h index 4d11f91ac..29e00f19e 100644 --- a/examples/SharedMemory/PhysicsClient.h +++ b/examples/SharedMemory/PhysicsClient.h @@ -26,9 +26,9 @@ public: virtual bool submitClientCommand(const SharedMemoryCommand& command); - virtual int getNumPoweredJoints() const; + virtual int getNumJoints() const; - virtual void getPoweredJointInfo(int index, PoweredJointInfo& info) const; + virtual void getJointInfo(int index, b3JointInfo& info) const; }; diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp index be1ec94b3..14f58cd31 100644 --- a/examples/SharedMemory/PhysicsClientC_API.cpp +++ b/examples/SharedMemory/PhysicsClientC_API.cpp @@ -80,6 +80,117 @@ int b3InitStepSimulationCommand(struct SharedMemoryCommand* command) } + +int b3JointControlCommandInit(struct SharedMemoryCommand* command, int controlMode) +{ + b3Assert(command); + command->m_type = CMD_SEND_DESIRED_STATE; + command->m_sendDesiredStateCommandArgument.m_controlMode = controlMode; + command->m_updateFlags = 0; + return 0; +} + +int b3JointControlSetDesiredVelocity(struct SharedMemoryCommand* command, int dofIndex, double value) +{ + b3Assert(command); + command->m_sendDesiredStateCommandArgument.m_desiredStateQdot[dofIndex] = 1; + return 0; +} + + +int b3JointControlSetMaximumForce(struct SharedMemoryCommand* command, int dofIndex, double value) +{ + b3Assert(command); + command->m_sendDesiredStateCommandArgument.m_desiredStateForceTorque[dofIndex] = value; + return 0; +} + +int b3JointControlSetDesiredForceTorque(struct SharedMemoryCommand* command, int dofIndex, double value) +{ + b3Assert(command); + command->m_sendDesiredStateCommandArgument.m_desiredStateForceTorque[dofIndex] = value; + return 0; +} + + +int b3RequestActualStateCommandInit(struct SharedMemoryCommand* command) +{ + b3Assert(command); + command->m_type =CMD_REQUEST_ACTUAL_STATE; + return 0; +} + +int b3CreateBoxShapeCommandInit(struct SharedMemoryCommand* command) +{ + b3Assert(command); + command->m_type = CMD_CREATE_BOX_COLLISION_SHAPE; + command->m_updateFlags =0; + return 0; +} + +int b3CreateBoxCommandSetStartPosition(struct SharedMemoryCommand* command, double startPosX,double startPosY,double startPosZ) +{ + b3Assert(command); + b3Assert(command->m_type == CMD_CREATE_BOX_COLLISION_SHAPE); + command->m_updateFlags |=BOX_SHAPE_HAS_INITIAL_POSITION; + + command->m_createBoxShapeArguments.m_initialPosition[0] = startPosX; + command->m_createBoxShapeArguments.m_initialPosition[1] = startPosY; + command->m_createBoxShapeArguments.m_initialPosition[2] = startPosZ; + return 0; +} + +int b3CreateBoxCommandSetStartOrientation(struct SharedMemoryCommand* command, double startOrnX,double startOrnY,double startOrnZ, double startOrnW) +{ + b3Assert(command); + b3Assert(command->m_type == CMD_CREATE_BOX_COLLISION_SHAPE); + command->m_updateFlags |=BOX_SHAPE_HAS_INITIAL_ORIENTATION; + + command->m_createBoxShapeArguments.m_initialOrientation[0] = startOrnX; + command->m_createBoxShapeArguments.m_initialOrientation[1] = startOrnY; + command->m_createBoxShapeArguments.m_initialOrientation[2] = startOrnZ; + command->m_createBoxShapeArguments.m_initialOrientation[3] = startOrnW; + return 0; +} + +int b3CreateBoxCommandSetHalfExtents(struct SharedMemoryCommand* command, double halfExtentsX,double halfExtentsY,double halfExtentsZ) +{ + + b3Assert(command); + b3Assert(command->m_type == CMD_CREATE_BOX_COLLISION_SHAPE); + command->m_updateFlags |=BOX_SHAPE_HAS_HALF_EXTENTS; + + command->m_createBoxShapeArguments.m_halfExtentsX = halfExtentsX; + command->m_createBoxShapeArguments.m_halfExtentsY = halfExtentsY; + command->m_createBoxShapeArguments.m_halfExtentsZ = halfExtentsZ; + + return 0; +} + + + +int b3CreateSensorCommandInit(struct SharedMemoryCommand* command) +{ + b3Assert(command); + command->m_type = CMD_CREATE_SENSOR; + command->m_updateFlags = 0; + command->m_createSensorArguments.m_numJointSensorChanges = 0; + return 0; +} + +int b3CreateSensorEnable6DofJointForceTorqueSensor(struct SharedMemoryCommand* command, int jointIndex, int enable) +{ + b3Assert(command); + b3Assert(command->m_type == CMD_CREATE_SENSOR); + int curIndex = command->m_createSensorArguments.m_numJointSensorChanges; + + command->m_createSensorArguments.m_jointIndex[curIndex] = jointIndex; + command->m_createSensorArguments.m_enableJointForceSensor[curIndex] = enable; + command->m_createSensorArguments.m_numJointSensorChanges++; + return 0; +} + + b3PhysicsClientHandle b3ConnectSharedMemory( int allowSharedMemoryInitialization) { PhysicsClientSharedMemory* cl = new PhysicsClientSharedMemory(); @@ -111,41 +222,19 @@ int b3SubmitClientCommand(b3PhysicsClientHandle physClient, struct SharedMemoryC return (int)cl->submitClientCommand(*command); } + + int b3GetNumJoints(b3PhysicsClientHandle physClient) { PhysicsClientSharedMemory* cl = (PhysicsClientSharedMemory* ) physClient; - return cl->getNumPoweredJoints(); + return cl->getNumJoints(); } -void b3GetPoweredJointInfo(b3PhysicsClientHandle physClient, int linkIndex, struct PoweredJointInfo* info) + +void b3GetJointInfo(b3PhysicsClientHandle physClient, int linkIndex, struct b3JointInfo* info) { PhysicsClientSharedMemory* cl = (PhysicsClientSharedMemory* ) physClient; - cl->getPoweredJointInfo(linkIndex,*info); + cl->getJointInfo(linkIndex,*info); } -#if 0 -#include "SharedMemoryBlock.h" - -#define B3_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name - -B3_DECLARE_HANDLE(b3PhysicsClientHandle); - -b3PhysicsClientHandle b3ConnectSharedMemory(int memKey, int allowSharedMemoryInitialization); - -void b3DisconnectSharedMemory(b3PhysicsClientHandle physClient); - -int b3ProcessServerStatus(b3PhysicsClientHandle physClient, struct SharedMemoryStatus* status); - -int b3CanSubmitCommand(b3PhysicsClientHandle physClient); - -int b3SubmitClientCommand(b3PhysicsClientHandle physClient, struct SharedMemoryCommand* command); - -int b3GetNumPoweredJoints(b3PhysicsClientHandle physClient); - -void b3GetPoweredJointInfo(int linkIndex, struct PoweredJointInfo* info); - -int b3InitPhysicsParamCommand(struct SharedMemoryCommand* command); -int b3PhysicsParamSetGravity(struct SharedMemoryCommand* command, double gravx,double gravy, double gravz); - -#endif diff --git a/examples/SharedMemory/PhysicsClientC_API.h b/examples/SharedMemory/PhysicsClientC_API.h index 472b19a25..35a1a5801 100644 --- a/examples/SharedMemory/PhysicsClientC_API.h +++ b/examples/SharedMemory/PhysicsClientC_API.h @@ -22,9 +22,9 @@ int b3CanSubmitCommand(b3PhysicsClientHandle physClient); int b3SubmitClientCommand(b3PhysicsClientHandle physClient, struct SharedMemoryCommand* command); -int b3GetNumPoweredJoints(b3PhysicsClientHandle physClient); +int b3GetNumJoints(b3PhysicsClientHandle physClient); -void b3GetPoweredJointInfo(b3PhysicsClientHandle physClient, int linkIndex, struct PoweredJointInfo* info); +void b3GetJointInfo(b3PhysicsClientHandle physClient, int linkIndex, struct b3JointInfo* info); int b3InitPhysicsParamCommand(struct SharedMemoryCommand* command); int b3PhysicsParamSetGravity(struct SharedMemoryCommand* command, double gravx,double gravy, double gravz); @@ -39,6 +39,33 @@ int b3LoadUrdfCommandSetStartOrientation(struct SharedMemoryCommand* command, do int b3LoadUrdfCommandSetUseMultiBody(struct SharedMemoryCommand* command, int useMultiBody); int b3LoadUrdfCommandSetUseFixedBase(struct SharedMemoryCommand* command, int useFixedBase); +///Set joint control variables such as desired position/angle, desired velocity, +///applied joint forces, dependent on the control mode (CONTROL_MODE_VELOCITY or CONTROL_MODE_TORQUE) +int b3JointControlCommandInit(struct SharedMemoryCommand* command, int controlMode); +//Only use when controlMode is CONTROL_MODE_VELOCITY +int b3JointControlSetDesiredVelocity(struct SharedMemoryCommand* command, int dofIndex, double value); +int b3JointControlSetMaximumForce(struct SharedMemoryCommand* command, int dofIndex, double value); +///Only use if when controlMode is CONTROL_MODE_TORQUE, +int b3JointControlSetDesiredForceTorque(struct SharedMemoryCommand* command, int dofIndex, double value); + + +///the creation of collision shapes and rigid bodies etc is likely going to change, +///but good to have a b3CreateBoxShapeCommandInit for now + +//create a box of size (1,1,1) at world origin (0,0,0) at orientation quat (0,0,0,1) +//after that, you can optionally adjust the initial position, orientation and size +int b3CreateBoxShapeCommandInit(struct SharedMemoryCommand* command); +int b3CreateBoxCommandSetStartPosition(struct SharedMemoryCommand* command, double startPosX,double startPosY,double startPosZ); +int b3CreateBoxCommandSetStartOrientation(struct SharedMemoryCommand* command, double startOrnX,double startOrnY,double startOrnZ, double startOrnW); +int b3CreateBoxCommandSetHalfExtents(struct SharedMemoryCommand* command, double halfExtentsX,double halfExtentsY,double halfExtentsZ); + + + int b3CreateSensorCommandInit(struct SharedMemoryCommand* command); +int b3CreateSensorEnable6DofJointForceTorqueSensor(struct SharedMemoryCommand* command, int dofIndex, int enable); + + +int b3RequestActualStateCommandInit(struct SharedMemoryCommand* command); + #ifdef __cplusplus } diff --git a/examples/SharedMemory/PhysicsClientExample.cpp b/examples/SharedMemory/PhysicsClientExample.cpp index 929727963..3f7e6a833 100644 --- a/examples/SharedMemory/PhysicsClientExample.cpp +++ b/examples/SharedMemory/PhysicsClientExample.cpp @@ -215,11 +215,11 @@ void PhysicsClientExample::stepSimulation(float deltaTime) bool hasStatus = m_physicsClient.processServerStatus(status); if (hasStatus && status.m_type == CMD_URDF_LOADING_COMPLETED) { - for (int i=0;i m_jointFeedbacks; + btAlignedObjectArray m_multiBodyJointFeedbacks; btAlignedObjectArray m_worldImporters; btAlignedObjectArray m_urdfLinkNameMapper; @@ -98,11 +98,12 @@ bool PhysicsServerSharedMemory::connectSharedMemory(bool allowSharedMemoryInitia m_data->m_guiHelper = guiHelper; bool allowCreation = true; + bool allowConnectToExistingSharedMemory = false; m_data->m_testBlock1 = (SharedMemoryBlock*)m_data->m_sharedMemory->allocateSharedMemory(SHARED_MEMORY_KEY, SHARED_MEMORY_SIZE,allowCreation); if (m_data->m_testBlock1) { - if (m_data->m_testBlock1->m_magicId !=SHARED_MEMORY_MAGIC_NUMBER) + if (!allowConnectToExistingSharedMemory || (m_data->m_testBlock1->m_magicId !=SHARED_MEMORY_MAGIC_NUMBER)) { if (allowSharedMemoryInitialization) { @@ -287,16 +288,7 @@ bool PhysicsServerSharedMemory::loadUrdf(const char* fileName, const btVector3& } else { btAssert(0); - /* - for (int i=0;im_dynamicsWorld->getNumConstraints();i++) - { - btTypedConstraint* c = m_data->m_dynamicsWorld->getConstraint(i); - btJointFeedback* fb = new btJointFeedback(); - m_data->m_jointFeedbacks.push_back(fb); - c->setJointFeedback(fb); - - } - */ + return true; } @@ -407,6 +399,69 @@ void PhysicsServerSharedMemory::processClientCommands() + break; + } + case CMD_CREATE_SENSOR: + { + b3Printf("Processed CMD_CREATE_SENSOR"); + + if (m_data->m_dynamicsWorld->getNumMultibodies()>0) + { + btMultiBody* mb = m_data->m_dynamicsWorld->getMultiBody(0); + btAssert(mb); + for (int i=0;igetLink(jointIndex).m_jointFeedback) + { + b3Warning("CMD_CREATE_SENSOR: sensor for joint [%d] already enabled", jointIndex); + } else + { + btMultiBodyJointFeedback* fb = new btMultiBodyJointFeedback(); + fb->m_reactionForces.setZero(); + mb->getLink(jointIndex).m_jointFeedback = fb; + m_data->m_multiBodyJointFeedbacks.push_back(fb); + }; + + } else + { + if (mb->getLink(jointIndex).m_jointFeedback) + { + m_data->m_multiBodyJointFeedbacks.remove(mb->getLink(jointIndex).m_jointFeedback); + delete mb->getLink(jointIndex).m_jointFeedback; + mb->getLink(jointIndex).m_jointFeedback=0; + } else + { + b3Warning("CMD_CREATE_SENSOR: cannot perform sensor removal request, no sensor on joint [%d]", jointIndex); + }; + + } + } + + } else + { + b3Warning("No btMultiBody in the world. btRigidBody/btTypedConstraint sensor not hooked up yet"); + } + +#if 0 + //todo(erwincoumans) here is some sample code to hook up a force/torque sensor for btTypedConstraint/btRigidBody + /* + for (int i=0;im_dynamicsWorld->getNumConstraints();i++) + { + btTypedConstraint* c = m_data->m_dynamicsWorld->getConstraint(i); + btJointFeedback* fb = new btJointFeedback(); + m_data->m_jointFeedbacks.push_back(fb); + c->setJointFeedback(fb); + + + } + */ +#endif + + SharedMemoryStatus& serverCmd =m_data->createServerStatus(CMD_CLIENT_COMMAND_COMPLETED,clientCmd.m_sequenceNumber,timeStamp); + m_data->submitServerStatus(serverCmd); break; } case CMD_SEND_DESIRED_STATE: @@ -448,6 +503,8 @@ void PhysicsServerSharedMemory::processClientCommands() } case CONTROL_MODE_VELOCITY: { + b3Printf("Using CONTROL_MODE_VELOCITY"); + int numMotors = 0; //find the joint motors and apply the desired velocity and maximum force/torque if (m_data->m_dynamicsWorld->getNumMultibodies()>0) @@ -475,7 +532,6 @@ void PhysicsServerSharedMemory::processClientCommands() dofIndex += mb->getLink(link).m_dofCount; } } - b3Printf("Using CONTROL_MODE_TORQUE with %d motors", numMotors); break; } default: @@ -544,7 +600,26 @@ void PhysicsServerSharedMemory::processClientCommands() { serverCmd.m_sendActualStateArgs.m_actualStateQdot[totalDegreeOfFreedomU++] = mb->getJointVelMultiDof(l)[d]; } - + + if (0 == mb->getLink(l).m_jointFeedback) + { + for (int d=0;d<6;d++) + { + serverCmd.m_sendActualStateArgs.m_jointReactionForces[l*6+d]=0; + } + } else + { + btVector3 sensedForce = mb->getLink(l).m_jointFeedback->m_reactionForces.getLinear(); + btVector3 sensedTorque = mb->getLink(l).m_jointFeedback->m_reactionForces.getLinear(); + + serverCmd.m_sendActualStateArgs.m_jointReactionForces[l*6+0] = sensedForce[0]; + serverCmd.m_sendActualStateArgs.m_jointReactionForces[l*6+1] = sensedForce[1]; + serverCmd.m_sendActualStateArgs.m_jointReactionForces[l*6+2] = sensedForce[2]; + + serverCmd.m_sendActualStateArgs.m_jointReactionForces[l*6+3] = sensedTorque[0]; + serverCmd.m_sendActualStateArgs.m_jointReactionForces[l*6+4] = sensedTorque[1]; + serverCmd.m_sendActualStateArgs.m_jointReactionForces[l*6+5] = sensedTorque[2]; + } } serverCmd.m_sendActualStateArgs.m_numDegreeOfFreedomQ = totalDegreeOfFreedomQ; @@ -617,11 +692,33 @@ void PhysicsServerSharedMemory::processClientCommands() } case CMD_CREATE_BOX_COLLISION_SHAPE: { - btVector3 halfExtents(30,30,1); + btVector3 halfExtents(1,1,1); + if (clientCmd.m_updateFlags | BOX_SHAPE_HAS_HALF_EXTENTS) + { + halfExtents = btVector3( + clientCmd.m_createBoxShapeArguments.m_halfExtentsX, + clientCmd.m_createBoxShapeArguments.m_halfExtentsY, + clientCmd.m_createBoxShapeArguments.m_halfExtentsZ); + } btTransform startTrans; startTrans.setIdentity(); - startTrans.setOrigin(btVector3(0,0,-4)); - + if (clientCmd.m_updateFlags | BOX_SHAPE_HAS_INITIAL_POSITION) + { + startTrans.setOrigin(btVector3( + clientCmd.m_createBoxShapeArguments.m_initialPosition[0], + clientCmd.m_createBoxShapeArguments.m_initialPosition[1], + clientCmd.m_createBoxShapeArguments.m_initialPosition[2])); + } + + if (clientCmd.m_updateFlags | BOX_SHAPE_HAS_INITIAL_ORIENTATION) + { + startTrans.setRotation(btQuaternion( + clientCmd.m_createBoxShapeArguments.m_initialOrientation[0], + clientCmd.m_createBoxShapeArguments.m_initialOrientation[1], + clientCmd.m_createBoxShapeArguments.m_initialOrientation[2], + clientCmd.m_createBoxShapeArguments.m_initialOrientation[3])); + } + btBulletWorldImporter* worldImporter = new btBulletWorldImporter(m_data->m_dynamicsWorld); m_data->m_worldImporters.push_back(worldImporter); diff --git a/examples/SharedMemory/RobotControlExample.cpp b/examples/SharedMemory/RobotControlExample.cpp index 1ccb38e25..d9ec47176 100644 --- a/examples/SharedMemory/RobotControlExample.cpp +++ b/examples/SharedMemory/RobotControlExample.cpp @@ -167,8 +167,13 @@ void MyCallback2(int buttonId, bool buttonState, void* userPtr) for (int i=0;im_numMotors;i++) { btScalar targetVel = cl->m_motorTargetVelocities[i].m_velTarget; + int uIndex = cl->m_motorTargetVelocities[i].m_uIndex; - command.m_sendDesiredStateCommandArgument.m_desiredStateQdot[uIndex] = targetVel; + if (targetVel>1) + { + printf("testme"); + } + command.m_sendDesiredStateCommandArgument.m_desiredStateQdot[uIndex] = targetVel; } break; @@ -300,26 +305,29 @@ void RobotControlExample::stepSimulation(float deltaTime) bool hasStatus = m_physicsClient.processServerStatus(status); if (hasStatus && status.m_type == CMD_URDF_LOADING_COMPLETED) { - for (int i=0;im_velTarget = 0.f; - motorInfo->m_uIndex = info.m_uIndex; - - SliderParams slider(motorName,&motorInfo->m_velTarget); - slider.m_minVal=-4; - slider.m_maxVal=4; - m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); - m_numMotors++; - } + if (info.m_flags & JOINT_HAS_MOTORIZED_POWER) + { + if (m_numMotorsm_velTarget = 0.f; + motorInfo->m_uIndex = info.m_uIndex; + + SliderParams slider(motorName,&motorInfo->m_velTarget); + slider.m_minVal=-4; + slider.m_maxVal=4; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + m_numMotors++; + } + } } } diff --git a/examples/SharedMemory/SharedMemoryCommands.h b/examples/SharedMemory/SharedMemoryCommands.h index c399fcda0..f99a9e114 100644 --- a/examples/SharedMemory/SharedMemoryCommands.h +++ b/examples/SharedMemory/SharedMemoryCommands.h @@ -30,10 +30,11 @@ enum EnumSharedMemoryClientCommand // CMD_DELETE_BOX_COLLISION_SHAPE, // CMD_CREATE_RIGID_BODY, // CMD_DELETE_RIGID_BODY, -// CMD_SET_JOINT_FEEDBACK,///enable or disable joint feedback for force/torque sensors + CMD_CREATE_SENSOR,///enable or disable joint feedback for force/torque sensors +// CMD_REQUEST_SENSOR_MEASUREMENTS,//see CMD_REQUEST_ACTUAL_STATE/CMD_ACTUAL_STATE_UPDATE_COMPLETED CMD_INIT_POSE, CMD_SEND_PHYSICS_SIMULATION_PARAMETERS, - CMD_SEND_DESIRED_STATE, + CMD_SEND_DESIRED_STATE,//todo: reconsider naming, for example SET_JOINT_CONTROL_VARIABLE? CMD_REQUEST_ACTUAL_STATE, CMD_STEP_FORWARD_SIMULATION, CMD_SHUTDOWN, @@ -42,7 +43,7 @@ enum EnumSharedMemoryClientCommand enum EnumSharedMemoryServerStatus { - CMD_SHARED_MEMORY_NOT_INITIALIZED, + CMD_SHARED_MEMORY_NOT_INITIALIZED=0, CMD_WAITING_FOR_CLIENT_COMMAND, //CMD_CLIENT_COMMAND_COMPLETED is a generic 'completed' status that doesn't need special handling on the client @@ -65,8 +66,8 @@ enum EnumSharedMemoryServerStatus }; #define SHARED_MEMORY_SERVER_TEST_C -#define MAX_DEGREE_OF_FREEDOM 1024 -#define MAX_NUM_SENSORS 1024 +#define MAX_DEGREE_OF_FREEDOM 256 +#define MAX_NUM_SENSORS 256 #define MAX_URDF_FILENAME_LENGTH 1024 enum EnumUrdfArgsUpdateFlags @@ -105,7 +106,7 @@ struct SetJointFeedbackArgs //todo: discuss and decide about control mode and combinations enum { // POSITION_CONTROL=0, - CONTROL_MODE_VELOCITY, + CONTROL_MODE_VELOCITY=0, CONTROL_MODE_TORQUE, }; @@ -173,13 +174,38 @@ struct SendActualStateArgs //actual state is only written by the server, read-only access by client is expected double m_actualStateQ[MAX_DEGREE_OF_FREEDOM]; double m_actualStateQdot[MAX_DEGREE_OF_FREEDOM]; - double m_actualStateSensors[MAX_NUM_SENSORS];//these are force sensors and IMU information + + //measured 6DOF force/torque sensors: force[x,y,z] and torque[x,y,z] + double m_jointReactionForces[6*MAX_DEGREE_OF_FREEDOM]; }; +struct CreateSensorArgs +{ + int m_bodyUniqueId; + int m_numJointSensorChanges; + int m_jointIndex[MAX_DEGREE_OF_FREEDOM]; + int m_enableJointForceSensor[MAX_DEGREE_OF_FREEDOM]; +}; typedef struct SharedMemoryCommand SharedMemoryCommand_t; +enum EnumBoxShapeFlags +{ + BOX_SHAPE_HAS_INITIAL_POSITION=1, + BOX_SHAPE_HAS_INITIAL_ORIENTATION=2, + BOX_SHAPE_HAS_HALF_EXTENTS=4 +}; +///This command will be replaced to allow arbitrary collision shape types +struct CreateBoxShapeArgs +{ + double m_halfExtentsX; + double m_halfExtentsY; + double m_halfExtentsZ; + + double m_initialPosition[3]; + double m_initialOrientation[4]; +}; struct SharedMemoryCommand { @@ -199,6 +225,8 @@ struct SharedMemoryCommand struct BulletDataStreamArgs m_dataStreamArguments; struct SendDesiredStateArgs m_sendDesiredStateCommandArgument; struct RequestActualStateArgs m_requestActualStateInformationCommandArgument; + struct CreateSensorArgs m_createSensorArguments; + struct CreateBoxShapeArgs m_createBoxShapeArguments; }; }; @@ -219,15 +247,22 @@ struct SharedMemoryStatus typedef struct SharedMemoryStatus SharedMemoryStatus_t; -struct PoweredJointInfo +enum JointInfoFlags +{ + JOINT_HAS_MOTORIZED_POWER=1, +}; +struct b3JointInfo { char* m_linkName; char* m_jointName; int m_jointType; int m_qIndex; int m_uIndex; + /// + int m_flags; }; + #endif //SHARED_MEMORY_COMMANDS_H diff --git a/src/Bullet3Common/b3Logging.h b/src/Bullet3Common/b3Logging.h index 8d8ad4dcb..b302effe4 100644 --- a/src/Bullet3Common/b3Logging.h +++ b/src/Bullet3Common/b3Logging.h @@ -2,6 +2,10 @@ #ifndef B3_LOGGING_H #define B3_LOGGING_H +#ifdef __cplusplus +extern "C" { +#endif + ///We add the do/while so that the statement "if (condition) b3Printf("test"); else {...}" would fail ///You can also customize the message by uncommenting out a different line below #define b3Printf(...) b3OutputPrintfVarArgsInternal(__VA_ARGS__) @@ -18,6 +22,7 @@ void b3EnterProfileZone(const char* name); void b3LeaveProfileZone(); +#ifdef __cplusplus class b3ProfileZone { @@ -34,6 +39,7 @@ public: }; #define B3_PROFILE( name ) b3ProfileZone __profile( name ) +#endif #else //B3_NO_PROFILE @@ -64,6 +70,8 @@ void b3OutputPrintfVarArgsInternal(const char *str, ...); void b3OutputWarningMessageVarArgsInternal(const char *str, ...); void b3OutputErrorMessageVarArgsInternal(const char *str, ...); - +#ifdef __cplusplus + } +#endif #endif//B3_LOGGING_H \ No newline at end of file diff --git a/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/src/BulletCollision/CollisionShapes/btConvexShape.cpp index f03d0b21e..b56d72917 100644 --- a/src/BulletCollision/CollisionShapes/btConvexShape.cpp +++ b/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -48,7 +48,7 @@ btConvexShape::~btConvexShape() } -void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const +void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max, btVector3& witnesPtMin,btVector3& witnesPtMax) const { btVector3 localAxis = dir*trans.getBasis(); btVector3 vtx1 = trans(localGetSupportingVertex(localAxis)); @@ -56,12 +56,16 @@ void btConvexShape::project(const btTransform& trans, const btVector3& dir, btSc min = vtx1.dot(dir); max = vtx2.dot(dir); - + witnesPtMax = vtx2; + witnesPtMin = vtx1; + if(min>max) { btScalar tmp = min; min = max; max = tmp; + witnesPtMax = vtx1; + witnesPtMin = vtx2; } } diff --git a/src/BulletCollision/CollisionShapes/btConvexShape.h b/src/BulletCollision/CollisionShapes/btConvexShape.h index 290cd9fd1..875f2ac19 100644 --- a/src/BulletCollision/CollisionShapes/btConvexShape.h +++ b/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -52,7 +52,8 @@ public: btScalar getMarginNonVirtual () const; void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const; - virtual void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const; + + virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const; //notice that the vectors should be unit length diff --git a/src/BulletDynamics/Featherstone/btMultiBody.cpp b/src/BulletDynamics/Featherstone/btMultiBody.cpp index 1b6e0b9b5..1f6f7aa90 100644 --- a/src/BulletDynamics/Featherstone/btMultiBody.cpp +++ b/src/BulletDynamics/Featherstone/btMultiBody.cpp @@ -846,8 +846,8 @@ void btMultiBody::stepVelocitiesMultiDof(btScalar dt, btVector3 linkAppliedTorque =isConstraintPass ? m_links[i].m_appliedConstraintTorque : m_links[i].m_appliedTorque; zeroAccSpatFrc[i+1].setVector(-(rot_from_world[i+1] * linkAppliedTorque), -(rot_from_world[i+1] * linkAppliedForce )); - - if (0) + +#if 0 { b3Printf("stepVelocitiesMultiDof zeroAccSpatFrc[%d] linear:%f,%f,%f, angular:%f,%f,%f", @@ -860,6 +860,7 @@ void btMultiBody::stepVelocitiesMultiDof(btScalar dt, zeroAccSpatFrc[i+1].m_bottomVec[1], zeroAccSpatFrc[i+1].m_bottomVec[2]); } +#endif // //adding damping terms (only) btScalar linDampMult = 1., angDampMult = 1.; diff --git a/test/SharedMemory/test.c b/test/SharedMemory/test.c index 65837e8b2..9a0ecc924 100644 --- a/test/SharedMemory/test.c +++ b/test/SharedMemory/test.c @@ -1,6 +1,8 @@ #include "SharedMemoryBlock.h" #include "PhysicsClientC_API.h" #include "SharedMemoryCommands.h" +#include "Bullet3Common/b3Logging.h" +#include struct test { @@ -8,17 +10,21 @@ struct test }; #include -#define MAX_TIMEOUT 1024 +#define MAX_TIMEOUT 1024*1024*1024 int main(int argc, char* argv[]) { int ret ,allowSharedMemoryInitialization=0; int timeout = MAX_TIMEOUT; + int sensorJointIndexLeft=-1; + int sensorJointIndexRight=-1; + const char* urdfFileName = "r2d2.urdf"; - double gravx=0, gravy=0, gravz=0; + double gravx=0, gravy=0, gravz=-9.8; double timeStep = 1./60.; double startPosX, startPosY,startPosZ; - + b3Printf("timeout = %d\n",timeout); + SharedMemoryCommand_t command; SharedMemoryStatus_t status; @@ -34,7 +40,8 @@ int main(int argc, char* argv[]) ret = b3SubmitClientCommand(sm, &command); timeout = MAX_TIMEOUT; while ((timeout-- > 0) && b3ProcessServerStatus(sm, &status)==0) {} - + b3Printf("timeout = %d\n",timeout); + ret = b3LoadUrdfCommandInit(&command, urdfFileName); //setting the initial position, orientation and other arguments are optional @@ -46,14 +53,103 @@ int main(int argc, char* argv[]) ret = b3SubmitClientCommand(sm, &command); timeout = MAX_TIMEOUT; while ((timeout-- > 0) && b3ProcessServerStatus(sm, &status)==0) {} - - + b3Printf("timeout = %d\n",timeout); + + int numJoints = b3GetNumJoints(sm); + for (int i=0;i=0) || (sensorJointIndexRight>=0)) + { + ret = b3CreateSensorCommandInit(&command); + if (sensorJointIndexLeft>=0) + { + ret = b3CreateSensorEnable6DofJointForceTorqueSensor(&command, sensorJointIndexLeft, 1); + } + if(sensorJointIndexRight>=0) + { + ret = b3CreateSensorEnable6DofJointForceTorqueSensor(&command, sensorJointIndexRight, 1); + } + ret = b3SubmitClientCommand(sm, &command); + timeout = MAX_TIMEOUT; + while ((timeout-- > 0) && b3ProcessServerStatus(sm, &status)==0) {} + } + + ret = b3CreateBoxShapeCommandInit(&command); + ret = b3CreateBoxCommandSetStartPosition(&command, 0,0,-1); + ret = b3CreateBoxCommandSetStartOrientation(&command,0,0,0,1); + ret = b3CreateBoxCommandSetHalfExtents(&command, 10,10,1); + ret = b3SubmitClientCommand(sm, &command); + timeout = MAX_TIMEOUT; + while ((timeout-- > 0) && b3ProcessServerStatus(sm, &status)==0) {} + + + b3RequestActualStateCommandInit(&command); + ret = b3SubmitClientCommand(sm, &command); + timeout = MAX_TIMEOUT; + while ((timeout-- > 0) && b3ProcessServerStatus(sm, &status)==0) {} - - ret = b3InitStepSimulationCommand(&command); + int posVarCount =status.m_sendActualStateArgs.m_numDegreeOfFreedomQ; + int dofCount =status.m_sendActualStateArgs.m_numDegreeOfFreedomU; + + b3Printf("posVarCount = %d\n",posVarCount); + printf("dofCount = %d\n",dofCount); + + b3JointControlCommandInit(&command, CONTROL_MODE_VELOCITY); + for (int dofIndex=0;dofIndex 0) && b3ProcessServerStatus(sm, &status)==0) {} + + ///perform some simulation steps for testing + for (int i=0;i<100;i++) + { + ret = b3InitStepSimulationCommand(&command); + ret = b3SubmitClientCommand(sm, &command); + timeout = MAX_TIMEOUT; + while ((timeout-- > 0) && b3ProcessServerStatus(sm, &status)==0) {} + } + + b3RequestActualStateCommandInit(&command); + ret = b3SubmitClientCommand(sm, &command); + timeout = MAX_TIMEOUT; + while ((timeout-- > 0) && b3ProcessServerStatus(sm, &status)==0) {} + + if (sensorJointIndexLeft>=0) + { + b3Printf("Sensor for joint [%d] = %f,%f,%f\n", sensorJointIndexLeft, + status.m_sendActualStateArgs.m_jointReactionForces[6*sensorJointIndexLeft+0], + status.m_sendActualStateArgs.m_jointReactionForces[6*sensorJointIndexLeft+1], + status.m_sendActualStateArgs.m_jointReactionForces[6*sensorJointIndexLeft+2]); + } + + if (sensorJointIndexRight>=0) + { + b3Printf("Sensor for joint [%d] = %f,%f,%f\n", sensorJointIndexRight, + status.m_sendActualStateArgs.m_jointReactionForces[6*sensorJointIndexRight+0], + status.m_sendActualStateArgs.m_jointReactionForces[6*sensorJointIndexRight+1], + status.m_sendActualStateArgs.m_jointReactionForces[6*sensorJointIndexRight+2]); + } + + } b3DisconnectSharedMemory(sm); }