#include "../SharedMemory/PhysicsClientC_API.h" #include "../SharedMemory/PhysicsDirectC_API.h" #include "../SharedMemory/SharedMemoryInProcessPhysicsC_API.h" #ifdef BT_ENABLE_ENET #include "../SharedMemory/PhysicsClientUDP_C_API.h" #endif //BT_ENABLE_ENET #ifdef __APPLE__ #include #else #include #endif #ifdef PYBULLET_USE_NUMPY #include #endif #if PY_MAJOR_VERSION >= 3 #define PyInt_FromLong PyLong_FromLong #define PyString_FromString PyBytes_FromString #endif enum eCONNECT_METHOD { eCONNECT_GUI = 1, eCONNECT_DIRECT = 2, eCONNECT_SHARED_MEMORY = 3, eCONNECT_UDP = 4, }; static PyObject* SpamError; #define MAX_PHYSICS_CLIENTS 1024 static b3PhysicsClientHandle sPhysicsClients1[MAX_PHYSICS_CLIENTS] = {0}; static int sNumPhysicsClients=0; b3PhysicsClientHandle getPhysicsClient(int physicsClientId) { b3PhysicsClientHandle sm; if ((physicsClientId <0) || (physicsClientId>=MAX_PHYSICS_CLIENTS) || (0 == sPhysicsClients1[physicsClientId])) { return 0; } sm = sPhysicsClients1[physicsClientId]; if (sm) { if (b3CanSubmitCommand(sm)) { return sm; } //broken connection? b3DisconnectSharedMemory(sm); sPhysicsClients1[physicsClientId] = 0; sNumPhysicsClients--; } return 0; } static double pybullet_internalGetFloatFromSequence(PyObject* seq, int index) { double v = 0.0; 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; } // internal function to set a float matrix[16] // used to initialize camera position with // a view and projection matrix in renderImage() // // // Args: // matrix - float[16] which will be set by values from objMat static int pybullet_internalSetMatrix(PyObject* objMat, float matrix[16]) { int i, len; PyObject* seq; seq = PySequence_Fast(objMat, "expected a sequence"); if (seq) { len = PySequence_Size(objMat); if (len == 16) { for (i = 0; i < len; i++) { matrix[i] = pybullet_internalGetFloatFromSequence(seq, i); } Py_DECREF(seq); return 1; } Py_DECREF(seq); } return 0; } // internal function to set a float vector[3] // used to initialize camera position with // a view and projection matrix in renderImage() // // // Args: // vector - float[3] which will be set by values from objMat static int pybullet_internalSetVector(PyObject* objVec, float vector[3]) { int i, len; PyObject* seq = 0; if (objVec == NULL) return 0; seq = PySequence_Fast(objVec, "expected a sequence"); if (seq) { len = PySequence_Size(objVec); if (len == 3) { for (i = 0; i < len; i++) { vector[i] = pybullet_internalGetFloatFromSequence(seq, i); } Py_DECREF(seq); return 1; } Py_DECREF(seq); } return 0; } // vector - double[3] which will be set by values from obVec static int pybullet_internalSetVectord(PyObject* obVec, double vector[3]) { int i, len; PyObject* seq; if (obVec == NULL) return 0; seq = PySequence_Fast(obVec, "expected a sequence"); if (seq) { len = PySequence_Size(obVec); if (len == 3) { for (i = 0; i < len; i++) { vector[i] = pybullet_internalGetFloatFromSequence(seq, i); } Py_DECREF(seq); return 1; } Py_DECREF(seq); } return 0; } // vector - double[3] which will be set by values from obVec static int pybullet_internalSetVector4d(PyObject* obVec, double vector[4]) { int i, len; PyObject* seq; if (obVec == NULL) return 0; seq = PySequence_Fast(obVec, "expected a sequence"); len = PySequence_Size(obVec); if (len == 4) { for (i = 0; i < len; i++) { vector[i] = pybullet_internalGetFloatFromSequence(seq, i); } Py_DECREF(seq); return 1; } Py_DECREF(seq); return 0; } // Step through one timestep of the simulation static PyObject* pybullet_stepSimulation(PyObject* self, PyObject* args, PyObject *keywds) { int physicsClientId = 0; static char *kwlist[] = { "physicsClientId", NULL }; b3PhysicsClientHandle sm=0; if (!PyArg_ParseTupleAndKeywords(args, keywds, "|i", kwlist,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3SharedMemoryStatusHandle statusHandle; int statusType; if (b3CanSubmitCommand(sm)) { statusHandle = b3SubmitClientCommandAndWaitStatus( sm, b3InitStepSimulationCommand(sm)); statusType = b3GetStatusType(statusHandle); } } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, PyObject* keywds) { int freeIndex = -1; int i; b3PhysicsClientHandle sm=0; if (sNumPhysicsClients>=MAX_PHYSICS_CLIENTS) { PyErr_SetString(SpamError, "Exceeding maximum number of physics connections."); return NULL; } { int method = eCONNECT_GUI; int key = SHARED_MEMORY_KEY; int port = 1234; const char* hostName = "localhost"; int size = PySequence_Size(args); if (size == 1) { if (!PyArg_ParseTuple(args, "i", &method)) { PyErr_SetString(SpamError, "connectPhysicsServer expected argument GUI, " "DIRECT, SHARED_MEMORY or UDP"); return NULL; } } if (size == 2) { if (!PyArg_ParseTuple(args, "ii", &method, &key)) { if (!PyArg_ParseTuple(args, "is", &method, &hostName)) { PyErr_SetString(SpamError, "connectPhysicsServer cannot parse second argument (either integer or string)"); return NULL; } } } if (size == 3) { if (!PyArg_ParseTuple(args, "isi", &method, &hostName, &port)) { PyErr_SetString(SpamError, "connectPhysicsServer 3 arguments: method, hostname, port"); return NULL; } } switch (method) { case eCONNECT_GUI: { int argc = 0; char* argv[1] = {0}; #ifdef __APPLE__ sm = b3CreateInProcessPhysicsServerAndConnectMainThread(argc, argv); #else sm = b3CreateInProcessPhysicsServerAndConnect(argc, argv); #endif break; } case eCONNECT_DIRECT: { sm = b3ConnectPhysicsDirect(); break; } case eCONNECT_SHARED_MEMORY: { sm = b3ConnectSharedMemory(key); break; } case eCONNECT_UDP: { #ifdef BT_ENABLE_ENET sm = b3ConnectPhysicsUDP(hostName, port); #else PyErr_SetString(SpamError, "UDP is not enabled in this pybullet build"); return NULL; #endif //BT_ENABLE_ENET break; } default: { PyErr_SetString(SpamError, "connectPhysicsServer unexpected argument"); return NULL; } }; } if (sm && b3CanSubmitCommand(sm)) { for (i=0;i=0) { sPhysicsClients1[freeIndex] = sm; sNumPhysicsClients++; } } return PyInt_FromLong(freeIndex); } static PyObject* pybullet_disconnectPhysicsServer(PyObject* self, PyObject* args, PyObject *keywds) { int physicsClientId = 0; b3PhysicsClientHandle sm=0; static char *kwlist[] = { "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "|i", kwlist,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3DisconnectSharedMemory(sm); sm = 0; } sPhysicsClients1[physicsClientId] = 0; sNumPhysicsClients--; Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_saveWorld(PyObject* self, PyObject* args,PyObject *keywds) { const char* worldFileName = ""; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "worldFileName","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|i", kwlist, &worldFileName,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3SharedMemoryCommandHandle command; b3SharedMemoryStatusHandle statusHandle; int statusType; command = b3SaveWorldCommandInit(sm, worldFileName); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); statusType = b3GetStatusType(statusHandle); if (statusType != CMD_SAVE_WORLD_COMPLETED) { PyErr_SetString(SpamError, "saveWorld command execution failed."); return NULL; } Py_INCREF(Py_None); return Py_None; } PyErr_SetString(SpamError, "Cannot execute saveWorld command."); return NULL; } #define MAX_SDF_BODIES 512 static PyObject* pybullet_loadBullet(PyObject* self, PyObject* args,PyObject *keywds) { const char* bulletFileName = ""; b3SharedMemoryStatusHandle statusHandle; int statusType; b3SharedMemoryCommandHandle command; int i,numBodies; int bodyIndicesOut[MAX_SDF_BODIES]; PyObject* pylist = 0; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bulletFileName","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|i", kwlist, &bulletFileName,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } command = b3LoadBulletCommandInit(sm, bulletFileName); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); statusType = b3GetStatusType(statusHandle); if (statusType != CMD_BULLET_LOADING_COMPLETED) { PyErr_SetString(SpamError, "Couldn't load .bullet file."); return NULL; } numBodies = b3GetStatusBodyIndices(statusHandle, bodyIndicesOut, MAX_SDF_BODIES); if (numBodies > MAX_SDF_BODIES) { PyErr_SetString(SpamError, "loadBullet exceeds body capacity"); return NULL; } pylist = PyTuple_New(numBodies); if (numBodies > 0 && numBodies <= MAX_SDF_BODIES) { for (i = 0; i < numBodies; i++) { PyTuple_SetItem(pylist, i, PyInt_FromLong(bodyIndicesOut[i])); } } return pylist; } static PyObject* pybullet_saveBullet(PyObject* self, PyObject* args, PyObject* keywds) { const char* bulletFileName = ""; b3SharedMemoryStatusHandle statusHandle; int statusType; b3SharedMemoryCommandHandle command; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bulletFileName","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|i", kwlist, &bulletFileName,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } command = b3SaveBulletCommandInit(sm, bulletFileName); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); statusType = b3GetStatusType(statusHandle); if (statusType != CMD_BULLET_SAVING_COMPLETED) { PyErr_SetString(SpamError, "Couldn't save .bullet file."); return NULL; } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_loadMJCF(PyObject* self, PyObject* args, PyObject* keywds) { const char* mjcfFileName = ""; b3SharedMemoryStatusHandle statusHandle; int statusType; b3SharedMemoryCommandHandle command; b3PhysicsClientHandle sm = 0; int numBodies = 0; int i; int bodyIndicesOut[MAX_SDF_BODIES]; PyObject* pylist = 0; int physicsClientId = 0; static char *kwlist[] = { "mjcfFileName","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|i", kwlist, &mjcfFileName,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } command = b3LoadMJCFCommandInit(sm, mjcfFileName); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); statusType = b3GetStatusType(statusHandle); if (statusType != CMD_MJCF_LOADING_COMPLETED) { PyErr_SetString(SpamError, "Couldn't load .mjcf file."); return NULL; } numBodies = b3GetStatusBodyIndices(statusHandle, bodyIndicesOut, MAX_SDF_BODIES); if (numBodies > MAX_SDF_BODIES) { PyErr_SetString(SpamError, "SDF exceeds body capacity"); return NULL; } pylist = PyTuple_New(numBodies); if (numBodies > 0 && numBodies <= MAX_SDF_BODIES) { for (i = 0; i < numBodies; i++) { PyTuple_SetItem(pylist, i, PyInt_FromLong(bodyIndicesOut[i])); } } return pylist; } static PyObject* pybullet_setPhysicsEngineParameter(PyObject* self, PyObject* args, PyObject *keywds) { double fixedTimeStep = -1; int numSolverIterations = -1; int useSplitImpulse = -1; double splitImpulsePenetrationThreshold = -1; int numSubSteps = -1; int collisionFilterMode = -1; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "fixedTimeStep", "numSolverIterations","useSplitImpulse","splitImpulsePenetrationThreshold", "numSubSteps","collisionFilterMode", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "|diidiii", kwlist,&fixedTimeStep,&numSolverIterations,&useSplitImpulse,&splitImpulsePenetrationThreshold,&numSubSteps, &collisionFilterMode, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3SharedMemoryCommandHandle command = b3InitPhysicsParamCommand(sm); b3SharedMemoryStatusHandle statusHandle; if (numSolverIterations >= 0) { b3PhysicsParamSetNumSolverIterations(command, numSolverIterations); } if (collisionFilterMode>=0) { b3PhysicsParamSetCollisionFilterMode(command, collisionFilterMode); } if (numSubSteps >= 0) { b3PhysicsParamSetNumSubSteps(command, numSubSteps); } if (fixedTimeStep >= 0) { b3PhysicsParamSetTimeStep(command, fixedTimeStep); } if (useSplitImpulse >= 0) { b3PhysicsParamSetUseSplitImpulse(command,useSplitImpulse); } if (splitImpulsePenetrationThreshold >= 0) { b3PhysicsParamSetSplitImpulsePenetrationThreshold(command, splitImpulsePenetrationThreshold); } //ret = b3PhysicsParamSetRealTimeSimulation(command, enableRealTimeSimulation); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); } #if 0 b3SharedMemoryCommandHandle b3InitPhysicsParamCommand(b3PhysicsClientHandle physClient); int b3PhysicsParamSetGravity(b3SharedMemoryCommandHandle commandHandle, double gravx, double gravy, double gravz); int b3PhysicsParamSetTimeStep(b3SharedMemoryCommandHandle commandHandle, double timeStep); int b3PhysicsParamSetDefaultContactERP(b3SharedMemoryCommandHandle commandHandle, double defaultContactERP); int b3PhysicsParamSetNumSubSteps(b3SharedMemoryCommandHandle commandHandle, int numSubSteps); int b3PhysicsParamSetRealTimeSimulation(b3SharedMemoryCommandHandle commandHandle, int enableRealTimeSimulation); int b3PhysicsParamSetNumSolverIterations(b3SharedMemoryCommandHandle commandHandle, int numSolverIterations); #endif Py_INCREF(Py_None); return Py_None; } // Load a robot from a URDF file (universal robot description format) // function can be called without arguments and will default // to position (0,0,1) with orientation(0,0,0,1) // els(x,y,z) or // loadURDF(pos_x, pos_y, pos_z, orn_x, orn_y, orn_z, orn_w) static PyObject* pybullet_loadURDF(PyObject* self, PyObject* args, PyObject *keywds) { int physicsClientId = 0; static char *kwlist[] = { "fileName", "basePosition", "baseOrientation", "useMaximalCoordinates","useFixedBase","physicsClientId", NULL }; static char *kwlistBackwardCompatible4[] = { "fileName", "startPosX", "startPosY", "startPosZ", NULL }; static char *kwlistBackwardCompatible8[] = { "fileName", "startPosX", "startPosY", "startPosZ", "startOrnX", "startOrnY","startOrnZ","startOrnW", NULL }; int bodyIndex = -1; const char* urdfFileName = ""; double startPosX = 0.0; double startPosY = 0.0; double startPosZ = 0.0; double startOrnX = 0.0; double startOrnY = 0.0; double startOrnZ = 0.0; double startOrnW = 1.0; int useMaximalCoordinates = 0; int useFixedBase = 0; int backwardsCompatibilityArgs = 0; b3PhysicsClientHandle sm=0; if (PyArg_ParseTupleAndKeywords(args, keywds, "sddd", kwlistBackwardCompatible4, &urdfFileName, &startPosX, &startPosY, &startPosZ)) { backwardsCompatibilityArgs = 1; } else { PyErr_Clear(); } if (PyArg_ParseTupleAndKeywords(args, keywds, "sddddddd", kwlistBackwardCompatible8,&urdfFileName, &startPosX, &startPosY, &startPosZ, &startOrnX, &startOrnY,&startOrnZ, &startOrnW)) { backwardsCompatibilityArgs = 1; } else { PyErr_Clear(); } if (!backwardsCompatibilityArgs) { PyObject* basePosObj = 0; PyObject* baseOrnObj = 0; double basePos[3]; double baseOrn[4]; if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|OOiii", kwlist, &urdfFileName, &basePosObj, &baseOrnObj, &useMaximalCoordinates,&useFixedBase,&physicsClientId)) { return NULL; } else { if (basePosObj) { if (!pybullet_internalSetVectord(basePosObj, basePos)) { PyErr_SetString(SpamError, "Cannot convert basePosition."); return NULL; } startPosX = basePos[0]; startPosY = basePos[1]; startPosZ = basePos[2]; } if (baseOrnObj) { if (!pybullet_internalSetVector4d(baseOrnObj, baseOrn)) { PyErr_SetString(SpamError, "Cannot convert baseOrientation."); return NULL; } startOrnX = baseOrn[0]; startOrnY = baseOrn[1]; startOrnZ = baseOrn[2]; startOrnW = baseOrn[3]; } } } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } if (strlen(urdfFileName)) { // printf("(%f, %f, %f) (%f, %f, %f, %f)\n", // startPosX,startPosY,startPosZ,startOrnX, startOrnY,startOrnZ, startOrnW); b3SharedMemoryStatusHandle statusHandle; int statusType; b3SharedMemoryCommandHandle command = b3LoadUrdfCommandInit(sm, urdfFileName); // setting the initial position, orientation and other arguments are // optional b3LoadUrdfCommandSetStartPosition(command, startPosX, startPosY, startPosZ); b3LoadUrdfCommandSetStartOrientation(command, startOrnX, startOrnY, startOrnZ, startOrnW); if (useMaximalCoordinates) { b3LoadUrdfCommandSetUseMultiBody(command, 0); } if (useFixedBase) { b3LoadUrdfCommandSetUseFixedBase(command, 1); } statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); statusType = b3GetStatusType(statusHandle); if (statusType != CMD_URDF_LOADING_COMPLETED) { PyErr_SetString(SpamError, "Cannot load URDF file."); return NULL; } bodyIndex = b3GetStatusBodyIndex(statusHandle); } else { PyErr_SetString(SpamError, "Empty filename, method expects 1, 4 or 8 arguments."); return NULL; } return PyLong_FromLong(bodyIndex); } static PyObject* pybullet_loadSDF(PyObject* self, PyObject* args, PyObject *keywds) { const char* sdfFileName = ""; int numBodies = 0; int i; int bodyIndicesOut[MAX_SDF_BODIES]; PyObject* pylist = 0; b3SharedMemoryStatusHandle statusHandle; int statusType; b3SharedMemoryCommandHandle commandHandle; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "sdfFileName","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|i", kwlist, &sdfFileName,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } commandHandle = b3LoadSdfCommandInit(sm, sdfFileName); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); if (statusType != CMD_SDF_LOADING_COMPLETED) { PyErr_SetString(SpamError, "Cannot load SDF file."); return NULL; } numBodies = b3GetStatusBodyIndices(statusHandle, bodyIndicesOut, MAX_SDF_BODIES); if (numBodies > MAX_SDF_BODIES) { PyErr_SetString(SpamError, "SDF exceeds body capacity"); return NULL; } pylist = PyTuple_New(numBodies); if (numBodies > 0 && numBodies <= MAX_SDF_BODIES) { for (i = 0; i < numBodies; i++) { PyTuple_SetItem(pylist, i, PyInt_FromLong(bodyIndicesOut[i])); } } return pylist; } // Reset the simulation to remove all loaded objects static PyObject* pybullet_resetSimulation(PyObject* self, PyObject* args, PyObject* keywds) { int physicsClientId = 0; static char *kwlist[] = { "physicsClientId", NULL }; b3PhysicsClientHandle sm = 0; if (!PyArg_ParseTupleAndKeywords(args, keywds, "|i", kwlist,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3SharedMemoryStatusHandle statusHandle; statusHandle = b3SubmitClientCommandAndWaitStatus( sm, b3InitResetSimulationCommand(sm)); } Py_INCREF(Py_None); return Py_None; } //this method is obsolete, use pybullet_setJointMotorControl2 instead static PyObject* pybullet_setJointMotorControl(PyObject* self, PyObject* args) { int size; int bodyIndex, jointIndex, controlMode; double targetPosition = 0.0; double targetVelocity = 0.0; double maxForce = 100000.0; double appliedForce = 0.0; double kp = 0.1; double kd = 1.0; int valid = 0; int physicsClientId = 0; b3PhysicsClientHandle sm; sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } size = PySequence_Size(args); if (size == 4) { double targetValue = 0.0; // see switch statement below for convertsions dependent on controlMode if (!PyArg_ParseTuple(args, "iiid", &bodyIndex, &jointIndex, &controlMode, &targetValue)) { PyErr_SetString(SpamError, "Error parsing arguments"); return NULL; } valid = 1; switch (controlMode) { case CONTROL_MODE_POSITION_VELOCITY_PD: { targetPosition = targetValue; break; } case CONTROL_MODE_VELOCITY: { targetVelocity = targetValue; break; } case CONTROL_MODE_TORQUE: { appliedForce = targetValue; break; } default: { valid = 0; } } } if (size == 5) { double targetValue = 0.0; // See switch statement for conversions if (!PyArg_ParseTuple(args, "iiidd", &bodyIndex, &jointIndex, &controlMode, &targetValue, &maxForce)) { PyErr_SetString(SpamError, "Error parsing arguments"); return NULL; } valid = 1; switch (controlMode) { case CONTROL_MODE_POSITION_VELOCITY_PD: { targetPosition = targetValue; break; } case CONTROL_MODE_VELOCITY: { targetVelocity = targetValue; break; } case CONTROL_MODE_TORQUE: { valid = 0; break; } default: { valid = 0; } } } if (size == 6) { double gain = 0.0; double targetValue = 0.0; if (!PyArg_ParseTuple(args, "iiiddd", &bodyIndex, &jointIndex, &controlMode, &targetValue, &maxForce, &gain)) { PyErr_SetString(SpamError, "Error parsing arguments"); return NULL; } valid = 1; switch (controlMode) { case CONTROL_MODE_POSITION_VELOCITY_PD: { targetPosition = targetValue; kp = gain; break; } case CONTROL_MODE_VELOCITY: { targetVelocity = targetValue; kd = gain; break; } case CONTROL_MODE_TORQUE: { valid = 0; break; } default: { valid = 0; } } } if (size == 8) { // only applicable for CONTROL_MODE_POSITION_VELOCITY_PD. if (!PyArg_ParseTuple(args, "iiiddddd", &bodyIndex, &jointIndex, &controlMode, &targetPosition, &targetVelocity, &maxForce, &kp, &kd)) { PyErr_SetString(SpamError, "Error parsing arguments"); return NULL; } valid = 1; } if (valid) { int numJoints; b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; struct b3JointInfo info; numJoints = b3GetNumJoints(sm, bodyIndex); if ((jointIndex >= numJoints) || (jointIndex < 0)) { PyErr_SetString(SpamError, "Joint index out-of-range."); return NULL; } if ((controlMode != CONTROL_MODE_VELOCITY) && (controlMode != CONTROL_MODE_TORQUE) && (controlMode != CONTROL_MODE_POSITION_VELOCITY_PD)) { PyErr_SetString(SpamError, "Illegral control mode."); return NULL; } commandHandle = b3JointControlCommandInit2(sm, bodyIndex, controlMode); b3GetJointInfo(sm, bodyIndex, jointIndex, &info); switch (controlMode) { case CONTROL_MODE_VELOCITY: { b3JointControlSetDesiredVelocity(commandHandle, info.m_uIndex, targetVelocity); b3JointControlSetKd(commandHandle, info.m_uIndex, kd); b3JointControlSetMaximumForce(commandHandle, info.m_uIndex, maxForce); break; } case CONTROL_MODE_TORQUE: { b3JointControlSetDesiredForceTorque(commandHandle, info.m_uIndex, appliedForce); break; } case CONTROL_MODE_POSITION_VELOCITY_PD: { b3JointControlSetDesiredPosition(commandHandle, info.m_qIndex, targetPosition); b3JointControlSetKp(commandHandle, info.m_uIndex, kp); b3JointControlSetDesiredVelocity(commandHandle, info.m_uIndex, targetVelocity); b3JointControlSetKd(commandHandle, info.m_uIndex, kd); b3JointControlSetMaximumForce(commandHandle, info.m_uIndex, maxForce); break; } default: {} }; statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); Py_INCREF(Py_None); return Py_None; } PyErr_SetString(SpamError, "Error parsing arguments in setJointControl."); return NULL; } static PyObject* pybullet_setJointMotorControl2(PyObject* self, PyObject* args, PyObject* keywds) { int bodyIndex, jointIndex, controlMode; double targetPosition = 0.0; double targetVelocity = 0.0; double force = 100000.0; double kp = 0.1; double kd = 1.0; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bodyIndex", "jointIndex", "controlMode", "targetPosition", "targetVelocity" , "force", "positionGain", "velocityGain", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "iii|dddddi", kwlist,&bodyIndex, &jointIndex, &controlMode, &targetPosition, &targetVelocity,&force, &kp, &kd, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { int numJoints; b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; struct b3JointInfo info; numJoints = b3GetNumJoints(sm, bodyIndex); if ((jointIndex >= numJoints) || (jointIndex < 0)) { PyErr_SetString(SpamError, "Joint index out-of-range."); return NULL; } if ((controlMode != CONTROL_MODE_VELOCITY) && (controlMode != CONTROL_MODE_TORQUE) && (controlMode != CONTROL_MODE_POSITION_VELOCITY_PD)) { PyErr_SetString(SpamError, "Illegral control mode."); return NULL; } commandHandle = b3JointControlCommandInit2(sm, bodyIndex, controlMode); b3GetJointInfo(sm, bodyIndex, jointIndex, &info); switch (controlMode) { case CONTROL_MODE_VELOCITY: { b3JointControlSetDesiredVelocity(commandHandle, info.m_uIndex, targetVelocity); b3JointControlSetKd(commandHandle, info.m_uIndex, kd); b3JointControlSetMaximumForce(commandHandle, info.m_uIndex, force); break; } case CONTROL_MODE_TORQUE: { b3JointControlSetDesiredForceTorque(commandHandle, info.m_uIndex, force); break; } case CONTROL_MODE_POSITION_VELOCITY_PD: { b3JointControlSetDesiredPosition(commandHandle, info.m_qIndex, targetPosition); b3JointControlSetKp(commandHandle, info.m_uIndex, kp); b3JointControlSetDesiredVelocity(commandHandle, info.m_uIndex, targetVelocity); b3JointControlSetKd(commandHandle, info.m_uIndex, kd); b3JointControlSetMaximumForce(commandHandle, info.m_uIndex, force); break; } default: {} }; statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); Py_INCREF(Py_None); return Py_None; } // PyErr_SetString(SpamError, "Error parsing arguments in setJointControl."); // return NULL; } static PyObject* pybullet_setRealTimeSimulation(PyObject* self, PyObject* args, PyObject* keywds) { int enableRealTimeSimulation = 0; int ret; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "enableRealTimeSimulation", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist,&enableRealTimeSimulation, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3SharedMemoryCommandHandle command = b3InitPhysicsParamCommand(sm); b3SharedMemoryStatusHandle statusHandle; ret = b3PhysicsParamSetRealTimeSimulation(command, enableRealTimeSimulation); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); // ASSERT_EQ(b3GetStatusType(statusHandle), CMD_CLIENT_COMMAND_COMPLETED); } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_setInternalSimFlags(PyObject* self, PyObject* args, PyObject* keywds) { int flags = 0; int ret; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "flags", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist,&flags, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3SharedMemoryCommandHandle command = b3InitPhysicsParamCommand(sm); b3SharedMemoryStatusHandle statusHandle; ret = b3PhysicsParamSetInternalSimFlags(command, flags); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); // ASSERT_EQ(b3GetStatusType(statusHandle), CMD_CLIENT_COMMAND_COMPLETED); } Py_INCREF(Py_None); return Py_None; } // Set the gravity of the world with (x, y, z) arguments static PyObject* pybullet_setGravity(PyObject* self, PyObject* args, PyObject* keywds) { { double gravX = 0.0; double gravY = 0.0; double gravZ = -10.0; int ret; b3PhysicsClientHandle sm = 0; b3SharedMemoryCommandHandle command; b3SharedMemoryStatusHandle statusHandle; int physicsClientId = 0; static char *kwlist[] = { "gravX", "gravY", "gravZ", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "ddd|i", kwlist,&gravX, &gravY, &gravZ, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } command = b3InitPhysicsParamCommand(sm); ret = b3PhysicsParamSetGravity(command, gravX, gravY, gravZ); // ret = b3PhysicsParamSetTimeStep(command, timeStep); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); // ASSERT_EQ(b3GetStatusType(statusHandle), CMD_CLIENT_COMMAND_COMPLETED); } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_setTimeStep(PyObject* self, PyObject* args, PyObject* keywds) { double timeStep = 0.001; int ret; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "timeStep", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "d|i", kwlist,&timeStep, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3SharedMemoryCommandHandle command = b3InitPhysicsParamCommand(sm); b3SharedMemoryStatusHandle statusHandle; ret = b3PhysicsParamSetTimeStep(command, timeStep); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); Py_INCREF(Py_None); return Py_None; } } static PyObject * pybullet_setDefaultContactERP(PyObject* self, PyObject* args,PyObject* keywds) { double defaultContactERP=0.005; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "defaultContactERP", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "d|i", kwlist,&defaultContactERP, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { int ret; b3SharedMemoryStatusHandle statusHandle; b3SharedMemoryCommandHandle command = b3InitPhysicsParamCommand(sm); ret = b3PhysicsParamSetDefaultContactERP(command, defaultContactERP); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); } Py_INCREF(Py_None); return Py_None; } static int pybullet_internalGetBaseVelocity( int bodyIndex, double baseLinearVelocity[3], double baseAngularVelocity[3],b3PhysicsClientHandle sm) { baseLinearVelocity[0] = 0.; baseLinearVelocity[1] = 0.; baseLinearVelocity[2] = 0.; baseAngularVelocity[0] = 0.; baseAngularVelocity[1] = 0.; baseAngularVelocity[2] = 0.; if (0 == sm) { PyErr_SetString(SpamError, "Not connected to physics server."); return 0; } { { b3SharedMemoryCommandHandle cmd_handle = b3RequestActualStateCommandInit(sm, bodyIndex); b3SharedMemoryStatusHandle status_handle = b3SubmitClientCommandAndWaitStatus(sm, cmd_handle); const int status_type = b3GetStatusType(status_handle); const double* actualStateQdot; // const double* jointReactionForces[]; if (status_type != CMD_ACTUAL_STATE_UPDATE_COMPLETED) { PyErr_SetString(SpamError, "getBaseVelocity failed."); return 0; } b3GetStatusActualState( status_handle, 0 /* body_unique_id */, 0 /* num_degree_of_freedom_q */, 0 /* num_degree_of_freedom_u */, 0 /*root_local_inertial_frame*/, 0, &actualStateQdot, 0 /* joint_reaction_forces */); // printf("joint reaction forces="); // for (i=0; i < (sizeof(jointReactionForces)/sizeof(double)); i++) { // printf("%f ", jointReactionForces[i]); // } // now, position x,y,z = actualStateQ[0],actualStateQ[1],actualStateQ[2] // and orientation x,y,z,w = // actualStateQ[3],actualStateQ[4],actualStateQ[5],actualStateQ[6] baseLinearVelocity[0] = actualStateQdot[0]; baseLinearVelocity[1] = actualStateQdot[1]; baseLinearVelocity[2] = actualStateQdot[2]; baseAngularVelocity[0] = actualStateQdot[3]; baseAngularVelocity[1] = actualStateQdot[4]; baseAngularVelocity[2] = actualStateQdot[5]; } } return 1; } // Internal function used to get the base position and orientation // Orientation is returned in quaternions static int pybullet_internalGetBasePositionAndOrientation( int bodyIndex, double basePosition[3], double baseOrientation[4],b3PhysicsClientHandle sm) { basePosition[0] = 0.; basePosition[1] = 0.; basePosition[2] = 0.; baseOrientation[0] = 0.; baseOrientation[1] = 0.; baseOrientation[2] = 0.; baseOrientation[3] = 1.; if (0 == sm) { PyErr_SetString(SpamError, "Not connected to physics server."); return 0; } { { b3SharedMemoryCommandHandle cmd_handle = b3RequestActualStateCommandInit(sm, bodyIndex); b3SharedMemoryStatusHandle status_handle = b3SubmitClientCommandAndWaitStatus(sm, cmd_handle); const int status_type = b3GetStatusType(status_handle); const double* actualStateQ; // const double* jointReactionForces[]; if (status_type != CMD_ACTUAL_STATE_UPDATE_COMPLETED) { PyErr_SetString(SpamError, "getBasePositionAndOrientation failed."); return 0; } b3GetStatusActualState( status_handle, 0 /* body_unique_id */, 0 /* num_degree_of_freedom_q */, 0 /* num_degree_of_freedom_u */, 0 /*root_local_inertial_frame*/, &actualStateQ, 0 /* actual_state_q_dot */, 0 /* joint_reaction_forces */); // printf("joint reaction forces="); // for (i=0; i < (sizeof(jointReactionForces)/sizeof(double)); i++) { // printf("%f ", jointReactionForces[i]); // } // now, position x,y,z = actualStateQ[0],actualStateQ[1],actualStateQ[2] // and orientation x,y,z,w = // actualStateQ[3],actualStateQ[4],actualStateQ[5],actualStateQ[6] basePosition[0] = actualStateQ[0]; basePosition[1] = actualStateQ[1]; basePosition[2] = actualStateQ[2]; baseOrientation[0] = actualStateQ[3]; baseOrientation[1] = actualStateQ[4]; baseOrientation[2] = actualStateQ[5]; baseOrientation[3] = actualStateQ[6]; } } return 1; } // Get the positions (x,y,z) and orientation (x,y,z,w) in quaternion // values for the base link of your object // Object is retrieved based on body index, which is the order // the object was loaded into the simulation (0-based) static PyObject* pybullet_getBasePositionAndOrientation(PyObject* self, PyObject* args, PyObject* keywds) { int bodyUniqueId = -1; double basePosition[3]; double baseOrientation[4]; PyObject* pylistPos; PyObject* pylistOrientation; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bodyUniqueId", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist,&bodyUniqueId, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } if (0 == pybullet_internalGetBasePositionAndOrientation( bodyUniqueId, basePosition, baseOrientation,sm)) { PyErr_SetString(SpamError, "GetBasePositionAndOrientation failed."); return NULL; } { PyObject* item; int i; int num = 3; pylistPos = PyTuple_New(num); for (i = 0; i < num; i++) { item = PyFloat_FromDouble(basePosition[i]); PyTuple_SetItem(pylistPos, i, item); } } { PyObject* item; int i; int num = 4; pylistOrientation = PyTuple_New(num); for (i = 0; i < num; i++) { item = PyFloat_FromDouble(baseOrientation[i]); PyTuple_SetItem(pylistOrientation, i, item); } } { PyObject* pylist; pylist = PyTuple_New(2); PyTuple_SetItem(pylist, 0, pylistPos); PyTuple_SetItem(pylist, 1, pylistOrientation); return pylist; } } static PyObject* pybullet_getBaseVelocity(PyObject* self, PyObject* args, PyObject* keywds) { int bodyUniqueId = -1; double baseLinearVelocity[3]; double baseAngularVelocity[3]; PyObject* pylistLinVel=0; PyObject* pylistAngVel=0; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "bodyUniqueId", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist,&bodyUniqueId, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } if (0 == pybullet_internalGetBaseVelocity( bodyUniqueId, baseLinearVelocity, baseAngularVelocity,sm)) { PyErr_SetString(SpamError, "getBaseVelocity failed."); return NULL; } { PyObject* item; int i; int num = 3; pylistLinVel = PyTuple_New(num); for (i = 0; i < num; i++) { item = PyFloat_FromDouble(baseLinearVelocity[i]); PyTuple_SetItem(pylistLinVel, i, item); } } { PyObject* item; int i; int num = 3; pylistAngVel = PyTuple_New(num); for (i = 0; i < num; i++) { item = PyFloat_FromDouble(baseAngularVelocity[i]); PyTuple_SetItem(pylistAngVel, i, item); } } { PyObject* pylist; pylist = PyTuple_New(2); PyTuple_SetItem(pylist, 0, pylistLinVel); PyTuple_SetItem(pylist, 1, pylistAngVel); return pylist; } } static PyObject* pybullet_getNumBodies(PyObject* self, PyObject* args, PyObject* keywds) { int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "|i", kwlist,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { int numBodies = b3GetNumBodies(sm); #if PY_MAJOR_VERSION >= 3 return PyLong_FromLong(numBodies); #else return PyInt_FromLong(numBodies); #endif } } static PyObject* pybullet_getBodyUniqueId(PyObject* self, PyObject* args, PyObject* keywds) { int physicsClientId = 0; int serialIndex=-1; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "serialIndex", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist,&serialIndex, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { int bodyUniqueId = -1; bodyUniqueId = b3GetBodyUniqueId(sm, serialIndex); #if PY_MAJOR_VERSION >= 3 return PyLong_FromLong(bodyUniqueId); #else return PyInt_FromLong(bodyUniqueId); #endif } } static PyObject* pybullet_getBodyInfo(PyObject* self, PyObject* args, PyObject* keywds) { { int bodyUniqueId= -1; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bodyUniqueId", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist,&bodyUniqueId, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { struct b3BodyInfo info; if (b3GetBodyInfo(sm,bodyUniqueId,&info)) { PyObject* pyListJointInfo = PyTuple_New(1); PyTuple_SetItem(pyListJointInfo, 0, PyString_FromString(info.m_baseName)); return pyListJointInfo; } else { PyErr_SetString(SpamError, "Couldn't get body info"); return NULL; } } } PyErr_SetString(SpamError, "error in getBodyInfo."); return NULL; } // Return the number of joints in an object based on // body index; body index is based on order of sequence // the object is loaded into simulation static PyObject* pybullet_getNumJoints(PyObject* self, PyObject* args, PyObject* keywds) { int bodyUniqueId = -1; int numJoints = 0; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "bodyUniqueId", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist,&bodyUniqueId, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } numJoints = b3GetNumJoints(sm, bodyUniqueId); #if PY_MAJOR_VERSION >= 3 return PyLong_FromLong(numJoints); #else return PyInt_FromLong(numJoints); #endif } // Initalize all joint positions given a list of values static PyObject* pybullet_resetJointState(PyObject* self, PyObject* args, PyObject* keywds) { { int bodyUniqueId; int jointIndex; double targetValue; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bodyUniqueId", "jointIndex", "targetValue","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "iid|i", kwlist,&bodyUniqueId, &jointIndex, &targetValue, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; int numJoints; numJoints = b3GetNumJoints(sm, bodyUniqueId); if ((jointIndex >= numJoints) || (jointIndex < 0)) { PyErr_SetString(SpamError, "Joint index out-of-range."); return NULL; } commandHandle = b3CreatePoseCommandInit(sm, bodyUniqueId); b3CreatePoseCommandSetJointPosition(sm, commandHandle, jointIndex, targetValue); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); Py_INCREF(Py_None); return Py_None; } } PyErr_SetString(SpamError, "error in resetJointState."); return NULL; } static PyObject* pybullet_resetBaseVelocity(PyObject* self, PyObject* args, PyObject *keywds) { static char *kwlist[] = { "objectUniqueId", "linearVelocity", "angularVelocity","physicsClientId", NULL }; { int bodyIndex=0; PyObject* linVelObj=0; PyObject* angVelObj=0; double linVel[3] = { 0, 0, 0 }; double angVel[3] = { 0, 0, 0 }; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|OOi", kwlist, &bodyIndex, &linVelObj, &angVelObj,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } if (linVelObj || angVelObj) { b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; commandHandle = b3CreatePoseCommandInit(sm, bodyIndex); if (linVelObj) { pybullet_internalSetVectord(linVelObj, linVel); b3CreatePoseCommandSetBaseLinearVelocity(commandHandle, linVel); } if (angVelObj) { pybullet_internalSetVectord(angVelObj, angVel); b3CreatePoseCommandSetBaseAngularVelocity(commandHandle, angVel); } statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); Py_INCREF(Py_None); return Py_None; } else { PyErr_SetString(SpamError, "expected at least linearVelocity and/or angularVelocity."); return NULL; } } PyErr_SetString(SpamError, "error in resetJointState."); return NULL; } // Reset the position and orientation of the base/root link, position [x,y,z] // and orientation quaternion [x,y,z,w] static PyObject* pybullet_resetBasePositionAndOrientation(PyObject* self, PyObject* args, PyObject* keywds) { { int bodyUniqueId; PyObject* posObj; PyObject* ornObj; double pos[3]; double orn[4]; // as a quaternion b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bodyUniqueId", "posObj", "ornObj", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "iOO|i", kwlist,&bodyUniqueId, &posObj, &ornObj, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; { PyObject* seq; int len, i; seq = PySequence_Fast(posObj, "expected a sequence"); len = PySequence_Size(posObj); if (len == 3) { for (i = 0; i < 3; i++) { pos[i] = pybullet_internalGetFloatFromSequence(seq, i); } } else { PyErr_SetString(SpamError, "position needs a 3 coordinates [x,y,z]."); Py_DECREF(seq); return NULL; } Py_DECREF(seq); } { PyObject* seq; int len, i; seq = PySequence_Fast(ornObj, "expected a sequence"); len = PySequence_Size(ornObj); if (len == 4) { for (i = 0; i < 4; i++) { orn[i] = pybullet_internalGetFloatFromSequence(seq, i); } } else { PyErr_SetString( SpamError, "orientation needs a 4 coordinates, quaternion [x,y,z,w]."); Py_DECREF(seq); return NULL; } Py_DECREF(seq); } commandHandle = b3CreatePoseCommandInit(sm, bodyUniqueId); b3CreatePoseCommandSetBasePosition(commandHandle, pos[0], pos[1], pos[2]); b3CreatePoseCommandSetBaseOrientation(commandHandle, orn[0], orn[1], orn[2], orn[3]); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); Py_INCREF(Py_None); return Py_None; } } PyErr_SetString(SpamError, "error in resetJointState."); return NULL; } // Get the a single joint info for a specific bodyIndex // // Args: // bodyIndex - integer indicating body in simulation // jointIndex - integer indicating joint for a specific body // // Joint information includes: // index, name, type, q-index, u-index, // flags, joint damping, joint friction // // The format of the returned list is // [int, str, int, int, int, int, float, float] // // TODO(hellojas): get joint positions for a body static PyObject* pybullet_getJointInfo(PyObject* self, PyObject* args,PyObject* keywds) { PyObject* pyListJointInfo; struct b3JointInfo info; int bodyUniqueId = -1; int jointIndex = -1; int jointInfoSize = 8; // size of struct b3JointInfo b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bodyUniqueId", "jointIndex", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "ii|i", kwlist,&bodyUniqueId, &jointIndex, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { { // printf("body index = %d, joint index =%d\n", bodyIndex, jointIndex); pyListJointInfo = PyTuple_New(jointInfoSize); if (b3GetJointInfo(sm, bodyUniqueId, jointIndex, &info)) { // printf("Joint%d %s, type %d, at q-index %d and u-index %d\n", // info.m_jointIndex, // info.m_jointName, // info.m_jointType, // info.m_qIndex, // info.m_uIndex); // printf(" flags=%d jointDamping=%f jointFriction=%f\n", // info.m_flags, // info.m_jointDamping, // info.m_jointFriction); PyTuple_SetItem(pyListJointInfo, 0, PyInt_FromLong(info.m_jointIndex)); PyTuple_SetItem(pyListJointInfo, 1, PyString_FromString(info.m_jointName)); PyTuple_SetItem(pyListJointInfo, 2, PyInt_FromLong(info.m_jointType)); PyTuple_SetItem(pyListJointInfo, 3, PyInt_FromLong(info.m_qIndex)); PyTuple_SetItem(pyListJointInfo, 4, PyInt_FromLong(info.m_uIndex)); PyTuple_SetItem(pyListJointInfo, 5, PyInt_FromLong(info.m_flags)); PyTuple_SetItem(pyListJointInfo, 6, PyFloat_FromDouble(info.m_jointDamping)); PyTuple_SetItem(pyListJointInfo, 7, PyFloat_FromDouble(info.m_jointFriction)); return pyListJointInfo; } else { PyErr_SetString(SpamError, "GetJointInfo failed."); return NULL; } } } Py_INCREF(Py_None); return Py_None; } // Returns the state of a specific joint in a given bodyIndex // // Args: // bodyIndex - integer indicating body in simulation // jointIndex - integer indicating joint for a specific body // // The state of a joint includes the following: // position, velocity, force torque (6 values), and motor torque // The returned pylist is an array of [float, float, float[6], float] // TODO(hellojas): check accuracy of position and velocity // TODO(hellojas): check force torque values static PyObject* pybullet_getJointState(PyObject* self, PyObject* args,PyObject* keywds) { PyObject* pyListJointForceTorque; PyObject* pyListJointState; struct b3JointSensorState sensorState; int bodyUniqueId = -1; int jointIndex = -1; int sensorStateSize = 4; // size of struct b3JointSensorState int forceTorqueSize = 6; // size of force torque list from b3JointSensorState int j; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bodyUniqueId", "jointIndex","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "ii|i", kwlist,&bodyUniqueId, &jointIndex, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { { int status_type = 0; b3SharedMemoryCommandHandle cmd_handle; b3SharedMemoryStatusHandle status_handle; if (bodyUniqueId < 0) { PyErr_SetString(SpamError, "getJointState failed; invalid bodyIndex"); return NULL; } if (jointIndex < 0) { PyErr_SetString(SpamError, "getJointState failed; invalid jointIndex"); return NULL; } cmd_handle = b3RequestActualStateCommandInit(sm, bodyUniqueId); status_handle = b3SubmitClientCommandAndWaitStatus(sm, cmd_handle); status_type = b3GetStatusType(status_handle); if (status_type != CMD_ACTUAL_STATE_UPDATE_COMPLETED) { PyErr_SetString(SpamError, "getJointState failed."); return NULL; } pyListJointState = PyTuple_New(sensorStateSize); pyListJointForceTorque = PyTuple_New(forceTorqueSize); b3GetJointState(sm, status_handle, jointIndex, &sensorState); PyTuple_SetItem(pyListJointState, 0, PyFloat_FromDouble(sensorState.m_jointPosition)); PyTuple_SetItem(pyListJointState, 1, PyFloat_FromDouble(sensorState.m_jointVelocity)); for (j = 0; j < forceTorqueSize; j++) { PyTuple_SetItem(pyListJointForceTorque, j, PyFloat_FromDouble(sensorState.m_jointForceTorque[j])); } PyTuple_SetItem(pyListJointState, 2, pyListJointForceTorque); PyTuple_SetItem(pyListJointState, 3, PyFloat_FromDouble(sensorState.m_jointMotorTorque)); return pyListJointState; } } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_getLinkState(PyObject* self, PyObject* args,PyObject* keywds) { PyObject* pyLinkState; PyObject* pyLinkStateWorldPosition; PyObject* pyLinkStateWorldOrientation; PyObject* pyLinkStateLocalInertialPosition; PyObject* pyLinkStateLocalInertialOrientation; PyObject* pyLinkStateWorldLinkFramePosition; PyObject* pyLinkStateWorldLinkFrameOrientation; struct b3LinkState linkState; int bodyUniqueId = -1; int linkIndex = -1; int i; b3PhysicsClientHandle sm = 0; int physicsClientId = 0; static char *kwlist[] = { "bodyUniqueId", "linkIndex", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "ii|i", kwlist, &bodyUniqueId, &linkIndex, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { { int status_type = 0; b3SharedMemoryCommandHandle cmd_handle; b3SharedMemoryStatusHandle status_handle; if (bodyUniqueId < 0) { PyErr_SetString(SpamError, "getLinkState failed; invalid bodyIndex"); return NULL; } if (linkIndex < 0) { PyErr_SetString(SpamError, "getLinkState failed; invalid jointIndex"); return NULL; } cmd_handle = b3RequestActualStateCommandInit(sm, bodyUniqueId); status_handle = b3SubmitClientCommandAndWaitStatus(sm, cmd_handle); status_type = b3GetStatusType(status_handle); if (status_type != CMD_ACTUAL_STATE_UPDATE_COMPLETED) { PyErr_SetString(SpamError, "getLinkState failed."); return NULL; } b3GetLinkState(sm, status_handle, linkIndex, &linkState); pyLinkStateWorldPosition = PyTuple_New(3); for (i = 0; i < 3; ++i) { PyTuple_SetItem(pyLinkStateWorldPosition, i, PyFloat_FromDouble(linkState.m_worldPosition[i])); } pyLinkStateWorldOrientation = PyTuple_New(4); for (i = 0; i < 4; ++i) { PyTuple_SetItem(pyLinkStateWorldOrientation, i, PyFloat_FromDouble(linkState.m_worldOrientation[i])); } pyLinkStateLocalInertialPosition = PyTuple_New(3); for (i = 0; i < 3; ++i) { PyTuple_SetItem(pyLinkStateLocalInertialPosition, i, PyFloat_FromDouble(linkState.m_localInertialPosition[i])); } pyLinkStateLocalInertialOrientation = PyTuple_New(4); for (i = 0; i < 4; ++i) { PyTuple_SetItem(pyLinkStateLocalInertialOrientation, i, PyFloat_FromDouble(linkState.m_localInertialOrientation[i])); } pyLinkStateWorldLinkFramePosition = PyTuple_New(3); for (i = 0; i < 3; ++i) { PyTuple_SetItem(pyLinkStateWorldLinkFramePosition , i, PyFloat_FromDouble(linkState.m_worldLinkFramePosition[i])); } pyLinkStateWorldLinkFrameOrientation = PyTuple_New(4); for (i = 0; i < 4; ++i) { PyTuple_SetItem(pyLinkStateWorldLinkFrameOrientation, i, PyFloat_FromDouble(linkState.m_worldLinkFrameOrientation[i])); } pyLinkState = PyTuple_New(6); PyTuple_SetItem(pyLinkState, 0, pyLinkStateWorldPosition); PyTuple_SetItem(pyLinkState, 1, pyLinkStateWorldOrientation); PyTuple_SetItem(pyLinkState, 2, pyLinkStateLocalInertialPosition); PyTuple_SetItem(pyLinkState, 3, pyLinkStateLocalInertialOrientation); PyTuple_SetItem(pyLinkState, 4, pyLinkStateWorldLinkFramePosition ); PyTuple_SetItem(pyLinkState, 5, pyLinkStateWorldLinkFrameOrientation); return pyLinkState; } } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_addUserDebugText(PyObject* self, PyObject* args, PyObject *keywds) { b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; int statusType; int res = 0; char* text; double posXYZ[3]; double colorRGB[3]={1,1,1}; PyObject* textPositionObj=0; PyObject* textColorRGBObj=0; double textSize = 1.f; double lifeTime = 0.f; int physicsClientId = 0; b3PhysicsClientHandle sm=0; static char *kwlist[] = { "text", "textPosition", "textColorRGB", "textSize", "lifeTime","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "sO|Oddi", kwlist, &text, &textPositionObj, &textColorRGBObj,&textSize, &lifeTime,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } res = pybullet_internalSetVectord(textPositionObj,posXYZ); if (!res) { PyErr_SetString(SpamError, "Error converting textPositionObj[3]"); return NULL; } if (textColorRGBObj) { res = pybullet_internalSetVectord(textColorRGBObj,colorRGB); if (!res) { PyErr_SetString(SpamError, "Error converting textColorRGBObj[3]"); return NULL; } } commandHandle = b3InitUserDebugDrawAddText3D(sm,text,posXYZ,colorRGB,textSize,lifeTime); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); if (statusType == CMD_USER_DEBUG_DRAW_COMPLETED) { int debugItemUniqueId = b3GetDebugItemUniqueId(statusHandle); PyObject* item = PyInt_FromLong(debugItemUniqueId); return item; } PyErr_SetString(SpamError, "Error in addUserDebugText."); return NULL; } static PyObject* pybullet_addUserDebugLine(PyObject* self, PyObject* args, PyObject *keywds) { b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; int statusType; int res = 0; double fromXYZ[3]; double toXYZ[3]; double colorRGB[3]={1,1,1}; PyObject* lineFromObj=0; PyObject* lineToObj=0; PyObject* lineColorRGBObj=0; double lineWidth = 1.f; double lifeTime = 0.f; int physicsClientId = 0; b3PhysicsClientHandle sm=0; static char *kwlist[] = { "lineFromXYZ", "lineToXYZ", "lineColorRGB", "lineWidth", "lifeTime","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "OO|Oddi", kwlist, &lineFromObj, &lineToObj, &lineColorRGBObj,&lineWidth, &lifeTime,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } res = pybullet_internalSetVectord(lineFromObj,fromXYZ); if (!res) { PyErr_SetString(SpamError, "Error converting lineFrom[3]"); return NULL; } res = pybullet_internalSetVectord(lineToObj,toXYZ); if (!res) { PyErr_SetString(SpamError, "Error converting lineTo[3]"); return NULL; } if (lineColorRGBObj) { res = pybullet_internalSetVectord(lineColorRGBObj,colorRGB); } commandHandle = b3InitUserDebugDrawAddLine3D(sm,fromXYZ,toXYZ,colorRGB,lineWidth,lifeTime); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); if (statusType == CMD_USER_DEBUG_DRAW_COMPLETED) { int debugItemUniqueId = b3GetDebugItemUniqueId(statusHandle); PyObject* item = PyInt_FromLong(debugItemUniqueId); return item; } PyErr_SetString(SpamError, "Error in addUserDebugLine."); return NULL; } static PyObject* pybullet_removeUserDebugItem(PyObject* self, PyObject* args, PyObject *keywds) { b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; int statusType; int itemUniqueId; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "itemUniqueId", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist,&itemUniqueId, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } commandHandle = b3InitUserDebugDrawRemove(sm,itemUniqueId); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_removeAllUserDebugItems(PyObject* self, PyObject* args, PyObject *keywds) { b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; int statusType; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "|i", kwlist,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } commandHandle = b3InitUserDebugDrawRemoveAll(sm); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_rayTest(PyObject* self, PyObject* args, PyObject *keywds) { b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; int statusType; PyObject* rayFromObj=0; PyObject* rayToObj=0; double from[3]; double to[3]; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "rayFromPosition", "rayToPosition", "physicsClientId", NULL }; int physicsClientId = 0; if (!PyArg_ParseTupleAndKeywords(args, keywds, "OO|i", kwlist, &rayFromObj, &rayToObj,&physicsClientId)) return NULL; sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } pybullet_internalSetVectord(rayFromObj,from); pybullet_internalSetVectord(rayToObj,to); commandHandle = b3CreateRaycastCommandInit(sm, from[0],from[1],from[2], to[0],to[1],to[2]); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); if (statusType==CMD_REQUEST_RAY_CAST_INTERSECTIONS_COMPLETED) { struct b3RaycastInformation raycastInfo; PyObject* rayHitsObj = 0; int i; b3GetRaycastInformation(sm, &raycastInfo); rayHitsObj = PyTuple_New(raycastInfo.m_numRayHits); for (i=0;i=-1) { b3SetVRCameraTrackingObject(commandHandle,trackObjectUid); } statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_getVREvents(PyObject* self, PyObject* args, PyObject *keywds) { b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; int statusType; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "|i", kwlist,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } commandHandle = b3RequestVREventsCommandInit(sm); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); if (statusType==CMD_REQUEST_VR_EVENTS_DATA_COMPLETED) { struct b3VREventsData vrEvents; PyObject* vrEventsObj; int i=0; b3GetVREventsData(sm,&vrEvents); vrEventsObj = PyTuple_New(vrEvents.m_numControllerEvents); for (i=0;im_numContactPoints); for (i = 0; i < contactPointPtr->m_numContactPoints; i++) { PyObject* contactObList = PyTuple_New(10); // see above 10 fields PyObject* item; item = PyInt_FromLong(contactPointPtr->m_contactPointData[i].m_contactFlags); PyTuple_SetItem(contactObList, 0, item); item = PyInt_FromLong( contactPointPtr->m_contactPointData[i].m_bodyUniqueIdA); PyTuple_SetItem(contactObList, 1, item); item = PyInt_FromLong( contactPointPtr->m_contactPointData[i].m_bodyUniqueIdB); PyTuple_SetItem(contactObList, 2, item); item = PyInt_FromLong(contactPointPtr->m_contactPointData[i].m_linkIndexA); PyTuple_SetItem(contactObList, 3, item); item = PyInt_FromLong(contactPointPtr->m_contactPointData[i].m_linkIndexB); PyTuple_SetItem(contactObList, 4, item); { PyObject* posAObj = PyTuple_New(3); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_positionOnAInWS[0]); PyTuple_SetItem(posAObj, 0, item); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_positionOnAInWS[1]); PyTuple_SetItem(posAObj, 1, item); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_positionOnAInWS[2]); PyTuple_SetItem(posAObj, 2, item); PyTuple_SetItem(contactObList, 5, posAObj); } { PyObject* posBObj = PyTuple_New(3); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_positionOnBInWS[0]); PyTuple_SetItem(posBObj, 0, item); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_positionOnBInWS[1]); PyTuple_SetItem(posBObj, 1, item); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_positionOnBInWS[2]); PyTuple_SetItem(posBObj, 2, item); PyTuple_SetItem(contactObList, 6, posBObj); } { PyObject* normalOnB = PyTuple_New(3); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_contactNormalOnBInWS[0]); PyTuple_SetItem(normalOnB, 0, item); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_contactNormalOnBInWS[1]); PyTuple_SetItem(normalOnB, 1, item); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_contactNormalOnBInWS[2]); PyTuple_SetItem(normalOnB, 2, item); PyTuple_SetItem(contactObList, 7, normalOnB); } item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_contactDistance); PyTuple_SetItem(contactObList, 8, item); item = PyFloat_FromDouble( contactPointPtr->m_contactPointData[i].m_normalForce); PyTuple_SetItem(contactObList, 9, item); PyTuple_SetItem(pyResultList, i, contactObList); } return pyResultList; } static PyObject* pybullet_getOverlappingObjects(PyObject* self, PyObject* args, PyObject *keywds) { PyObject* aabbMinOb=0, *aabbMaxOb=0; double aabbMin[3]; double aabbMax[3]; b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; struct b3AABBOverlapData overlapData; int i; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "aabbMin", "aabbMax", "physicsClientId",NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "OO|i", kwlist, &aabbMinOb, &aabbMaxOb,&physicsClientId)) return NULL; sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } pybullet_internalSetVectord(aabbMinOb, aabbMin); pybullet_internalSetVectord(aabbMaxOb, aabbMax); commandHandle = b3InitAABBOverlapQuery(sm, aabbMin, aabbMax); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); b3GetAABBOverlapResults(sm, &overlapData); if (overlapData.m_numOverlappingObjects) { PyObject* pyResultList = PyTuple_New(overlapData.m_numOverlappingObjects); //For huge amount of overlap, we could use numpy instead (see camera pixel data) //What would Python do with huge amount of data? Pass it onto TensorFlow! for (i = 0; i < overlapData.m_numOverlappingObjects; i++) { PyObject* overlap = PyTuple_New(2);//body unique id and link index PyObject* item; item = PyInt_FromLong(overlapData.m_overlappingObjects[i].m_objectUniqueId); PyTuple_SetItem(overlap, 0, item); item = PyInt_FromLong(overlapData.m_overlappingObjects[i].m_linkIndex); PyTuple_SetItem(overlap, 1, item); PyTuple_SetItem(pyResultList, i, overlap); } return pyResultList; } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_getClosestPointData(PyObject* self, PyObject* args, PyObject *keywds) { int bodyUniqueIdA = -1; int bodyUniqueIdB = -1; int linkIndexA = -2; int linkIndexB = -2; double distanceThreshold = 0.f; b3SharedMemoryCommandHandle commandHandle; struct b3ContactInformation contactPointData; b3SharedMemoryStatusHandle statusHandle; int statusType; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "bodyA", "bodyB", "distance", "linkIndexA","linkIndexB","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "iid|iii", kwlist, &bodyUniqueIdA, &bodyUniqueIdB, &distanceThreshold, &linkIndexA, &linkIndexB,&physicsClientId)) return NULL; sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } commandHandle = b3InitClosestDistanceQuery(sm); b3SetClosestDistanceFilterBodyA(commandHandle, bodyUniqueIdA); b3SetClosestDistanceFilterBodyB(commandHandle, bodyUniqueIdB); b3SetClosestDistanceThreshold(commandHandle, distanceThreshold); if (linkIndexA >= -1) { b3SetClosestDistanceFilterLinkA(commandHandle, linkIndexA); } if (linkIndexB >= -1) { b3SetClosestDistanceFilterLinkB(commandHandle, linkIndexB); } statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); if (statusType == CMD_CONTACT_POINT_INFORMATION_COMPLETED) { b3GetContactPointInformation(sm, &contactPointData); return MyConvertContactPoint(&contactPointData); } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_changeUserConstraint(PyObject* self, PyObject* args, PyObject *keywds) { static char *kwlist[] = { "userConstraintUniqueId","jointChildPivot", "jointChildFrameOrientation","maxForce", "physicsClientId", NULL}; int userConstraintUniqueId=-1; b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; int statusType; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; PyObject* jointChildPivotObj=0; PyObject* jointChildFrameOrnObj=0; double jointChildPivot[3]; double jointChildFrameOrn[4]; double maxForce = -1; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|OOdi", kwlist,&userConstraintUniqueId,&jointChildPivotObj, &jointChildFrameOrnObj,&maxForce, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } commandHandle = b3InitChangeUserConstraintCommand(sm,userConstraintUniqueId); if (pybullet_internalSetVectord(jointChildPivotObj,jointChildPivot)) { b3InitChangeUserConstraintSetPivotInB(commandHandle, jointChildPivot); } if (pybullet_internalSetVector4d(jointChildFrameOrnObj,jointChildFrameOrn)) { b3InitChangeUserConstraintSetFrameInB(commandHandle, jointChildFrameOrn); } if (maxForce>=0) { b3InitChangeUserConstraintSetMaxForce(commandHandle,maxForce); } statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); Py_INCREF(Py_None); return Py_None; }; static PyObject* pybullet_removeUserConstraint(PyObject* self, PyObject* args, PyObject *keywds) { static char *kwlist[] = { "userConstraintUniqueId","physicsClientId", NULL}; int userConstraintUniqueId=-1; b3SharedMemoryCommandHandle commandHandle; b3SharedMemoryStatusHandle statusHandle; int statusType; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist,&userConstraintUniqueId,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } commandHandle = b3InitRemoveUserConstraintCommand(sm,userConstraintUniqueId); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); Py_INCREF(Py_None); return Py_None; }; /* static PyObject* pybullet_updateUserConstraint(PyObject* self, PyObject* args, PyObject *keywds) { return NULL; } */ static PyObject* pybullet_createUserConstraint(PyObject* self, PyObject* args, PyObject *keywds) { b3SharedMemoryCommandHandle commandHandle; int parentBodyUniqueId=-1; int parentLinkIndex=-1; int childBodyUniqueId=-1; int childLinkIndex=-1; int jointType=ePoint2PointType; PyObject* jointAxisObj=0; double jointAxis[3]={0,0,0}; PyObject* parentFramePositionObj = 0; double parentFramePosition[3]={0,0,0}; PyObject* childFramePositionObj = 0; double childFramePosition[3]={0,0,0}; PyObject* parentFrameOrientationObj = 0; double parentFrameOrientation[4]={0,0,0,1}; PyObject* childFrameOrientationObj = 0; double childFrameOrientation[4]={0,0,0,1}; struct b3JointInfo jointInfo; b3SharedMemoryStatusHandle statusHandle; int statusType; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "parentBodyUniqueId", "parentLinkIndex", "childBodyUniqueId", "childLinkIndex", "jointType", "jointAxis", "parentFramePosition", "childFramePosition", "parentFrameOrientation", "childFrameOrientation", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "iiiiiOOO|OOi", kwlist,&parentBodyUniqueId,&parentLinkIndex, &childBodyUniqueId,&childLinkIndex, &jointType,&jointAxisObj, &parentFramePositionObj, &childFramePositionObj, &parentFrameOrientationObj, &childFrameOrientationObj, &physicsClientId )) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } pybullet_internalSetVectord(jointAxisObj,jointAxis); pybullet_internalSetVectord(parentFramePositionObj,parentFramePosition); pybullet_internalSetVectord(childFramePositionObj,childFramePosition); pybullet_internalSetVector4d(parentFrameOrientationObj,parentFrameOrientation); pybullet_internalSetVector4d(childFrameOrientationObj,childFrameOrientation); jointInfo.m_jointType = jointType; jointInfo.m_parentFrame[0] = parentFramePosition[0]; jointInfo.m_parentFrame[1] = parentFramePosition[1]; jointInfo.m_parentFrame[2] = parentFramePosition[2]; jointInfo.m_parentFrame[3] = parentFrameOrientation[0]; jointInfo.m_parentFrame[4] = parentFrameOrientation[1]; jointInfo.m_parentFrame[5] = parentFrameOrientation[2]; jointInfo.m_parentFrame[6] = parentFrameOrientation[3]; jointInfo.m_childFrame[0] = childFramePosition[0]; jointInfo.m_childFrame[1] = childFramePosition[1]; jointInfo.m_childFrame[2] = childFramePosition[2]; jointInfo.m_childFrame[3] = childFrameOrientation[0]; jointInfo.m_childFrame[4] = childFrameOrientation[1]; jointInfo.m_childFrame[5] = childFrameOrientation[2]; jointInfo.m_childFrame[6] = childFrameOrientation[3]; jointInfo.m_jointAxis[0] = jointAxis[0]; jointInfo.m_jointAxis[1] = jointAxis[1]; jointInfo.m_jointAxis[2] = jointAxis[2]; commandHandle = b3InitCreateUserConstraintCommand(sm, parentBodyUniqueId, parentLinkIndex, childBodyUniqueId, childLinkIndex, &jointInfo); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); if (statusType==CMD_USER_CONSTRAINT_COMPLETED) { int userConstraintUid = b3GetStatusUserConstraintUniqueId(statusHandle); PyObject* ob = PyLong_FromLong(userConstraintUid); return ob; } else { PyErr_SetString(SpamError, "createConstraint failed."); return NULL; } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_getContactPointData(PyObject* self, PyObject* args, PyObject *keywds) { int bodyUniqueIdA = -1; int bodyUniqueIdB = -1; b3SharedMemoryCommandHandle commandHandle; struct b3ContactInformation contactPointData; b3SharedMemoryStatusHandle statusHandle; int statusType; static char *kwlist[] = { "bodyA", "bodyB","physicsClientId", NULL }; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iii", kwlist, &bodyUniqueIdA, &bodyUniqueIdB,&physicsClientId)) return NULL; sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } commandHandle = b3InitRequestContactPointInformation(sm); b3SetContactFilterBodyA(commandHandle, bodyUniqueIdA); b3SetContactFilterBodyB(commandHandle, bodyUniqueIdB); //b3SetContactQueryMode(commandHandle, mode); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); if (statusType == CMD_CONTACT_POINT_INFORMATION_COMPLETED) { b3GetContactPointInformation(sm, &contactPointData); return MyConvertContactPoint(&contactPointData); } Py_INCREF(Py_None); return Py_None; } /// Render an image from the current timestep of the simulation, width, height are required, other args are optional // getCameraImage(w, h, view[16], projection[16], lightDir[3], lightColor[3], lightDist, hasShadow, lightAmbientCoeff, lightDiffuseCoeff, lightSpecularCoeff) static PyObject* pybullet_getCameraImage(PyObject* self, PyObject* args, PyObject *keywds) { /// request an image from a simulated camera, using a software renderer. struct b3CameraImageData imageData; PyObject* objViewMat = 0, *objProjMat = 0, *lightDirObj = 0, *lightColorObj = 0; int width, height; float viewMatrix[16]; float projectionMatrix[16]; float lightDir[3]; float lightColor[3]; float lightDist = 10.0; int hasShadow = 0; float lightAmbientCoeff = 0.6; float lightDiffuseCoeff = 0.35; float lightSpecularCoeff = 0.05; // inialize cmd b3SharedMemoryCommandHandle command; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; // set camera resolution, optionally view, projection matrix, light direction, light color, light distance, shadow static char *kwlist[] = { "width", "height", "viewMatrix", "projectionMatrix", "lightDirection", "lightColor", "lightDistance", "shadow", "lightAmbientCoeff", "lightDiffuseCoeff", "lightSpecularCoeff", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "ii|OOOOfifffi", kwlist, &width, &height, &objViewMat, &objProjMat, &lightDirObj, &lightColorObj, &lightDist, &hasShadow, &lightAmbientCoeff, &lightDiffuseCoeff, &lightSpecularCoeff,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } command = b3InitRequestCameraImage(sm); b3RequestCameraImageSetPixelResolution(command, width, height); // set camera matrices only if set matrix function succeeds if (pybullet_internalSetMatrix(objViewMat, viewMatrix) && (pybullet_internalSetMatrix(objProjMat, projectionMatrix))) { b3RequestCameraImageSetCameraMatrices(command, viewMatrix, projectionMatrix); } //set light direction only if function succeeds if (pybullet_internalSetVector(lightDirObj, lightDir)) { b3RequestCameraImageSetLightDirection(command, lightDir); } //set light color only if function succeeds if (pybullet_internalSetVector(lightColorObj, lightColor)) { b3RequestCameraImageSetLightColor(command, lightColor); } b3RequestCameraImageSetLightDistance(command, lightDist); b3RequestCameraImageSetShadow(command, hasShadow); b3RequestCameraImageSetLightAmbientCoeff(command, lightAmbientCoeff); b3RequestCameraImageSetLightDiffuseCoeff(command, lightDiffuseCoeff); b3RequestCameraImageSetLightSpecularCoeff(command, lightSpecularCoeff); if (b3CanSubmitCommand(sm)) { b3SharedMemoryStatusHandle statusHandle; int statusType; // b3RequestCameraImageSelectRenderer(command,ER_BULLET_HARDWARE_OPENGL); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); statusType = b3GetStatusType(statusHandle); if (statusType == CMD_CAMERA_IMAGE_COMPLETED) { PyObject* item2; PyObject* pyResultList; // store 4 elements in this result: width, // height, rgbData, depth #ifdef PYBULLET_USE_NUMPY PyObject* pyRGB; PyObject* pyDep; PyObject* pySeg; int i, j, p; b3GetCameraImageData(sm, &imageData); // TODO(hellojas): error handling if image size is 0 pyResultList = PyTuple_New(5); PyTuple_SetItem(pyResultList, 0, PyInt_FromLong(imageData.m_pixelWidth)); PyTuple_SetItem(pyResultList, 1, PyInt_FromLong(imageData.m_pixelHeight)); int bytesPerPixel = 4; // Red, Green, Blue, and Alpha each 8 bit values npy_intp rgb_dims[3] = { imageData.m_pixelHeight, imageData.m_pixelWidth, bytesPerPixel }; npy_intp dep_dims[2] = { imageData.m_pixelHeight, imageData.m_pixelWidth }; npy_intp seg_dims[2] = { imageData.m_pixelHeight, imageData.m_pixelWidth }; pyRGB = PyArray_SimpleNew(3, rgb_dims, NPY_UINT8); pyDep = PyArray_SimpleNew(2, dep_dims, NPY_FLOAT32); pySeg = PyArray_SimpleNew(2, seg_dims, NPY_INT32); memcpy(PyArray_DATA(pyRGB), imageData.m_rgbColorData, imageData.m_pixelHeight * imageData.m_pixelWidth * bytesPerPixel); memcpy(PyArray_DATA(pyDep), imageData.m_depthValues, imageData.m_pixelHeight * imageData.m_pixelWidth); memcpy(PyArray_DATA(pySeg), imageData.m_segmentationMaskValues, imageData.m_pixelHeight * imageData.m_pixelWidth); PyTuple_SetItem(pyResultList, 2, pyRGB); PyTuple_SetItem(pyResultList, 3, pyDep); PyTuple_SetItem(pyResultList, 4, pySeg); #else//PYBULLET_USE_NUMPY PyObject* pylistRGB; PyObject* pylistDep; PyObject* pylistSeg; int i, j, p; b3GetCameraImageData(sm, &imageData); // TODO(hellojas): error handling if image size is 0 pyResultList = PyTuple_New(5); PyTuple_SetItem(pyResultList, 0, PyInt_FromLong(imageData.m_pixelWidth)); PyTuple_SetItem(pyResultList, 1, PyInt_FromLong(imageData.m_pixelHeight)); { PyObject* item; int bytesPerPixel = 4; // Red, Green, Blue, and Alpha each 8 bit values int num = bytesPerPixel * imageData.m_pixelWidth * imageData.m_pixelHeight; pylistRGB = PyTuple_New(num); pylistDep = PyTuple_New(imageData.m_pixelWidth * imageData.m_pixelHeight); pylistSeg = PyTuple_New(imageData.m_pixelWidth * imageData.m_pixelHeight); for (i = 0; i < imageData.m_pixelWidth; i++) { for (j = 0; j < imageData.m_pixelHeight; j++) { // TODO(hellojas): validate depth values make sense int depIndex = i + j * imageData.m_pixelWidth; { item = PyFloat_FromDouble(imageData.m_depthValues[depIndex]); PyTuple_SetItem(pylistDep, depIndex, item); } { item2 = PyLong_FromLong(imageData.m_segmentationMaskValues[depIndex]); PyTuple_SetItem(pylistSeg, depIndex, item2); } for (p = 0; p < bytesPerPixel; p++) { int pixelIndex = bytesPerPixel * (i + j * imageData.m_pixelWidth) + p; item = PyInt_FromLong(imageData.m_rgbColorData[pixelIndex]); PyTuple_SetItem(pylistRGB, pixelIndex, item); } } } } PyTuple_SetItem(pyResultList, 2, pylistRGB); PyTuple_SetItem(pyResultList, 3, pylistDep); PyTuple_SetItem(pyResultList, 4, pylistSeg); return pyResultList; #endif//PYBULLET_USE_NUMPY return pyResultList; } } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_computeViewMatrix(PyObject* self, PyObject* args, PyObject *keywds) { PyObject* camEyeObj = 0; PyObject* camTargetPositionObj = 0; PyObject* camUpVectorObj = 0; float camEye[3]; float camTargetPosition[3]; float camUpVector[3]; // set camera resolution, optionally view, projection matrix, light position static char *kwlist[] = { "cameraEyePosition", "cameraTargetPosition", "cameraUpVector",NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "OOO", kwlist, &camEyeObj, &camTargetPositionObj, &camUpVectorObj)) { return NULL; } if (pybullet_internalSetVector(camEyeObj, camEye) && pybullet_internalSetVector(camTargetPositionObj, camTargetPosition) && pybullet_internalSetVector(camUpVectorObj, camUpVector)) { float viewMatrix[16]; PyObject* pyResultList=0; int i; b3ComputeViewMatrixFromPositions(camEye, camTargetPosition, camUpVector, viewMatrix); pyResultList = PyTuple_New(16); for (i = 0; i < 16; i++) { PyObject* item = PyFloat_FromDouble(viewMatrix[i]); PyTuple_SetItem(pyResultList, i, item); } return pyResultList; } PyErr_SetString(SpamError, "Error in computeViewMatrix."); return NULL; } ///compute a view matrix, helper function for b3RequestCameraImageSetCameraMatrices static PyObject* pybullet_computeViewMatrixFromYawPitchRoll(PyObject* self, PyObject* args, PyObject *keywds) { PyObject* cameraTargetPositionObj = 0; float cameraTargetPosition[3]; float distance, yaw, pitch, roll; int upAxisIndex; float viewMatrix[16]; PyObject* pyResultList = 0; int i; // set camera resolution, optionally view, projection matrix, light position static char *kwlist[] = { "cameraTargetPosition", "distance", "yaw", "pitch", "roll", "upAxisIndex" ,NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "Offffi", kwlist, &cameraTargetPositionObj, &distance,&yaw,&pitch,&roll, &upAxisIndex)) { return NULL; } if (!pybullet_internalSetVector(cameraTargetPositionObj, cameraTargetPosition)) { PyErr_SetString(SpamError, "Cannot convert cameraTargetPosition."); return NULL; } b3ComputeViewMatrixFromYawPitchRoll(cameraTargetPosition, distance, yaw, pitch, roll, upAxisIndex, viewMatrix); pyResultList = PyTuple_New(16); for (i = 0; i < 16; i++) { PyObject* item = PyFloat_FromDouble(viewMatrix[i]); PyTuple_SetItem(pyResultList, i, item); } return pyResultList; } ///compute a projection matrix, helper function for b3RequestCameraImageSetCameraMatrices static PyObject* pybullet_computeProjectionMatrix(PyObject* self, PyObject* args, PyObject *keywds) { PyObject* pyResultList = 0; float left; float right; float bottom; float top; float nearVal; float farVal; float projectionMatrix[16]; int i; // set camera resolution, optionally view, projection matrix, light position static char *kwlist[] = { "left", "right", "bottom", "top", "nearVal", "farVal" ,NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "ffffff", kwlist, &left, &right, &bottom, &top, &nearVal, &farVal)) { return NULL; } b3ComputeProjectionMatrix(left, right, bottom, top, nearVal, farVal, projectionMatrix); pyResultList = PyTuple_New(16); for (i = 0; i < 16; i++) { PyObject* item = PyFloat_FromDouble(projectionMatrix[i]); PyTuple_SetItem(pyResultList, i, item); } return pyResultList; } static PyObject* pybullet_computeProjectionMatrixFOV(PyObject* self, PyObject* args, PyObject *keywds) { float fov, aspect, nearVal, farVal; PyObject* pyResultList = 0; float projectionMatrix[16]; int i; static char *kwlist[] = { "fov","aspect","nearVal","farVal",NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "ffff", kwlist, &fov, &aspect, &nearVal, &farVal)) { return NULL; } b3ComputeProjectionMatrixFOV(fov, aspect, nearVal, farVal, projectionMatrix); pyResultList = PyTuple_New(16); for (i = 0; i < 16; i++) { PyObject* item = PyFloat_FromDouble(projectionMatrix[i]); PyTuple_SetItem(pyResultList, i, item); } return pyResultList; } // Render an image from the current timestep of the simulation // // Examples: // renderImage() - default image resolution and camera position // renderImage(w, h) - image resolution of (w,h), default camera // renderImage(w, h, view[16], projection[16]) - set both resolution // and initialize camera to the view and projection values // renderImage(w, h, cameraPos, targetPos, cameraUp, nearVal, farVal) - set // resolution and initialize camera based on camera position, target // position, camera up and fulstrum near/far values. // renderImage(w, h, cameraPos, targetPos, cameraUp, nearVal, farVal, fov) - // set resolution and initialize camera based on camera position, target // position, camera up, fulstrum near/far values and camera field of view. // renderImage(w, h, targetPos, distance, yaw, pitch, upAxisIndex, nearVal, // farVal, fov) // // Note if the (w,h) is too small, the objects may not appear based on // where the camera has been set // // TODO(hellojas): fix image is cut off at head // TODO(hellojas): should we add check to give minimum image resolution // to see object based on camera position? static PyObject* pybullet_renderImageObsolete(PyObject* self, PyObject* args) { /// request an image from a simulated camera, using a software renderer. struct b3CameraImageData imageData; PyObject* objViewMat, *objProjMat; PyObject* objCameraPos, *objTargetPos, *objCameraUp; int width, height; int size = PySequence_Size(args); float viewMatrix[16]; float projectionMatrix[16]; float cameraPos[3]; float targetPos[3]; float cameraUp[3]; float left, right, bottom, top, aspect; float nearVal, farVal; float fov; // inialize cmd b3SharedMemoryCommandHandle command; b3PhysicsClientHandle sm; int physicsClientId = 0; sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } command = b3InitRequestCameraImage(sm); if (size == 2) // only set camera resolution { if (PyArg_ParseTuple(args, "ii", &width, &height)) { b3RequestCameraImageSetPixelResolution(command, width, height); } } else if (size == 4) // set camera resolution and view and projection matrix { if (PyArg_ParseTuple(args, "iiOO", &width, &height, &objViewMat, &objProjMat)) { b3RequestCameraImageSetPixelResolution(command, width, height); // set camera matrices only if set matrix function succeeds if (pybullet_internalSetMatrix(objViewMat, viewMatrix) && (pybullet_internalSetMatrix(objProjMat, projectionMatrix))) { b3RequestCameraImageSetCameraMatrices(command, viewMatrix, projectionMatrix); } else { PyErr_SetString(SpamError, "Error parsing view or projection matrix."); return NULL; } } } else if (size == 7) // set camera resolution, camera positions and // calculate projection using near/far values. { if (PyArg_ParseTuple(args, "iiOOOff", &width, &height, &objCameraPos, &objTargetPos, &objCameraUp, &nearVal, &farVal)) { b3RequestCameraImageSetPixelResolution(command, width, height); if (pybullet_internalSetVector(objCameraPos, cameraPos) && pybullet_internalSetVector(objTargetPos, targetPos) && pybullet_internalSetVector(objCameraUp, cameraUp)) { b3RequestCameraImageSetViewMatrix(command, cameraPos, targetPos, cameraUp); } else { PyErr_SetString(SpamError, "Error parsing camera position, target or up."); return NULL; } aspect = width / height; left = -aspect * nearVal; right = aspect * nearVal; bottom = -nearVal; top = nearVal; b3RequestCameraImageSetProjectionMatrix(command, left, right, bottom, top, nearVal, farVal); } } else if (size == 8) // set camera resolution, camera positions and // calculate projection using near/far values & field // of view { if (PyArg_ParseTuple(args, "iiOOOfff", &width, &height, &objCameraPos, &objTargetPos, &objCameraUp, &nearVal, &farVal, &fov)) { b3RequestCameraImageSetPixelResolution(command, width, height); if (pybullet_internalSetVector(objCameraPos, cameraPos) && pybullet_internalSetVector(objTargetPos, targetPos) && pybullet_internalSetVector(objCameraUp, cameraUp)) { b3RequestCameraImageSetViewMatrix(command, cameraPos, targetPos, cameraUp); } else { PyErr_SetString(SpamError, "Error parsing camera position, target or up."); return NULL; } aspect = width / height; b3RequestCameraImageSetFOVProjectionMatrix(command, fov, aspect, nearVal, farVal); } } else if (size == 11) { int upAxisIndex = 1; float camDistance, yaw, pitch, roll; // sometimes more arguments are better :-) if (PyArg_ParseTuple(args, "iiOffffifff", &width, &height, &objTargetPos, &camDistance, &yaw, &pitch, &roll, &upAxisIndex, &nearVal, &farVal, &fov)) { b3RequestCameraImageSetPixelResolution(command, width, height); if (pybullet_internalSetVector(objTargetPos, targetPos)) { // printf("width = %d, height = %d, targetPos = %f,%f,%f, distance = %f, // yaw = %f, pitch = %f, upAxisIndex = %d, near=%f, far=%f, // fov=%f\n",width,height,targetPos[0],targetPos[1],targetPos[2],camDistance,yaw,pitch,upAxisIndex,nearVal,farVal,fov); b3RequestCameraImageSetViewMatrix2(command, targetPos, camDistance, yaw, pitch, roll, upAxisIndex); aspect = width / height; b3RequestCameraImageSetFOVProjectionMatrix(command, fov, aspect, nearVal, farVal); } else { PyErr_SetString(SpamError, "Error parsing camera target pos"); } } else { PyErr_SetString(SpamError, "Error parsing arguments"); } } else { PyErr_SetString(SpamError, "Invalid number of args passed to renderImage."); return NULL; } if (b3CanSubmitCommand(sm)) { b3SharedMemoryStatusHandle statusHandle; int statusType; // b3RequestCameraImageSelectRenderer(command,ER_BULLET_HARDWARE_OPENGL); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); statusType = b3GetStatusType(statusHandle); if (statusType == CMD_CAMERA_IMAGE_COMPLETED) { PyObject* item2; PyObject* pyResultList; // store 4 elements in this result: width, // height, rgbData, depth #ifdef PYBULLET_USE_NUMPY PyObject* pyRGB; PyObject* pyDep; PyObject* pySeg; int i, j, p; b3GetCameraImageData(sm, &imageData); // TODO(hellojas): error handling if image size is 0 pyResultList = PyTuple_New(5); PyTuple_SetItem(pyResultList, 0, PyInt_FromLong(imageData.m_pixelWidth)); PyTuple_SetItem(pyResultList, 1, PyInt_FromLong(imageData.m_pixelHeight)); int bytesPerPixel = 4; // Red, Green, Blue, and Alpha each 8 bit values npy_intp rgb_dims[3] = {imageData.m_pixelHeight, imageData.m_pixelWidth, bytesPerPixel}; npy_intp dep_dims[2] = {imageData.m_pixelHeight, imageData.m_pixelWidth}; npy_intp seg_dims[2] = {imageData.m_pixelHeight, imageData.m_pixelWidth}; pyRGB = PyArray_SimpleNew(3, rgb_dims, NPY_UINT8); pyDep = PyArray_SimpleNew(2, dep_dims, NPY_FLOAT32); pySeg = PyArray_SimpleNew(2, seg_dims, NPY_INT32); memcpy(PyArray_DATA(pyRGB), imageData.m_rgbColorData, imageData.m_pixelHeight * imageData.m_pixelWidth * bytesPerPixel); memcpy(PyArray_DATA(pyDep), imageData.m_depthValues, imageData.m_pixelHeight * imageData.m_pixelWidth); memcpy(PyArray_DATA(pySeg), imageData.m_segmentationMaskValues, imageData.m_pixelHeight * imageData.m_pixelWidth); PyTuple_SetItem(pyResultList, 2, pyRGB); PyTuple_SetItem(pyResultList, 3, pyDep); PyTuple_SetItem(pyResultList, 4, pySeg); #else//PYBULLET_USE_NUMPY PyObject* pylistRGB; PyObject* pylistDep; PyObject* pylistSeg; int i, j, p; b3GetCameraImageData(sm, &imageData); // TODO(hellojas): error handling if image size is 0 pyResultList = PyTuple_New(5); PyTuple_SetItem(pyResultList, 0, PyInt_FromLong(imageData.m_pixelWidth)); PyTuple_SetItem(pyResultList, 1, PyInt_FromLong(imageData.m_pixelHeight)); { PyObject* item; int bytesPerPixel = 4; // Red, Green, Blue, and Alpha each 8 bit values int num = bytesPerPixel * imageData.m_pixelWidth * imageData.m_pixelHeight; pylistRGB = PyTuple_New(num); pylistDep = PyTuple_New(imageData.m_pixelWidth * imageData.m_pixelHeight); pylistSeg = PyTuple_New(imageData.m_pixelWidth * imageData.m_pixelHeight); for (i = 0; i < imageData.m_pixelWidth; i++) { for (j = 0; j < imageData.m_pixelHeight; j++) { // TODO(hellojas): validate depth values make sense int depIndex = i + j * imageData.m_pixelWidth; { item = PyFloat_FromDouble(imageData.m_depthValues[depIndex]); PyTuple_SetItem(pylistDep, depIndex, item); } { item2 = PyLong_FromLong(imageData.m_segmentationMaskValues[depIndex]); PyTuple_SetItem(pylistSeg, depIndex, item2); } for (p = 0; p < bytesPerPixel; p++) { int pixelIndex = bytesPerPixel * (i + j * imageData.m_pixelWidth) + p; item = PyInt_FromLong(imageData.m_rgbColorData[pixelIndex]); PyTuple_SetItem(pylistRGB, pixelIndex, item); } } } } PyTuple_SetItem(pyResultList, 2, pylistRGB); PyTuple_SetItem(pyResultList, 3, pylistDep); PyTuple_SetItem(pyResultList, 4, pylistSeg); return pyResultList; #endif//PYBULLET_USE_NUMPY return pyResultList; } } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_applyExternalForce(PyObject* self, PyObject* args,PyObject* keywds) { { int objectUniqueId=-1, linkIndex=-1, flags; double force[3]; double position[3] = {0.0, 0.0, 0.0}; PyObject* forceObj=0, *posObj=0; b3SharedMemoryCommandHandle command; b3SharedMemoryStatusHandle statusHandle; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "objectUniqueId", "linkIndex", "forceObj", "posObj", "flags", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "iiOOi|i", kwlist,&objectUniqueId, &linkIndex, &forceObj, &posObj, &flags, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { PyObject* seq; int len, i; seq = PySequence_Fast(forceObj, "expected a sequence"); len = PySequence_Size(forceObj); if (len == 3) { for (i = 0; i < 3; i++) { force[i] = pybullet_internalGetFloatFromSequence(seq, i); } } else { PyErr_SetString(SpamError, "force needs a 3 coordinates [x,y,z]."); Py_DECREF(seq); return NULL; } Py_DECREF(seq); } { PyObject* seq; int len, i; seq = PySequence_Fast(posObj, "expected a sequence"); len = PySequence_Size(posObj); if (len == 3) { for (i = 0; i < 3; i++) { position[i] = pybullet_internalGetFloatFromSequence(seq, i); } } else { PyErr_SetString(SpamError, "position needs a 3 coordinates [x,y,z]."); Py_DECREF(seq); return NULL; } Py_DECREF(seq); } if ((flags != EF_WORLD_FRAME) && (flags != EF_LINK_FRAME)) { PyErr_SetString(SpamError, "flag has to be either WORLD_FRAME or LINK_FRAME"); return NULL; } command = b3ApplyExternalForceCommandInit(sm); b3ApplyExternalForce(command, objectUniqueId, linkIndex, force, position, flags); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_applyExternalTorque(PyObject* self, PyObject* args,PyObject* keywds) { { int objectUniqueId, linkIndex, flags; double torque[3]; PyObject* torqueObj; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "objectUniqueId", "linkIndex", "torqueObj", "flags", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "iiOi|i", kwlist,&objectUniqueId, &linkIndex, &torqueObj, &flags, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { PyObject* seq; int len, i; seq = PySequence_Fast(torqueObj, "expected a sequence"); len = PySequence_Size(torqueObj); if (len == 3) { for (i = 0; i < 3; i++) { torque[i] = pybullet_internalGetFloatFromSequence(seq, i); } } else { PyErr_SetString(SpamError, "torque needs a 3 coordinates [x,y,z]."); Py_DECREF(seq); return NULL; } Py_DECREF(seq); if (linkIndex < -1) { PyErr_SetString(SpamError, "Invalid link index, has to be -1 or larger"); return NULL; } if ((flags != EF_WORLD_FRAME) && (flags != EF_LINK_FRAME)) { PyErr_SetString(SpamError, "flag has to be either WORLD_FRAME or LINK_FRAME"); return NULL; } { b3SharedMemoryStatusHandle statusHandle; b3SharedMemoryCommandHandle command = b3ApplyExternalForceCommandInit(sm); b3ApplyExternalTorque(command, objectUniqueId, -1, torque, flags); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); } } } Py_INCREF(Py_None); return Py_None; } static PyObject* pybullet_getQuaternionFromEuler(PyObject* self, PyObject* args) { double rpy[3]; PyObject* eulerObj; if (PyArg_ParseTuple(args, "O", &eulerObj)) { PyObject* seq; int len, i; seq = PySequence_Fast(eulerObj, "expected a sequence"); len = PySequence_Size(eulerObj); if (len == 3) { for (i = 0; i < 3; i++) { rpy[i] = pybullet_internalGetFloatFromSequence(seq, i); } } else { PyErr_SetString(SpamError, "Euler angles need a 3 coordinates [roll, pitch, yaw]."); Py_DECREF(seq); return NULL; } Py_DECREF(seq); } else { PyErr_SetString(SpamError, "Euler angles need a 3 coordinates [roll, pitch, yaw]."); return NULL; } { double phi, the, psi; double roll = rpy[0]; double pitch = rpy[1]; double yaw = rpy[2]; phi = roll / 2.0; the = pitch / 2.0; psi = yaw / 2.0; { double quat[4] = { sin(phi) * cos(the) * cos(psi) - cos(phi) * sin(the) * sin(psi), cos(phi) * sin(the) * cos(psi) + sin(phi) * cos(the) * sin(psi), cos(phi) * cos(the) * sin(psi) - sin(phi) * sin(the) * cos(psi), cos(phi) * cos(the) * cos(psi) + sin(phi) * sin(the) * sin(psi)}; // normalize the quaternion double len = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * quat[2] + quat[3] * quat[3]); quat[0] /= len; quat[1] /= len; quat[2] /= len; quat[3] /= len; { PyObject* pylist; int i; pylist = PyTuple_New(4); for (i = 0; i < 4; i++) PyTuple_SetItem(pylist, i, PyFloat_FromDouble(quat[i])); return pylist; } } } Py_INCREF(Py_None); return Py_None; } /// quaternion <-> euler yaw/pitch/roll convention from URDF/SDF, see Gazebo /// https://github.com/arpg/Gazebo/blob/master/gazebo/math/Quaternion.cc static PyObject* pybullet_getEulerFromQuaternion(PyObject* self, PyObject* args) { double squ; double sqx; double sqy; double sqz; double quat[4]; PyObject* quatObj; if (PyArg_ParseTuple(args, "O", &quatObj)) { PyObject* seq; int len, i; seq = PySequence_Fast(quatObj, "expected a sequence"); len = PySequence_Size(quatObj); if (len == 4) { for (i = 0; i < 4; i++) { quat[i] = pybullet_internalGetFloatFromSequence(seq, i); } } else { PyErr_SetString(SpamError, "Quaternion need a 4 components [x,y,z,w]."); Py_DECREF(seq); return NULL; } Py_DECREF(seq); } else { PyErr_SetString(SpamError, "Quaternion need a 4 components [x,y,z,w]."); return NULL; } { double rpy[3]; double sarg; sqx = quat[0] * quat[0]; sqy = quat[1] * quat[1]; sqz = quat[2] * quat[2]; squ = quat[3] * quat[3]; rpy[0] = atan2(2 * (quat[1] * quat[2] + quat[3] * quat[0]), squ - sqx - sqy + sqz); sarg = -2 * (quat[0] * quat[2] - quat[3] * quat[1]); rpy[1] = sarg <= -1.0 ? -0.5 * 3.141592538 : (sarg >= 1.0 ? 0.5 * 3.141592538 : asin(sarg)); rpy[2] = atan2(2 * (quat[0] * quat[1] + quat[3] * quat[2]), squ + sqx - sqy - sqz); { PyObject* pylist; int i; pylist = PyTuple_New(3); for (i = 0; i < 3; i++) PyTuple_SetItem(pylist, i, PyFloat_FromDouble(rpy[i])); return pylist; } } Py_INCREF(Py_None); return Py_None; } ///Inverse Kinematics binding static PyObject* pybullet_calculateInverseKinematics(PyObject* self, PyObject* args, PyObject* keywds) { int bodyIndex; int endEffectorLinkIndex; PyObject* targetPosObj=0; PyObject* targetOrnObj=0; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; PyObject* lowerLimitsObj = 0; PyObject* upperLimitsObj = 0; PyObject* jointRangesObj = 0; PyObject* restPosesObj = 0; static char *kwlist[] = { "bodyIndex", "endEffectorLinkIndex", "targetPosition", "targetOrientation","lowerLimits", "upperLimits", "jointRanges", "restPoses", "physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "iiO|OOOOOi", kwlist, &bodyIndex, &endEffectorLinkIndex, &targetPosObj,&targetOrnObj,&lowerLimitsObj, &upperLimitsObj, &jointRangesObj, &restPosesObj, &physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { double pos[3]; double ori[4]={0,1.0,0,0}; int hasPos =pybullet_internalSetVectord(targetPosObj,pos); int hasOrn = pybullet_internalSetVector4d(targetOrnObj,ori); int szLowerLimits = lowerLimitsObj ? PySequence_Size(lowerLimitsObj) : 0; int szUpperLimits = upperLimitsObj? PySequence_Size(upperLimitsObj): 0; int szJointRanges = jointRangesObj? PySequence_Size(jointRangesObj):0; int szRestPoses = restPosesObj? PySequence_Size(restPosesObj):0; int numJoints = b3GetNumJoints(sm, bodyIndex); int hasNullSpace = 0; double* lowerLimits = 0; double* upperLimits = 0; double* jointRanges = 0; double* restPoses = 0; if (numJoints && (szLowerLimits == numJoints) && (szUpperLimits == numJoints) && (szJointRanges == numJoints) && (szRestPoses == numJoints)) { int szInBytes = sizeof(double) * numJoints; int i; lowerLimits = (double*)malloc(szInBytes); upperLimits = (double*)malloc(szInBytes); jointRanges = (double*)malloc(szInBytes); restPoses = (double*)malloc(szInBytes); for (i = 0; i < numJoints; i++) { lowerLimits[i] = pybullet_internalGetFloatFromSequence(lowerLimitsObj, i); upperLimits[i] = pybullet_internalGetFloatFromSequence(upperLimitsObj, i); jointRanges[i] = pybullet_internalGetFloatFromSequence(jointRangesObj, i); restPoses[i] = pybullet_internalGetFloatFromSequence(restPosesObj, i); } hasNullSpace = 1; } if (hasPos) { b3SharedMemoryStatusHandle statusHandle; int numPos=0; int resultBodyIndex; int result; b3SharedMemoryCommandHandle command = b3CalculateInverseKinematicsCommandInit(sm,bodyIndex); if (hasNullSpace) { if (hasOrn) { b3CalculateInverseKinematicsPosOrnWithNullSpaceVel(command, numJoints, endEffectorLinkIndex, pos, ori, lowerLimits, upperLimits, jointRanges, restPoses); } else { b3CalculateInverseKinematicsPosWithNullSpaceVel(command,numJoints, endEffectorLinkIndex, pos, lowerLimits, upperLimits, jointRanges, restPoses); } } else { if (hasOrn) { b3CalculateInverseKinematicsAddTargetPositionWithOrientation(command,endEffectorLinkIndex,pos,ori); } else { b3CalculateInverseKinematicsAddTargetPurePosition(command,endEffectorLinkIndex,pos); } } statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); result = b3GetStatusInverseKinematicsJointPositions(statusHandle, &resultBodyIndex, &numPos, 0); if (result && numPos) { int i; PyObject* pylist; double* ikOutPutJointPos = (double*)malloc(numPos*sizeof(double)); result = b3GetStatusInverseKinematicsJointPositions(statusHandle, &resultBodyIndex, &numPos, ikOutPutJointPos); pylist = PyTuple_New(numPos); for (i = 0; i < numPos; i++) { PyTuple_SetItem(pylist, i, PyFloat_FromDouble(ikOutPutJointPos[i])); } free(ikOutPutJointPos); return pylist; } else { PyErr_SetString(SpamError, "Error in calculateInverseKinematics"); return NULL; } } else { PyErr_SetString(SpamError, "calculateInverseKinematics couldn't extract position vector3"); return NULL; } } Py_INCREF(Py_None); return Py_None; } /// Given an object id, joint positions, joint velocities and joint /// accelerations, /// compute the joint forces using Inverse Dynamics static PyObject* pybullet_calculateInverseDynamics(PyObject* self, PyObject* args,PyObject* keywds) { { int bodyIndex; PyObject* objPositionsQ; PyObject* objVelocitiesQdot; PyObject* objAccelerations; int physicsClientId = 0; b3PhysicsClientHandle sm = 0; static char *kwlist[] = { "bodyIndex", "objPositions", "objVelocities", "objAccelerations","physicsClientId", NULL }; if (!PyArg_ParseTupleAndKeywords(args, keywds, "iOOO|i", kwlist, &bodyIndex, &objPositionsQ, &objVelocitiesQdot, &objAccelerations,&physicsClientId)) { return NULL; } sm = getPhysicsClient(physicsClientId); if (sm == 0) { PyErr_SetString(SpamError, "Not connected to physics server."); return NULL; } { int szObPos = PySequence_Size(objPositionsQ); int szObVel = PySequence_Size(objVelocitiesQdot); int szObAcc = PySequence_Size(objAccelerations); int numJoints = b3GetNumJoints(sm, bodyIndex); if (numJoints && (szObPos == numJoints) && (szObVel == numJoints) && (szObAcc == numJoints)) { int szInBytes = sizeof(double) * numJoints; int i; PyObject* pylist = 0; double* jointPositionsQ = (double*)malloc(szInBytes); double* jointVelocitiesQdot = (double*)malloc(szInBytes); double* jointAccelerations = (double*)malloc(szInBytes); double* jointForcesOutput = (double*)malloc(szInBytes); for (i = 0; i < numJoints; i++) { jointPositionsQ[i] = pybullet_internalGetFloatFromSequence(objPositionsQ, i); jointVelocitiesQdot[i] = pybullet_internalGetFloatFromSequence(objVelocitiesQdot, i); jointAccelerations[i] = pybullet_internalGetFloatFromSequence(objAccelerations, i); } { b3SharedMemoryStatusHandle statusHandle; int statusType; b3SharedMemoryCommandHandle commandHandle = b3CalculateInverseDynamicsCommandInit( sm, bodyIndex, jointPositionsQ, jointVelocitiesQdot, jointAccelerations); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, commandHandle); statusType = b3GetStatusType(statusHandle); if (statusType == CMD_CALCULATED_INVERSE_DYNAMICS_COMPLETED) { int bodyUniqueId; int dofCount; b3GetStatusInverseDynamicsJointForces(statusHandle, &bodyUniqueId, &dofCount, 0); if (dofCount) { b3GetStatusInverseDynamicsJointForces(statusHandle, 0, 0, jointForcesOutput); { { int i; pylist = PyTuple_New(dofCount); for (i = 0; i < dofCount; i++) PyTuple_SetItem(pylist, i, PyFloat_FromDouble(jointForcesOutput[i])); } } } } else { PyErr_SetString(SpamError, "Internal error in calculateInverseDynamics"); } } free(jointPositionsQ); free(jointVelocitiesQdot); free(jointAccelerations); free(jointForcesOutput); if (pylist) return pylist; } else { PyErr_SetString(SpamError, "calculateInverseDynamics numJoints needs to be " "positive and [joint positions], [joint velocities], " "[joint accelerations] need to match the number of " "joints."); return NULL; } } } Py_INCREF(Py_None); return Py_None; } static PyMethodDef SpamMethods[] = { {"connect",(PyCFunction)pybullet_connectPhysicsServer, METH_VARARGS|METH_KEYWORDS, "Connect to an existing physics server (using shared memory by default)."}, {"disconnect", (PyCFunction)pybullet_disconnectPhysicsServer, METH_VARARGS|METH_KEYWORDS, "Disconnect from the physics server."}, {"resetSimulation", (PyCFunction)pybullet_resetSimulation, METH_VARARGS|METH_KEYWORDS, "Reset the simulation: remove all objects and start from an empty world."}, {"stepSimulation", (PyCFunction)pybullet_stepSimulation, METH_VARARGS|METH_KEYWORDS, "Step the simulation using forward dynamics."}, {"setGravity", (PyCFunction)pybullet_setGravity, METH_VARARGS|METH_KEYWORDS, "Set the gravity acceleration (x,y,z)."}, {"setTimeStep",(PyCFunction) pybullet_setTimeStep, METH_VARARGS|METH_KEYWORDS, "Set the amount of time to proceed at each call to stepSimulation. (unit " "is seconds, typically range is 0.01 or 0.001)"}, {"setDefaultContactERP", (PyCFunction) pybullet_setDefaultContactERP, METH_VARARGS| METH_KEYWORDS, "Set the amount of contact penetration Error Recovery Paramater " "(ERP) in each time step. \ This is an tuning parameter to control resting contact stability. " "This value depends on the time step."}, { "setRealTimeSimulation",(PyCFunction) pybullet_setRealTimeSimulation, METH_VARARGS| METH_KEYWORDS, "Enable or disable real time simulation (using the real time clock," " RTC) in the physics server. Expects one integer argument, 0 or 1" }, { "setPhysicsEngineParameter", (PyCFunction)pybullet_setPhysicsEngineParameter, METH_VARARGS | METH_KEYWORDS, "Set some internal physics engine parameter, such as cfm or erp etc." }, { "setInternalSimFlags", (PyCFunction)pybullet_setInternalSimFlags, METH_VARARGS| METH_KEYWORDS, "This is for experimental purposes, use at own risk, magic may or not happen"}, {"loadURDF", (PyCFunction) pybullet_loadURDF, METH_VARARGS | METH_KEYWORDS, "Create a multibody by loading a URDF file."}, {"loadSDF", (PyCFunction)pybullet_loadSDF, METH_VARARGS| METH_KEYWORDS, "Load multibodies from an SDF file."}, { "loadBullet", (PyCFunction)pybullet_loadBullet, METH_VARARGS| METH_KEYWORDS, "Restore the full state of the world from a .bullet file." }, { "saveBullet", (PyCFunction)pybullet_saveBullet, METH_VARARGS| METH_KEYWORDS, "Save the full state of the world to a .bullet file." }, { "loadMJCF",(PyCFunction) pybullet_loadMJCF, METH_VARARGS| METH_KEYWORDS, "Load multibodies from an MJCF file." }, {"createConstraint", (PyCFunction)pybullet_createUserConstraint, METH_VARARGS | METH_KEYWORDS, "Create a constraint between two bodies. Returns a (int) unique id, if successfull." }, {"changeConstraint", (PyCFunction)pybullet_changeUserConstraint, METH_VARARGS | METH_KEYWORDS, "Change some parameters of an existing constraint, such as the child pivot or child frame orientation, using its unique id." }, {"removeConstraint", (PyCFunction)pybullet_removeUserConstraint, METH_VARARGS | METH_KEYWORDS, "Remove a constraint using its unique id." }, {"saveWorld", (PyCFunction)pybullet_saveWorld, METH_VARARGS| METH_KEYWORDS, "Save a approximate Python file to reproduce the current state of the world: saveWorld" "(filename). (very preliminary and approximately)"}, {"getNumBodies", (PyCFunction)pybullet_getNumBodies, METH_VARARGS| METH_KEYWORDS, "Get the number of bodies in the simulation."}, {"getBodyUniqueId", (PyCFunction)pybullet_getBodyUniqueId, METH_VARARGS| METH_KEYWORDS, "Get the unique id of the body, given a integer serial index in range [0.. number of bodies)."}, {"getBodyInfo",(PyCFunction) pybullet_getBodyInfo, METH_VARARGS | METH_KEYWORDS, "Get the body info, given a body unique id."}, {"getBasePositionAndOrientation",(PyCFunction) pybullet_getBasePositionAndOrientation, METH_VARARGS | METH_KEYWORDS, "Get the world position and orientation of the base of the object. " "(x,y,z) position vector and (x,y,z,w) quaternion orientation."}, {"resetBasePositionAndOrientation", (PyCFunction) pybullet_resetBasePositionAndOrientation, METH_VARARGS| METH_KEYWORDS, "Reset the world position and orientation of the base of the object " "instantaneously, not through physics simulation. (x,y,z) position vector " "and (x,y,z,w) quaternion orientation."}, { "getBaseVelocity", (PyCFunction)pybullet_getBaseVelocity, METH_VARARGS| METH_KEYWORDS, "Get the linear and angular velocity of the base of the object " " in world space coordinates. " "(x,y,z) linear velocity vector and (x,y,z) angular velocity vector." }, { "resetBaseVelocity", (PyCFunction)pybullet_resetBaseVelocity, METH_VARARGS | METH_KEYWORDS, "Reset the linear and/or angular velocity of the base of the object " " in world space coordinates. " "linearVelocity (x,y,z) and angularVelocity (x,y,z)." }, {"getNumJoints", (PyCFunction)pybullet_getNumJoints, METH_VARARGS| METH_KEYWORDS, "Get the number of joints for an object."}, {"getJointInfo", (PyCFunction)pybullet_getJointInfo, METH_VARARGS| METH_KEYWORDS, "Get the name and type info for a joint on a body."}, {"getJointState",(PyCFunction) pybullet_getJointState, METH_VARARGS| METH_KEYWORDS, "Get the state (position, velocity etc) for a joint on a body."}, {"getLinkState", (PyCFunction)pybullet_getLinkState, METH_VARARGS| METH_KEYWORDS, "Provides extra information such as the Cartesian world coordinates" " center of mass (COM) of the link, relative to the world reference" " frame."}, {"resetJointState",(PyCFunction) pybullet_resetJointState, METH_VARARGS| METH_KEYWORDS, "Reset the state (position, velocity etc) for a joint on a body " "instantaneously, not through physics simulation."}, {"setJointMotorControl",(PyCFunction) pybullet_setJointMotorControl, METH_VARARGS, "This (obsolete) method cannot select non-zero physicsClientId, use setJointMotorControl2 instead." "Set a single joint motor control mode and desired target value. There is " "no immediate state change, stepSimulation will process the motors."}, {"setJointMotorControl2",(PyCFunction) pybullet_setJointMotorControl2, METH_VARARGS| METH_KEYWORDS, "Set a single joint motor control mode and desired target value. There is " "no immediate state change, stepSimulation will process the motors."}, {"applyExternalForce",(PyCFunction) pybullet_applyExternalForce, METH_VARARGS| METH_KEYWORDS, "for objectUniqueId, linkIndex (-1 for base/root link), apply a force " "[x,y,z] at the a position [x,y,z], flag to select FORCE_IN_LINK_FRAME or " "WORLD_FRAME coordinates"}, {"applyExternalTorque", (PyCFunction)pybullet_applyExternalTorque, METH_VARARGS| METH_KEYWORDS, "for objectUniqueId, linkIndex (-1 for base/root link) apply a torque " "[x,y,z] in Cartesian coordinates, flag to select TORQUE_IN_LINK_FRAME or " "WORLD_FRAME coordinates"}, {"renderImage", pybullet_renderImageObsolete, METH_VARARGS, "obsolete, please use getCameraImage and getViewProjectionMatrices instead" }, { "getCameraImage",(PyCFunction)pybullet_getCameraImage, METH_VARARGS| METH_KEYWORDS, "Render an image (given the pixel resolution width, height, camera viewMatrix " ", projectionMatrix, lightDirection, lightColor, lightDistance, shadow, lightAmbientCoeff, lightDiffuseCoeff, and lightSpecularCoeff), and return the " "8-8-8bit RGB pixel data and floating point depth values" #ifdef PYBULLET_USE_NUMPY " as NumPy arrays" #endif }, { "computeViewMatrix", (PyCFunction)pybullet_computeViewMatrix, METH_VARARGS | METH_KEYWORDS, "Compute a camera viewmatrix from camera eye, target position and up vector " }, { "computeViewMatrixFromYawPitchRoll",(PyCFunction)pybullet_computeViewMatrixFromYawPitchRoll, METH_VARARGS | METH_KEYWORDS, "Compute a camera viewmatrix from camera eye, target position and up vector " }, { "computeProjectionMatrix", (PyCFunction)pybullet_computeProjectionMatrix, METH_VARARGS | METH_KEYWORDS, "Compute a camera projection matrix from screen left/right/bottom/top/near/far values" }, { "computeProjectionMatrixFOV", (PyCFunction)pybullet_computeProjectionMatrixFOV, METH_VARARGS | METH_KEYWORDS, "Compute a camera projection matrix from fov, aspect ratio, near, far values" }, {"getContactPoints", (PyCFunction)pybullet_getContactPointData, METH_VARARGS | METH_KEYWORDS, "Return existing contact points after the stepSimulation command. " "Optional arguments one or two object unique " "ids, that need to be involved in the contact."}, {"getClosestPoints", (PyCFunction)pybullet_getClosestPointData, METH_VARARGS | METH_KEYWORDS, "Compute the closest points between two objects, if the distance is below a given threshold." "Input is two objects unique ids and distance threshold." }, { "getOverlappingObjects", (PyCFunction)pybullet_getOverlappingObjects, METH_VARARGS | METH_KEYWORDS, "Return all the objects that have overlap with a given " "axis-aligned bounding box volume (AABB)." "Input are two vectors defining the AABB in world space [min_x,min_y,min_z],[max_x,max_y,max_z]." }, { "addUserDebugLine", (PyCFunction)pybullet_addUserDebugLine, METH_VARARGS | METH_KEYWORDS, "Add a user debug draw line with lineFrom[3], lineTo[3], lineColorRGB[3], lineWidth, lifeTime. " "A lifeTime of 0 means permanent until removed. Returns a unique id for the user debug item." }, { "addUserDebugText", (PyCFunction)pybullet_addUserDebugText, METH_VARARGS | METH_KEYWORDS, "Add a user debug draw line with text, textPosition[3], textSize and lifeTime in seconds " "A lifeTime of 0 means permanent until removed. Returns a unique id for the user debug item." }, { "removeUserDebugItem", (PyCFunction)pybullet_removeUserDebugItem, METH_VARARGS | METH_KEYWORDS, "remove a user debug draw item, giving its unique id" }, { "removeAllUserDebugItems", (PyCFunction)pybullet_removeAllUserDebugItems, METH_VARARGS | METH_KEYWORDS, "remove all user debug draw items" }, { "setDebugObjectColor", (PyCFunction)pybullet_setDebugObjectColor, METH_VARARGS | METH_KEYWORDS, "Override the wireframe debug drawing color for a particular object unique id / link index." "If you ommit the color, the custom color will be removed." }, {"getVisualShapeData", (PyCFunction)pybullet_getVisualShapeData, METH_VARARGS| METH_KEYWORDS, "Return the visual shape information for one object." }, {"resetVisualShapeData", (PyCFunction)pybullet_resetVisualShapeData, METH_VARARGS| METH_KEYWORDS, "Reset part of the visual shape information for one object." }, {"loadTexture", (PyCFunction)pybullet_loadTexture, METH_VARARGS| METH_KEYWORDS, "Load texture file." }, {"getQuaternionFromEuler", pybullet_getQuaternionFromEuler, METH_VARARGS, "Convert Euler [roll, pitch, yaw] as in URDF/SDF convention, to " "quaternion [x,y,z,w]"}, {"getEulerFromQuaternion", pybullet_getEulerFromQuaternion, METH_VARARGS, "Convert quaternion [x,y,z,w] to Euler [roll, pitch, yaw] as in URDF/SDF " "convention"}, {"getMatrixFromQuaterion", pybullet_getMatrixFromQuaterion,METH_VARARGS, "Compute the 3x3 matrix from a quaternion, as a list of 9 values (row-major)"}, {"calculateInverseDynamics", (PyCFunction)pybullet_calculateInverseDynamics, METH_VARARGS| METH_KEYWORDS, "Given an object id, joint positions, joint velocities and joint " "accelerations, compute the joint forces using Inverse Dynamics"}, {"calculateInverseKinematics", (PyCFunction)pybullet_calculateInverseKinematics, METH_VARARGS| METH_KEYWORDS, "Inverse Kinematics bindings: Given an object id, " "current joint positions and target position" " for the end effector," "compute the inverse kinematics and return the new joint state"}, { "getVREvents", (PyCFunction)pybullet_getVREvents, METH_VARARGS | METH_KEYWORDS, "Get Virtual Reality events, for example to track VR controllers position/buttons" }, { "setVRCameraState", (PyCFunction)pybullet_setVRCameraState, METH_VARARGS | METH_KEYWORDS, "Set properties of the VR Camera such as its root transform " "for teleporting or to track objects (camera inside a vehicle for example)." }, { "rayTest", (PyCFunction)pybullet_rayTest, METH_VARARGS | METH_KEYWORDS, "Cast a ray and return the first object hit, if any. " "Takes two arguments (from position [x,y,z] and to position [x,y,z] in Cartesian world coordinates" }, // todo(erwincoumans) // saveSnapshot // loadSnapshot // raycast info // object names {NULL, NULL, 0, NULL} /* Sentinel */ }; #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "pybullet", /* m_name */ "Python bindings for Bullet Physics Robotics API (also known as Shared " "Memory API)", /* m_doc */ -1, /* m_size */ SpamMethods, /* m_methods */ NULL, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ }; #endif PyMODINIT_FUNC #if PY_MAJOR_VERSION >= 3 PyInit_pybullet(void) #else initpybullet(void) #endif { PyObject* m; #if PY_MAJOR_VERSION >= 3 m = PyModule_Create(&moduledef); #else m = Py_InitModule3("pybullet", SpamMethods, "Python bindings for Bullet"); #endif #if PY_MAJOR_VERSION >= 3 if (m == NULL) return m; #else if (m == NULL) return; #endif PyModule_AddIntConstant(m, "SHARED_MEMORY", eCONNECT_SHARED_MEMORY); // user read PyModule_AddIntConstant(m, "DIRECT", eCONNECT_DIRECT); // user read PyModule_AddIntConstant(m, "GUI", eCONNECT_GUI); // user read PyModule_AddIntConstant(m, "UDP", eCONNECT_UDP); // user read PyModule_AddIntConstant(m, "JOINT_REVOLUTE", eRevoluteType); // user read PyModule_AddIntConstant(m, "JOINT_PRISMATIC", ePrismaticType); // user read PyModule_AddIntConstant(m, "JOINT_SPHERICAL", eSphericalType); // user read PyModule_AddIntConstant(m, "JOINT_PLANAR", ePlanarType); // user read PyModule_AddIntConstant(m, "JOINT_FIXED", eFixedType); // user read PyModule_AddIntConstant(m, "JOINT_POINT2POINT", ePoint2PointType); // user read PyModule_AddIntConstant(m, "TORQUE_CONTROL", CONTROL_MODE_TORQUE); PyModule_AddIntConstant(m, "VELOCITY_CONTROL", CONTROL_MODE_VELOCITY); // user read PyModule_AddIntConstant(m, "POSITION_CONTROL", CONTROL_MODE_POSITION_VELOCITY_PD); // user read PyModule_AddIntConstant(m, "LINK_FRAME", EF_LINK_FRAME); PyModule_AddIntConstant(m, "WORLD_FRAME", EF_WORLD_FRAME); PyModule_AddIntConstant(m, "CONTACT_REPORT_EXISTING", CONTACT_QUERY_MODE_REPORT_EXISTING_CONTACT_POINTS); PyModule_AddIntConstant(m, "CONTACT_RECOMPUTE_CLOSEST", CONTACT_QUERY_MODE_COMPUTE_CLOSEST_POINTS); PyModule_AddIntConstant(m, "VR_BUTTON_IS_DOWN", eButtonIsDown); PyModule_AddIntConstant(m, "VR_BUTTON_WAS_TRIGGERED", eButtonTriggered); PyModule_AddIntConstant(m, "VR_BUTTON_WAS_RELEASED", eButtonReleased); PyModule_AddIntConstant(m, "VR_MAX_CONTROLLERS", MAX_VR_CONTROLLERS); PyModule_AddIntConstant(m, "VR_MAX_BUTTONS", MAX_VR_BUTTONS); SpamError = PyErr_NewException("pybullet.error", NULL, NULL); Py_INCREF(SpamError); PyModule_AddObject(m, "error", SpamError); #ifdef PYBULLET_USE_NUMPY // Initialize numpy array. import_array(); #endif //PYBULLET_USE_NUMPY #if PY_MAJOR_VERSION >= 3 return m; #endif }