From 53a0772257e2b1bb144df2f3129a784502652ab4 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Thu, 16 Jun 2016 18:46:34 -0700 Subject: [PATCH] fix some issues related to controlling a robot/multibody beyond body index 0 (most testing happened with a single robot/multibody so far) preliminary pybullet.setJointControl implementation --- examples/SharedMemory/PhysicsClientC_API.cpp | 8 +- examples/SharedMemory/PhysicsClientC_API.h | 4 +- .../SharedMemory/PhysicsClientExample.cpp | 82 ++++++-- .../PhysicsServerCommandProcessor.cpp | 24 +-- examples/pybullet/pybullet.c | 195 +++++++++++++++--- .../Featherstone/btMultiBodyLink.h | 3 + test/SharedMemory/test.c | 2 +- 7 files changed, 248 insertions(+), 70 deletions(-) diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp index a627e08af..77e6060bf 100644 --- a/examples/SharedMemory/PhysicsClientC_API.cpp +++ b/examples/SharedMemory/PhysicsClientC_API.cpp @@ -150,7 +150,7 @@ b3SharedMemoryCommandHandle b3InitResetSimulationCommand(b3PhysicsClientHand } -b3SharedMemoryCommandHandle b3JointControlCommandInit( b3PhysicsClientHandle physClient, int controlMode) +b3SharedMemoryCommandHandle b3JointControlCommandInit( b3PhysicsClientHandle physClient, int bodyUniqueId, int controlMode) { PhysicsClient* cl = (PhysicsClient* ) physClient; b3Assert(cl); @@ -159,7 +159,7 @@ b3SharedMemoryCommandHandle b3JointControlCommandInit( b3PhysicsClientHandle phy b3Assert(command); command->m_type = CMD_SEND_DESIRED_STATE; command->m_sendDesiredStateCommandArgument.m_controlMode = controlMode; - command->m_sendDesiredStateCommandArgument.m_bodyUniqueId = 0; + command->m_sendDesiredStateCommandArgument.m_bodyUniqueId = bodyUniqueId; command->m_updateFlags = 0; return (b3SharedMemoryCommandHandle) command; } @@ -433,7 +433,7 @@ int b3CreatePoseCommandSetJointPosition(b3PhysicsClientHandle physClient, b3Shar -b3SharedMemoryCommandHandle b3CreateSensorCommandInit(b3PhysicsClientHandle physClient) +b3SharedMemoryCommandHandle b3CreateSensorCommandInit(b3PhysicsClientHandle physClient, int bodyUniqueId) { PhysicsClient* cl = (PhysicsClient* ) physClient; b3Assert(cl); @@ -444,7 +444,7 @@ b3SharedMemoryCommandHandle b3CreateSensorCommandInit(b3PhysicsClientHandle phys command->m_type = CMD_CREATE_SENSOR; command->m_updateFlags = 0; command->m_createSensorArguments.m_numJointSensorChanges = 0; - command->m_createSensorArguments.m_bodyUniqueId = 0; + command->m_createSensorArguments.m_bodyUniqueId = bodyUniqueId; return (b3SharedMemoryCommandHandle) command; } diff --git a/examples/SharedMemory/PhysicsClientC_API.h b/examples/SharedMemory/PhysicsClientC_API.h index 4ae1a5235..3813fab88 100644 --- a/examples/SharedMemory/PhysicsClientC_API.h +++ b/examples/SharedMemory/PhysicsClientC_API.h @@ -95,7 +95,7 @@ b3SharedMemoryCommandHandle b3LoadSdfCommandInit(b3PhysicsClientHandle physClien ///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) -b3SharedMemoryCommandHandle b3JointControlCommandInit(b3PhysicsClientHandle physClient, int controlMode); +b3SharedMemoryCommandHandle b3JointControlCommandInit(b3PhysicsClientHandle physClient, int bodyUniqueId, int controlMode); ///Only use when controlMode is CONTROL_MODE_POSITION_VELOCITY_PD int b3JointControlSetDesiredPosition(b3SharedMemoryCommandHandle commandHandle, int qIndex, double value); int b3JointControlSetKp(b3SharedMemoryCommandHandle commandHandle, int dofIndex, double value); @@ -132,7 +132,7 @@ int b3CreatePoseCommandSetJointPosition(b3PhysicsClientHandle physClient, b3Shar ///We are currently not reading the sensor information from the URDF file, and programmatically assign sensors. ///This is rather inconsistent, to mix programmatical creation with loading from file. -b3SharedMemoryCommandHandle b3CreateSensorCommandInit(b3PhysicsClientHandle physClient); +b3SharedMemoryCommandHandle b3CreateSensorCommandInit(b3PhysicsClientHandle physClient, int bodyUniqueId); int b3CreateSensorEnable6DofJointForceTorqueSensor(b3SharedMemoryCommandHandle commandHandle, int jointIndex, int enable); ///b3CreateSensorEnableIMUForLink is not implemented yet. ///For now, if the IMU is located in the root link, use the root world transform to mimic an IMU. diff --git a/examples/SharedMemory/PhysicsClientExample.cpp b/examples/SharedMemory/PhysicsClientExample.cpp index 691dbb9c6..e0338153a 100644 --- a/examples/SharedMemory/PhysicsClientExample.cpp +++ b/examples/SharedMemory/PhysicsClientExample.cpp @@ -37,6 +37,9 @@ protected: bool m_wantsTermination; btAlignedObjectArray m_userCommandRequests; + btAlignedObjectArray m_bodyUniqueIds; + + int m_sharedMemoryKey; int m_selectedBody; int m_prevSelectedBody; @@ -66,7 +69,8 @@ protected: { if (m_guiHelper && m_guiHelper->getParameterInterface()) { - int bodyIndex = comboIndex; + int itemIndex = int(atoi(name)); + int bodyIndex = m_bodyUniqueIds[itemIndex]; if (m_selectedBody != bodyIndex) { m_selectedBody = bodyIndex; @@ -154,14 +158,20 @@ protected: void prepareControlCommand(b3SharedMemoryCommandHandle commandHandle) { + for (int i=0;i=0) + { + // b3SharedMemoryCommandHandle command = b3JointControlCommandInit( m_physicsClientHandle, m_selectedBody, CONTROL_MODE_VELOCITY); + b3SharedMemoryCommandHandle command = b3JointControlCommandInit( m_physicsClientHandle, m_selectedBody, CONTROL_MODE_POSITION_VELOCITY_PD); + // b3Printf("prepare control command for body %d", m_selectedBody); + prepareControlCommand(command); + + b3SubmitClientCommand(m_physicsClientHandle, command); - break; + } + break; } case CMD_RESET_SIMULATION: { @@ -471,9 +488,36 @@ void PhysicsClientExample::createButtons() createButton("Initialize Pose",CMD_INIT_POSE, isTrigger); createButton("Set gravity", CMD_SEND_PHYSICS_SIMULATION_PARAMETERS, isTrigger); + if (m_bodyUniqueIds.size()) + { + if (m_selectedBody<0) + m_selectedBody = 0; + + ComboBoxParams comboParams; + comboParams.m_comboboxId = 0; + comboParams.m_numItems = m_bodyUniqueIds.size(); + comboParams.m_startItem = m_selectedBody; + comboParams.m_callback = MyComboBoxCallback; + comboParams.m_userPointer = this; + //todo: get the real object name + + const char** blarray = new const char*[m_bodyUniqueIds.size()]; + + for (int i=0;igetParameterInterface()->registerComboBox(comboParams); + } + if (m_physicsClientHandle && m_selectedBody>=0) { + m_numMotors = 0; + int numJoints = b3GetNumJoints(m_physicsClientHandle,m_selectedBody); for (int i=0;i0) + { + m_selectedBody = bodyUniqueId; + } +/* int numJoints = b3GetNumJoints(m_physicsClientHandle,bodyUniqueId); b3Printf("numJoints = %d", numJoints); for (int i=0;i=0) { + m_bodyUniqueIds.push_back(bodyIndex); + m_selectedBody = bodyIndex; int numJoints = b3GetNumJoints(m_physicsClientHandle,bodyIndex); for (int i=0;igetParameterInterface()->registerComboBox(comboParams); + } } } @@ -759,6 +800,7 @@ void PhysicsClientExample::stepSimulation(float deltaTime) { m_selectedBody = -1; m_numMotors=0; + m_bodyUniqueIds.clear(); createButtons(); b3SharedMemoryCommandHandle commandHandle = b3InitResetSimulationCommand(m_physicsClientHandle); if (m_options == eCLIENTEXAMPLE_SERVER) diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp index e3a9b7f48..33d7d3153 100644 --- a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp +++ b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp @@ -382,7 +382,6 @@ struct PhysicsServerCommandProcessorInternalData btAlignedObjectArray m_worldImporters; btAlignedObjectArray m_urdfLinkNameMapper; - btHashMap m_multiBodyJointMotorMap; btAlignedObjectArray m_strings; btAlignedObjectArray m_collisionShapes; @@ -560,7 +559,6 @@ void PhysicsServerCommandProcessor::deleteDynamicsWorld() } m_data->m_urdfLinkNameMapper.clear(); - m_data->m_multiBodyJointMotorMap.clear(); for (int i=0;im_strings.size();i++) { @@ -672,7 +670,7 @@ void PhysicsServerCommandProcessor::createJointMotors(btMultiBody* mb) btScalar desiredVelocity = 0.f; btMultiBodyJointMotor* motor = new btMultiBodyJointMotor(mb,mbLinkIndex,dof,desiredVelocity,maxMotorImpulse); //motor->setMaxAppliedImpulse(0); - m_data->m_multiBodyJointMotorMap.insert(mbLinkIndex,motor); + mb->getLink(mbLinkIndex).m_userPtr = motor; m_data->m_dynamicsWorld->addMultiBodyConstraint(motor); motor->finalizeMultiDof(); @@ -1436,10 +1434,11 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm if (supportsJointMotor(mb,link)) { - btMultiBodyJointMotor** motorPtr = m_data->m_multiBodyJointMotorMap[link]; - if (motorPtr) + btMultiBodyJointMotor* motor = (btMultiBodyJointMotor*)mb->getLink(link).m_userPtr; + + + if (motor) { - btMultiBodyJointMotor* motor = *motorPtr; btScalar desiredVelocity = 0.f; if ((clientCmd.m_updateFlags&SIM_DESIRED_STATE_HAS_QDOT)!=0) desiredVelocity = clientCmd.m_sendDesiredStateCommandArgument.m_desiredStateQdot[dofIndex]; @@ -1479,10 +1478,11 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm if (supportsJointMotor(mb,link)) { - btMultiBodyJointMotor** motorPtr = m_data->m_multiBodyJointMotorMap[link]; - if (motorPtr) + + btMultiBodyJointMotor* motor = (btMultiBodyJointMotor*)mb->getLink(link).m_userPtr; + + if (motor) { - btMultiBodyJointMotor* motor = *motorPtr; btScalar desiredVelocity = 0.f; if ((clientCmd.m_updateFlags & SIM_DESIRED_STATE_HAS_QDOT)!=0) @@ -1644,10 +1644,10 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm if (supportsJointMotor(mb,l)) { - btMultiBodyJointMotor** motorPtr = m_data->m_multiBodyJointMotorMap[l]; - if (motorPtr && m_data->m_physicsDeltaTime>btScalar(0)) + btMultiBodyJointMotor* motor = (btMultiBodyJointMotor*)body->m_multiBody->getLink(l).m_userPtr; + + if (motor && m_data->m_physicsDeltaTime>btScalar(0)) { - btMultiBodyJointMotor* motor = *motorPtr; btScalar force =motor->getAppliedImpulse(0)/m_data->m_physicsDeltaTime; serverCmd.m_sendActualStateArgs.m_jointMotorForce[l] = force; diff --git a/examples/pybullet/pybullet.c b/examples/pybullet/pybullet.c index 17c092b2d..fbd070ff9 100644 --- a/examples/pybullet/pybullet.c +++ b/examples/pybullet/pybullet.c @@ -1,6 +1,6 @@ -#include "../SharedMemory/SharedMemoryInProcessPhysicsC_API.h" #include "../SharedMemory/PhysicsClientC_API.h" #include "../SharedMemory/PhysicsDirectC_API.h" +#include "../SharedMemory/SharedMemoryInProcessPhysicsC_API.h" #ifdef __APPLE__ @@ -16,6 +16,8 @@ enum eCONNECT_METHOD eCONNECT_SHARED_MEMORY=3, }; + + static PyObject *SpamError; static b3PhysicsClientHandle sm=0; @@ -182,6 +184,25 @@ pybullet_loadURDF(PyObject* self, PyObject* args) return PyLong_FromLong(bodyIndex); } +static float pybullet_internalGetFloatFromSequence(PyObject* seq, int index) +{ + float v = 0.f; + PyObject* item; + + if (PyList_Check(seq)) + { + item = PyList_GET_ITEM(seq, index); + v = PyFloat_AsDouble(item); + } + else + { + item = PyTuple_GET_ITEM(seq,index); + v = PyFloat_AsDouble(item); + } + return v; +} + + #define MAX_SDF_BODIES 512 static PyObject* @@ -255,6 +276,109 @@ pybullet_resetSimulation(PyObject* self, PyObject* args) return Py_None; } +static int pybullet_setJointControl(PyObject* self, PyObject* args) +{ + //todo(erwincoumans): set max forces, kp, kd + + int size; + + if (0==sm) + { + PyErr_SetString(SpamError, "Not connected to physics server."); + return NULL; + } + + size= PySequence_Size(args); + + if (size==3) + { + int bodyIndex, controlMode; + PyObject* targetValues; + if (PyArg_ParseTuple(args, "iiO", &bodyIndex, &controlMode, &targetValues)) + { + PyObject* seq; + int numJoints, len; + seq = PySequence_Fast(targetValues, "expected a sequence"); + len = PySequence_Size(targetValues); + numJoints = b3GetNumJoints(sm,bodyIndex); + b3SharedMemoryCommandHandle commandHandle; + + if (len!=numJoints) + { + PyErr_SetString(SpamError, "Number of control target values doesn't match the number of joints."); + Py_DECREF(seq); + return NULL; + } + + if ((controlMode != CONTROL_MODE_VELOCITY) && + (controlMode != CONTROL_MODE_TORQUE) && + (controlMode != CONTROL_MODE_POSITION_VELOCITY_PD)) + { + PyErr_SetString(SpamError, "Illegral control mode."); + Py_DECREF(seq); + return NULL; + } + + commandHandle = b3JointControlCommandInit(sm, bodyIndex,controlMode); + + for (int qIndex=0;qIndex=0) || (sensorJointIndexRight>=0)) { - b3SharedMemoryCommandHandle command = b3CreateSensorCommandInit(sm); + b3SharedMemoryCommandHandle command = b3CreateSensorCommandInit(sm, bodyIndex); b3SharedMemoryStatusHandle statusHandle; if (imuLinkIndex>=0) {