2016-04-30 18:18:54 +00:00
|
|
|
#include "../SharedMemory/SharedMemoryInProcessPhysicsC_API.h"
|
|
|
|
#include "../SharedMemory/PhysicsClientC_API.h"
|
2016-05-10 07:57:54 +00:00
|
|
|
#include "../SharedMemory/PhysicsDirectC_API.h"
|
|
|
|
|
2016-04-30 18:18:54 +00:00
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#include <Python/Python.h>
|
|
|
|
#else
|
|
|
|
#include <Python.h>
|
|
|
|
#endif
|
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
enum eCONNECT_METHOD
|
|
|
|
{
|
|
|
|
eCONNECT_GUI=1,
|
|
|
|
eCONNECT_DIRECT=2,
|
|
|
|
eCONNECT_SHARED_MEMORY=3,
|
|
|
|
};
|
|
|
|
|
2016-04-30 18:18:54 +00:00
|
|
|
static PyObject *SpamError;
|
2016-05-03 19:59:21 +00:00
|
|
|
static b3PhysicsClientHandle sm=0;
|
|
|
|
|
2016-04-30 18:18:54 +00:00
|
|
|
|
|
|
|
static PyObject *
|
2016-05-03 19:59:21 +00:00
|
|
|
pybullet_stepSimulation(PyObject *self, PyObject *args)
|
2016-04-30 18:18:54 +00:00
|
|
|
{
|
2016-05-03 19:59:21 +00:00
|
|
|
if (0==sm)
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Not connected to physics server.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-04-30 18:18:54 +00:00
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
{
|
|
|
|
b3SharedMemoryStatusHandle statusHandle;
|
|
|
|
int statusType;
|
|
|
|
|
|
|
|
if (b3CanSubmitCommand(sm))
|
2016-04-30 18:18:54 +00:00
|
|
|
{
|
2016-05-10 07:57:54 +00:00
|
|
|
statusHandle = b3SubmitClientCommandAndWaitStatus(sm, b3InitStepSimulationCommand(sm));
|
|
|
|
statusType = b3GetStatusType(statusHandle);
|
|
|
|
}
|
|
|
|
}
|
2016-04-30 18:18:54 +00:00
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
2016-04-30 18:18:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
2016-05-03 19:59:21 +00:00
|
|
|
pybullet_connectPhysicsServer(PyObject *self, PyObject *args)
|
2016-04-30 18:18:54 +00:00
|
|
|
{
|
2016-05-03 19:59:21 +00:00
|
|
|
if (0!=sm)
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Already connected to physics server, disconnect first.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2016-05-10 07:57:54 +00:00
|
|
|
int method=eCONNECT_GUI;
|
|
|
|
if (!PyArg_ParseTuple(args, "i", &method))
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "connectPhysicsServer expected argument eCONNECT_GUI, eCONNECT_DIRECT or eCONNECT_SHARED_MEMORY");
|
|
|
|
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(SHARED_MEMORY_KEY);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "connectPhysicsServer unexpected argument");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-05-03 19:59:21 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
2016-05-03 19:59:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
pybullet_disconnectPhysicsServer(PyObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
if (0==sm)
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Not connected to physics server.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
b3DisconnectSharedMemory(sm);
|
|
|
|
sm = 0;
|
|
|
|
}
|
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
2016-05-03 19:59:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
pybullet_loadURDF(PyObject* self, PyObject* args)
|
|
|
|
{
|
2016-05-10 07:57:54 +00:00
|
|
|
|
2016-04-30 18:18:54 +00:00
|
|
|
int size= PySequence_Size(args);
|
|
|
|
|
|
|
|
int bodyIndex = -1;
|
2016-05-26 22:58:10 +00:00
|
|
|
const char* urdfFileName="";
|
2016-04-30 18:18:54 +00:00
|
|
|
float startPosX =0;
|
2016-05-03 19:59:21 +00:00
|
|
|
float startPosY =0;
|
|
|
|
float startPosZ = 1;
|
2016-04-30 18:18:54 +00:00
|
|
|
float startOrnX = 0;
|
|
|
|
float startOrnY = 0;
|
|
|
|
float startOrnZ = 0;
|
2016-05-26 22:58:10 +00:00
|
|
|
float startOrnW = 1;
|
2016-04-30 18:18:54 +00:00
|
|
|
printf("size=%d\n", size);
|
2016-05-10 07:57:54 +00:00
|
|
|
if (0==sm)
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Not connected to physics server.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-04-30 18:18:54 +00:00
|
|
|
if (size==1)
|
|
|
|
{
|
|
|
|
if (!PyArg_ParseTuple(args, "s", &urdfFileName))
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (size == 4)
|
|
|
|
{
|
|
|
|
if (!PyArg_ParseTuple(args, "sfff", &urdfFileName,
|
|
|
|
&startPosX,&startPosY,&startPosZ))
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-05-26 22:58:10 +00:00
|
|
|
if (size==8)
|
2016-04-30 18:18:54 +00:00
|
|
|
{
|
|
|
|
if (!PyArg_ParseTuple(args, "sfffffff", &urdfFileName,
|
2016-05-26 22:58:10 +00:00
|
|
|
&startPosX,&startPosY,&startPosZ,
|
|
|
|
&startOrnX,&startOrnY,&startOrnZ, &startOrnW))
|
2016-04-30 18:18:54 +00:00
|
|
|
return NULL;
|
2016-05-26 22:58:10 +00:00
|
|
|
|
2016-04-30 18:18:54 +00:00
|
|
|
}
|
2016-05-03 19:59:21 +00:00
|
|
|
{
|
2016-05-10 07:57:54 +00:00
|
|
|
|
2016-05-03 19:59:21 +00:00
|
|
|
b3SharedMemoryStatusHandle statusHandle;
|
|
|
|
int statusType;
|
|
|
|
b3SharedMemoryCommandHandle command = b3LoadUrdfCommandInit(sm, urdfFileName);
|
2016-05-10 07:57:54 +00:00
|
|
|
printf("urdf filename = %s\n", urdfFileName);
|
2016-05-03 19:59:21 +00:00
|
|
|
//setting the initial position, orientation and other arguments are optional
|
|
|
|
b3LoadUrdfCommandSetStartPosition(command, startPosX,startPosY,startPosZ);
|
|
|
|
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);
|
|
|
|
}
|
2016-04-30 18:18:54 +00:00
|
|
|
return PyLong_FromLong(bodyIndex);
|
|
|
|
}
|
2016-05-03 19:59:21 +00:00
|
|
|
static PyObject *
|
|
|
|
pybullet_resetSimulation(PyObject* self, PyObject* args)
|
|
|
|
{
|
|
|
|
if (0==sm)
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Not connected to physics server.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
b3SharedMemoryStatusHandle statusHandle;
|
|
|
|
statusHandle = b3SubmitClientCommandAndWaitStatus(sm, b3InitResetSimulationCommand(sm));
|
|
|
|
}
|
2016-05-10 07:57:54 +00:00
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
2016-05-04 06:34:48 +00:00
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
static PyObject *
|
|
|
|
pybullet_setGravity(PyObject* self, PyObject* args)
|
|
|
|
{
|
|
|
|
if (0==sm)
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Not connected to physics server.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
float gravX=0;
|
|
|
|
float gravY=0;
|
|
|
|
float gravZ=-10;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
b3SharedMemoryCommandHandle command = b3InitPhysicsParamCommand(sm);
|
|
|
|
b3SharedMemoryStatusHandle statusHandle;
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "fff", &gravX,&gravY,&gravZ))
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "setGravity expected (x,y,z) values.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ret = b3PhysicsParamSetGravity(command, gravX,gravY, gravZ);
|
|
|
|
//ret = b3PhysicsParamSetTimeStep(command, timeStep);
|
|
|
|
statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command);
|
|
|
|
//ASSERT_EQ(b3GetStatusType(statusHandle), CMD_CLIENT_COMMAND_COMPLETED);
|
|
|
|
}
|
|
|
|
|
2016-05-24 22:29:26 +00:00
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void pybullet_internalGetBasePositionAndOrientation(int bodyIndex, double basePosition[3],double baseOrientation[3])
|
|
|
|
{
|
|
|
|
basePosition[0] = 0.;
|
|
|
|
basePosition[1] = 0.;
|
|
|
|
basePosition[2] = 0.;
|
|
|
|
|
|
|
|
baseOrientation[0] = 0.;
|
|
|
|
baseOrientation[1] = 0.;
|
|
|
|
baseOrientation[2] = 0.;
|
|
|
|
baseOrientation[3] = 1.;
|
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
{
|
2016-05-24 22:29:26 +00:00
|
|
|
|
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
{
|
2016-05-24 22:29:26 +00:00
|
|
|
b3SharedMemoryCommandHandle cmd_handle =
|
|
|
|
b3RequestActualStateCommandInit(sm, bodyIndex);
|
|
|
|
b3SharedMemoryStatusHandle status_handle =
|
|
|
|
b3SubmitClientCommandAndWaitStatus(sm, cmd_handle);
|
|
|
|
|
|
|
|
const int status_type = b3GetStatusType(status_handle);
|
|
|
|
|
|
|
|
const double* actualStateQ;
|
|
|
|
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 */);
|
|
|
|
|
|
|
|
//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];
|
2016-05-10 07:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
2016-05-24 22:29:26 +00:00
|
|
|
}
|
2016-05-10 07:57:54 +00:00
|
|
|
|
2016-05-24 22:29:26 +00:00
|
|
|
static PyObject *
|
|
|
|
pybullet_getBasePositionAndOrientation(PyObject* self, PyObject* args)
|
|
|
|
{
|
|
|
|
if (0==sm)
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Not connected to physics server.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bodyIndex = -1;
|
|
|
|
if (!PyArg_ParseTuple(args, "i", &bodyIndex ))
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Expected a body index (integer).");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
double basePosition[3];
|
|
|
|
double baseOrientation[4];
|
|
|
|
|
|
|
|
pybullet_internalGetBasePositionAndOrientation(bodyIndex,basePosition,baseOrientation);
|
|
|
|
PyObject *pylistPos;
|
|
|
|
{
|
|
|
|
|
|
|
|
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 *pylistOrientation;
|
|
|
|
{
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-05-03 19:59:21 +00:00
|
|
|
}
|
2016-04-30 18:18:54 +00:00
|
|
|
|
2016-05-24 22:29:26 +00:00
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
static PyObject *
|
|
|
|
pybullet_getNumJoints(PyObject* self, PyObject* args)
|
|
|
|
{
|
|
|
|
if (0==sm)
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Not connected to physics server.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int bodyIndex = -1;
|
|
|
|
int numJoints=0;
|
|
|
|
if (!PyArg_ParseTuple(args, "i", &bodyIndex ))
|
|
|
|
{
|
|
|
|
PyErr_SetString(SpamError, "Expected a body index (integer).");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
numJoints = b3GetNumJoints(sm,bodyIndex);
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
return PyLong_FromLong(numJoints);
|
|
|
|
#else
|
|
|
|
return PyInt_FromLong(numJoints);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-30 18:18:54 +00:00
|
|
|
static PyMethodDef SpamMethods[] = {
|
2016-05-03 19:59:21 +00:00
|
|
|
{"loadURDF", pybullet_loadURDF, METH_VARARGS,
|
|
|
|
"Create a multibody by loading a URDF file."},
|
|
|
|
|
|
|
|
{"connect", pybullet_connectPhysicsServer, METH_VARARGS,
|
|
|
|
"Connect to an existing physics server (using shared memory by default)."},
|
2016-05-10 07:57:54 +00:00
|
|
|
|
2016-05-03 19:59:21 +00:00
|
|
|
{"disconnect", pybullet_disconnectPhysicsServer, METH_VARARGS,
|
|
|
|
"Disconnect from the physics server."},
|
|
|
|
|
|
|
|
{"resetSimulation", pybullet_resetSimulation, METH_VARARGS,
|
|
|
|
"Reset the simulation: remove all objects and start from an empty world."},
|
2016-05-10 07:57:54 +00:00
|
|
|
|
|
|
|
{"stepSimulation", pybullet_stepSimulation, METH_VARARGS,
|
2016-05-03 19:59:21 +00:00
|
|
|
"Step the simulation using forward dynamics."},
|
2016-05-10 07:57:54 +00:00
|
|
|
|
|
|
|
{"setGravity", pybullet_setGravity, METH_VARARGS,
|
|
|
|
"Set the gravity acceleration (x,y,z)."},
|
|
|
|
|
2016-05-24 22:29:26 +00:00
|
|
|
{"getBasePositionAndOrientation", pybullet_getBasePositionAndOrientation, METH_VARARGS,
|
|
|
|
"Get the world position and orientation of the base of the object. (x,y,z) position vector and (x,y,z,w) quaternion orientation."},
|
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
{"getNumsetGravity", pybullet_setGravity, METH_VARARGS,
|
|
|
|
"Set the gravity acceleration (x,y,z)."},
|
|
|
|
{
|
|
|
|
"getNumJoints", pybullet_getNumJoints, METH_VARARGS,
|
|
|
|
"Get the number of joints for an object."},
|
|
|
|
|
2016-04-30 18:18:54 +00:00
|
|
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
|
|
|
};
|
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
static struct PyModuleDef moduledef = {
|
|
|
|
PyModuleDef_HEAD_INIT,
|
|
|
|
"pybullet", /* m_name */
|
|
|
|
"Python bindings for Bullet", /* m_doc */
|
|
|
|
-1, /* m_size */
|
|
|
|
SpamMethods, /* m_methods */
|
|
|
|
NULL, /* m_reload */
|
|
|
|
NULL, /* m_traverse */
|
|
|
|
NULL, /* m_clear */
|
|
|
|
NULL, /* m_free */
|
|
|
|
};
|
|
|
|
#endif
|
2016-04-30 18:18:54 +00:00
|
|
|
|
|
|
|
PyMODINIT_FUNC
|
2016-05-10 07:57:54 +00:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
PyInit_pybullet(void)
|
|
|
|
#else
|
2016-04-30 18:18:54 +00:00
|
|
|
initpybullet(void)
|
2016-05-10 07:57:54 +00:00
|
|
|
#endif
|
2016-04-30 18:18:54 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
PyObject *m;
|
2016-05-10 07:57:54 +00:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
m = PyModule_Create(&moduledef);
|
|
|
|
#else
|
|
|
|
m = Py_InitModule3("pybullet",
|
|
|
|
SpamMethods, "Python bindings for Bullet");
|
|
|
|
#endif
|
|
|
|
|
2016-05-18 22:07:42 +00:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
2016-04-30 18:18:54 +00:00
|
|
|
if (m == NULL)
|
2016-05-10 07:57:54 +00:00
|
|
|
return m;
|
2016-05-18 22:07:42 +00:00
|
|
|
#else
|
|
|
|
if (m == NULL)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2016-05-10 07:57:54 +00:00
|
|
|
|
2016-05-18 22:07:42 +00:00
|
|
|
PyModule_AddIntConstant (m, "SHARED_MEMORY", eCONNECT_SHARED_MEMORY); // user read
|
2016-05-10 07:57:54 +00:00
|
|
|
PyModule_AddIntConstant (m, "DIRECT", eCONNECT_DIRECT); // user read
|
|
|
|
PyModule_AddIntConstant (m, "GUI", eCONNECT_GUI); // user read
|
2016-04-30 18:18:54 +00:00
|
|
|
|
|
|
|
SpamError = PyErr_NewException("pybullet.error", NULL, NULL);
|
|
|
|
Py_INCREF(SpamError);
|
|
|
|
PyModule_AddObject(m, "error", SpamError);
|
2016-05-10 07:57:54 +00:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
return m;
|
|
|
|
#endif
|
2016-04-30 18:18:54 +00:00
|
|
|
}
|
|
|
|
|