LuaPhysicsSetup.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. #include "LuaPhysicsSetup.h"
  2. #include "../CommonInterfaces/CommonMultiBodyBase.h"
  3. #include "../Importers/ImportURDFDemo/BulletURDFImporter.h"
  4. #include "../Importers/ImportURDFDemo/MyMultiBodyCreator.h"
  5. #include "../Importers/ImportURDFDemo/URDF2Bullet.h"
  6. struct LuaPhysicsSetup : public CommonMultiBodyBase
  7. {
  8. LuaPhysicsSetup(GUIHelperInterface* helper);
  9. virtual ~LuaPhysicsSetup();
  10. virtual void initPhysics();
  11. virtual void exitPhysics();
  12. virtual void stepSimulation(float deltaTime)
  13. {
  14. m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
  15. CommonMultiBodyBase::stepSimulation(deltaTime);
  16. }
  17. };
  18. #include "btBulletDynamicsCommon.h"
  19. #include "LinearMath/btVector3.h"
  20. #include <iostream>
  21. extern "C" {
  22. #include "lua.h"
  23. #include "lualib.h"
  24. #include "lauxlib.h"
  25. }
  26. const char* sLuaFileName = "init_physics.lua";
  27. static int upaxis = 1;
  28. //const char* sLuaFileName = "init_urdf.lua";
  29. //static int upaxis = 2;
  30. static const float scaling=0.35f;
  31. static LuaPhysicsSetup* sLuaDemo = 0;
  32. static btVector4 colors[4] =
  33. {
  34. btVector4(1,0,0,1),
  35. btVector4(0,1,0,1),
  36. btVector4(0,1,1,1),
  37. btVector4(1,1,0,1),
  38. };
  39. LuaPhysicsSetup::LuaPhysicsSetup(GUIHelperInterface* helper)
  40. :CommonMultiBodyBase(helper)
  41. {
  42. sLuaDemo = this;
  43. }
  44. LuaPhysicsSetup::~LuaPhysicsSetup()
  45. {
  46. sLuaDemo = 0;
  47. }
  48. //todo: allow to create solver, broadphase, multiple worlds etc.
  49. static int gCreateDefaultDynamicsWorld(lua_State *L)
  50. {
  51. sLuaDemo->createEmptyDynamicsWorld();
  52. btVector3 grav(0,0,0);
  53. grav[upaxis] = -10;
  54. sLuaDemo->m_dynamicsWorld->setGravity(grav);
  55. sLuaDemo->m_guiHelper->createPhysicsDebugDrawer(sLuaDemo->m_dynamicsWorld);
  56. lua_pushlightuserdata (L, sLuaDemo->m_dynamicsWorld);
  57. return 1;
  58. }
  59. static int gDeleteDynamicsWorld(lua_State *L)
  60. {
  61. return 0;
  62. }
  63. ATTRIBUTE_ALIGNED16(struct) CustomRigidBodyData
  64. {
  65. int m_graphicsInstanceIndex;
  66. };
  67. static int gCreateCubeShape(lua_State *L)
  68. {
  69. int argc = lua_gettop(L);
  70. if (argc==4)
  71. {
  72. btVector3 halfExtents(1,1,1);
  73. if (!lua_isuserdata(L,1))
  74. {
  75. std::cerr << "error: first argument to createCubeShape should be world";
  76. return 0;
  77. }
  78. //expect userdata = sLuaDemo->m_dynamicsWorld
  79. halfExtents = btVector3(lua_tonumber(L,2),lua_tonumber(L,3),lua_tonumber(L,4));
  80. btCollisionShape* colShape = new btBoxShape(halfExtents);
  81. lua_pushlightuserdata (L, colShape);
  82. return 1;
  83. } else
  84. {
  85. std::cerr << "Error: invalid number of arguments to createCubeShape, expected 4 (world,halfExtentsX,halfExtentsY,halfExtentsX) but got " << argc;
  86. }
  87. return 0;
  88. }
  89. static int gCreateSphereShape(lua_State *L)
  90. {
  91. int argc = lua_gettop(L);
  92. if (argc==2)
  93. {
  94. btVector3 halfExtents(1,1,1);
  95. if (!lua_isuserdata(L,1))
  96. {
  97. std::cerr << "error: first argument to createSphereShape should be world";
  98. return 0;
  99. }
  100. //expect userdata = sLuaDemo->m_dynamicsWorld
  101. btScalar radius = lua_tonumber(L,2);
  102. btCollisionShape* colShape = new btSphereShape(radius);
  103. lua_pushlightuserdata (L, colShape);
  104. return 1;
  105. } else
  106. {
  107. std::cerr << "Error: invalid number of arguments to createSphereShape, expected 2 (world,radius) but got " << argc;
  108. }
  109. return 0;
  110. }
  111. int luaL_returnlen(lua_State* L, int index)
  112. {
  113. lua_len(L, index);
  114. int len = lua_tointeger(L,-1);
  115. lua_pop(L, 1);
  116. return len;
  117. }
  118. btVector3 getLuaVectorArg(lua_State* L, int index)
  119. {
  120. btVector3 pos(0,0,0);
  121. int sz = luaL_returnlen(L, index); // get size of table
  122. {
  123. lua_rawgeti(L, index, 1); // push t[i]
  124. pos[0] = lua_tonumber(L,-1);
  125. lua_pop(L, 1);
  126. lua_rawgeti(L, index, 2); // push t[i]
  127. pos[1] = lua_tonumber(L,-1);
  128. lua_pop(L, 1);
  129. lua_rawgeti(L, index, 3); // push t[i]
  130. pos[2] = lua_tonumber(L,-1);
  131. lua_pop(L, 1);
  132. }
  133. return pos;
  134. }
  135. btQuaternion getLuaQuaternionArg(lua_State* L, int index)
  136. {
  137. btQuaternion orn(0,0,0,1);
  138. int sz = luaL_returnlen(L, index); // get size of table
  139. {
  140. lua_rawgeti(L, index, 1); // push t[i]
  141. orn[0] = lua_tonumber(L,-1);
  142. lua_pop(L, 1);
  143. lua_rawgeti(L, index, 2); // push t[i]
  144. orn[1] = lua_tonumber(L,-1);
  145. lua_pop(L, 1);
  146. lua_rawgeti(L, index, 3); // push t[i]
  147. orn[2] = lua_tonumber(L,-1);
  148. lua_pop(L, 1);
  149. lua_rawgeti(L, index, 4); // push t[i]
  150. orn[3] = lua_tonumber(L,-1);
  151. lua_pop(L, 1);
  152. }
  153. return orn;
  154. }
  155. static int gLoadMultiBodyFromUrdf(lua_State *L)
  156. {
  157. int argc = lua_gettop(L);
  158. if (argc==4)
  159. {
  160. if (!lua_isuserdata(L,1))
  161. {
  162. std::cerr << "error: first argument to b3CreateRigidbody should be world";
  163. return 0;
  164. }
  165. luaL_checktype(L,3, LUA_TTABLE);
  166. btVector3 pos = getLuaVectorArg(L,3);
  167. btQuaternion orn = getLuaQuaternionArg(L,4);
  168. btDiscreteDynamicsWorld* world = (btDiscreteDynamicsWorld*) lua_touserdata(L,1);
  169. if (world != sLuaDemo->m_dynamicsWorld)
  170. {
  171. std::cerr << "error: first argument expected to be a world";
  172. return 0;
  173. }
  174. const char* fileName = lua_tostring(L,2);
  175. #if 1
  176. BulletURDFImporter u2b(sLuaDemo->m_guiHelper);
  177. bool loadOk = u2b.loadURDF(fileName);
  178. if (loadOk)
  179. {
  180. b3Printf("loaded %s OK!", fileName);
  181. btTransform tr;
  182. tr.setIdentity();
  183. tr.setOrigin(pos);
  184. tr.setRotation(orn);
  185. int rootLinkIndex = u2b.getRootLinkIndex();
  186. // printf("urdf root link index = %d\n",rootLinkIndex);
  187. MyMultiBodyCreator creation(sLuaDemo->m_guiHelper);
  188. bool m_useMultiBody = true;
  189. ConvertURDF2Bullet(u2b,creation, tr,sLuaDemo->m_dynamicsWorld,m_useMultiBody,u2b.getPathPrefix());
  190. btMultiBody* mb = creation.getBulletMultiBody();
  191. if (mb)
  192. {
  193. lua_pushlightuserdata (L, mb);
  194. return 1;
  195. }
  196. } else
  197. {
  198. b3Printf("can't find %s",fileName);
  199. }
  200. #endif
  201. }
  202. return 0;
  203. }
  204. static int gCreateRigidBody (lua_State *L)
  205. {
  206. int argc = lua_gettop(L);
  207. if (argc==5)
  208. {
  209. btTransform startTransform;
  210. startTransform.setIdentity();
  211. if (!lua_isuserdata(L,1))
  212. {
  213. std::cerr << "error: first argument to b3CreateRigidbody should be world";
  214. return 0;
  215. }
  216. btDiscreteDynamicsWorld* world = (btDiscreteDynamicsWorld*) lua_touserdata(L,1);
  217. if (world != sLuaDemo->m_dynamicsWorld)
  218. {
  219. std::cerr << "error: first argument expected to be a world";
  220. return 0;
  221. }
  222. if (!lua_isuserdata(L,2))
  223. {
  224. std::cerr << "error: second argument to b3CreateRigidbody should be collision shape";
  225. return 0;
  226. }
  227. btScalar mass = lua_tonumber(L,3);
  228. luaL_checktype(L,4, LUA_TTABLE);
  229. btVector3 pos = getLuaVectorArg(L,4);
  230. btQuaternion orn = getLuaQuaternionArg(L,5);
  231. btCollisionShape* colShape = (btCollisionShape* )lua_touserdata(L,2);
  232. //expect userdata = sLuaDemo->m_dynamicsWorld
  233. btVector3 inertia(0,0,0);
  234. if (mass)
  235. {
  236. colShape->calculateLocalInertia(mass,inertia);
  237. }
  238. btRigidBody* body = new btRigidBody(mass,0,colShape,inertia);
  239. body->getWorldTransform().setOrigin(pos);
  240. body->getWorldTransform().setRotation(orn);
  241. world->addRigidBody(body);
  242. lua_pushlightuserdata (L, body);
  243. return 1;
  244. } else
  245. {
  246. std::cerr << "Error: invalid number of arguments to createRigidBody, expected 5 (world,shape,mass,pos,orn) but got " << argc;
  247. }
  248. return 0;
  249. }
  250. static int gSetBodyPosition(lua_State *L)
  251. {
  252. int argc = lua_gettop(L);
  253. if (argc==3)
  254. {
  255. if (!lua_isuserdata(L,1))
  256. {
  257. std::cerr << "error: first argument needs to be a world";
  258. return 0;
  259. }
  260. if (!lua_isuserdata(L,2))
  261. {
  262. std::cerr << "error: second argument needs to be a body";
  263. return 0;
  264. }
  265. btRigidBody* body = (btRigidBody*)lua_touserdata(L,2);
  266. btVector3 pos = getLuaVectorArg(L,3);
  267. btTransform& tr = body ->getWorldTransform();
  268. tr.setOrigin(pos);
  269. body->setWorldTransform(tr);
  270. } else
  271. {
  272. std::cerr << "error: setBodyPosition expects 6 arguments like setBodyPosition(world,body,0,1,0)";
  273. }
  274. return 0;
  275. }
  276. static int gSetBodyOrientation(lua_State *L)
  277. {
  278. int argc = lua_gettop(L);
  279. if (argc==3)
  280. {
  281. if (!lua_isuserdata(L,1))
  282. {
  283. std::cerr << "error: first argument needs to be a world";
  284. return 0;
  285. }
  286. if (!lua_isuserdata(L,2))
  287. {
  288. std::cerr << "error: second argument needs to be a body";
  289. return 0;
  290. }
  291. btRigidBody* body = (btRigidBody*)lua_touserdata(L,2);
  292. btQuaternion orn = getLuaQuaternionArg(L,3);
  293. btTransform& tr = body ->getWorldTransform();
  294. tr.setRotation(orn);
  295. body->setWorldTransform(tr);
  296. } else
  297. {
  298. std::cerr << "error: setBodyOrientation expects 3 arguments like setBodyOrientation(world,body,orn)";
  299. }
  300. return 0;
  301. }
  302. //b3CreateConvexShape(world, points)
  303. //b3CreateHingeConstraint(world,bodyA,bodyB,...)
  304. static void report_errors(lua_State *L, int status)
  305. {
  306. if ( status!=0 ) {
  307. std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
  308. lua_pop(L, 1); // remove error message
  309. }
  310. }
  311. void LuaPhysicsSetup::initPhysics()
  312. {
  313. m_guiHelper->setUpAxis(upaxis);
  314. const char* prefix[]={"./","./data/","../data/","../../data/","../../../data/","../../../../data/"};
  315. int numPrefixes = sizeof(prefix)/sizeof(const char*);
  316. char relativeFileName[1024];
  317. FILE* f=0;
  318. int result = 0;
  319. for (int i=0;!f && i<numPrefixes;i++)
  320. {
  321. sprintf(relativeFileName,"%s%s",prefix[i],sLuaFileName);
  322. f = fopen(relativeFileName,"rb");
  323. }
  324. if (f)
  325. {
  326. fclose(f);
  327. lua_State *L = luaL_newstate();
  328. luaopen_io(L); // provides io.*
  329. luaopen_base(L);
  330. luaopen_table(L);
  331. luaopen_string(L);
  332. luaopen_math(L);
  333. //luaopen_package(L);
  334. luaL_openlibs(L);
  335. // make my_function() available to Lua programs
  336. lua_register(L, "createDefaultDynamicsWorld", gCreateDefaultDynamicsWorld);
  337. lua_register(L, "deleteDynamicsWorld", gDeleteDynamicsWorld);
  338. lua_register(L, "createCubeShape", gCreateCubeShape);
  339. lua_register(L, "createSphereShape", gCreateSphereShape);
  340. lua_register(L, "loadMultiBodyFromUrdf",gLoadMultiBodyFromUrdf);
  341. lua_register(L, "createRigidBody", gCreateRigidBody);
  342. lua_register(L, "setBodyPosition", gSetBodyPosition);
  343. lua_register(L, "setBodyOrientation", gSetBodyOrientation);
  344. int s = luaL_loadfile(L, relativeFileName);
  345. if ( s==0 ) {
  346. // execute Lua program
  347. s = lua_pcall(L, 0, LUA_MULTRET, 0);
  348. }
  349. report_errors(L, s);
  350. lua_close(L);
  351. } else
  352. {
  353. b3Error("Cannot find Lua file%s\n",sLuaFileName);
  354. }
  355. }
  356. void LuaPhysicsSetup::exitPhysics()
  357. {
  358. CommonMultiBodyBase::exitPhysics();
  359. }
  360. class CommonExampleInterface* LuaDemoCreateFunc(struct CommonExampleOptions& options)
  361. {
  362. return new LuaPhysicsSetup(options.m_guiHelper);
  363. }