LuaPhysicsSetup.cpp 9.8 KB

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