├── tests ├── __init__.py ├── unit │ ├── __init__.py │ └── test_dart_loader.py ├── regression │ ├── __init__.py │ ├── test_issue81_get_joints.py │ └── test_get_shape.py ├── comprehensive │ ├── __init__.py │ └── test_collision_detector.py ├── assets │ ├── urdf │ │ ├── invalid.urdf │ │ ├── invalid_mesh.stl │ │ ├── KR5 │ │ │ ├── meshes │ │ │ │ ├── palm.STL │ │ │ │ ├── bicep.STL │ │ │ │ ├── elbow.STL │ │ │ │ ├── wrist.STL │ │ │ │ ├── base_link.STL │ │ │ │ ├── forearm.STL │ │ │ │ └── shoulder.STL │ │ │ ├── ground.urdf │ │ │ └── KR5 sixx R650.urdf │ │ ├── wam │ │ │ ├── meshes │ │ │ │ ├── wam │ │ │ │ │ ├── wam1.STL │ │ │ │ │ ├── wam2.STL │ │ │ │ │ ├── wam3.STL │ │ │ │ │ ├── wam4.STL │ │ │ │ │ ├── wam5.STL │ │ │ │ │ ├── wam6.STL │ │ │ │ │ ├── wam7.STL │ │ │ │ │ ├── wam_base.STL │ │ │ │ │ ├── wam1_collision.STL │ │ │ │ │ ├── wam2_collision.STL │ │ │ │ │ ├── wam3_collision.STL │ │ │ │ │ ├── wam4_collision.STL │ │ │ │ │ ├── wam5_collision.STL │ │ │ │ │ ├── wam6_collision.STL │ │ │ │ │ ├── wam7_collision.STL │ │ │ │ │ └── wam_base_collision.STL │ │ │ │ └── images │ │ │ │ │ ├── lpu_128x.jpg │ │ │ │ │ ├── forearm_256x.jpg │ │ │ │ │ ├── base_gray_128x.jpg │ │ │ │ │ ├── shoulder_256x.jpg │ │ │ │ │ ├── upperarm_128x.jpg │ │ │ │ │ └── wrist_yaw_128x.jpg │ │ │ └── wam.urdf │ │ ├── drchubo │ │ │ ├── meshes │ │ │ │ ├── convhull_LF1.stl │ │ │ │ ├── convhull_LF2.stl │ │ │ │ ├── convhull_LF3.stl │ │ │ │ ├── convhull_NK2.stl │ │ │ │ ├── convhull_RF1.stl │ │ │ │ ├── convhull_RF2.stl │ │ │ │ ├── convhull_RF3.stl │ │ │ │ ├── convhull_LAP_merged.stl │ │ │ │ ├── convhull_LAR_merged.stl │ │ │ │ ├── convhull_LEP_merged.stl │ │ │ │ ├── convhull_LHP_merged.stl │ │ │ │ ├── convhull_LHR_merged.stl │ │ │ │ ├── convhull_LHY_merged.stl │ │ │ │ ├── convhull_LKP_merged.stl │ │ │ │ ├── convhull_LSP_merged.stl │ │ │ │ ├── convhull_LSR_merged.stl │ │ │ │ ├── convhull_LSY_merged.stl │ │ │ │ ├── convhull_LWP_merged.stl │ │ │ │ ├── convhull_LWR_merged.stl │ │ │ │ ├── convhull_LWY_merged.stl │ │ │ │ ├── convhull_NK1_merged.stl │ │ │ │ ├── convhull_NKY_merged.stl │ │ │ │ ├── convhull_RAP_merged.stl │ │ │ │ ├── convhull_RAR_merged.stl │ │ │ │ ├── convhull_REP_merged.stl │ │ │ │ ├── convhull_RHP_merged.stl │ │ │ │ ├── convhull_RHR_merged.stl │ │ │ │ ├── convhull_RHY_merged.stl │ │ │ │ ├── convhull_RKP_merged.stl │ │ │ │ ├── convhull_RSP_merged.stl │ │ │ │ ├── convhull_RSR_merged.stl │ │ │ │ ├── convhull_RSY_merged.stl │ │ │ │ ├── convhull_RWP_merged.stl │ │ │ │ ├── convhull_RWR_merged.stl │ │ │ │ ├── convhull_RWY_merged.stl │ │ │ │ ├── convhull_TSY_merged.stl │ │ │ │ └── convhull_Torso_merged.stl │ │ │ ├── CMakeLists.txt │ │ │ └── package.xml │ │ ├── invalid_mesh.urdf │ │ ├── missing_mesh.urdf │ │ ├── missing_package.urdf │ │ ├── testWorld.urdf │ │ ├── primitive_geometry.urdf │ │ ├── issue838.urdf │ │ ├── ground.urdf │ │ └── joint_properties.urdf │ └── skel │ │ └── cubes.skel ├── util.py └── CMakeLists.txt ├── examples ├── __init__.py ├── wam │ ├── __init__.py │ ├── assets │ │ ├── meshes │ │ │ ├── wam │ │ │ │ ├── wam1.STL │ │ │ │ ├── wam2.STL │ │ │ │ ├── wam3.STL │ │ │ │ ├── wam4.STL │ │ │ │ ├── wam5.STL │ │ │ │ ├── wam6.STL │ │ │ │ ├── wam7.STL │ │ │ │ ├── wam_base.STL │ │ │ │ ├── wam1_collision.STL │ │ │ │ ├── wam2_collision.STL │ │ │ │ ├── wam3_collision.STL │ │ │ │ ├── wam4_collision.STL │ │ │ │ ├── wam5_collision.STL │ │ │ │ ├── wam6_collision.STL │ │ │ │ ├── wam7_collision.STL │ │ │ │ ├── wam_base_collision.STL │ │ │ │ └── wam2.dae │ │ │ └── images │ │ │ │ ├── lpu_128x.jpg │ │ │ │ ├── base_gray_128x.jpg │ │ │ │ ├── forearm_256x.jpg │ │ │ │ ├── shoulder_256x.jpg │ │ │ │ ├── upperarm_128x.jpg │ │ │ │ └── wrist_yaw_128x.jpg │ │ └── wam.urdf │ ├── main_vispy.py │ └── main_opengl.py ├── rigid_cubes │ ├── __init__.py │ ├── main_vispy.py │ ├── main_opengl.py │ └── cubes.skel └── rigid_cubes_offscreen │ ├── __init__.py │ ├── main_opengl.py │ ├── main_vispy.py │ └── cubes.skel ├── src ├── generated │ └── .gitignore ├── Skeleton.cpp ├── template_registry.cpp ├── BodyNode.cpp └── skel_parser.cpp ├── cmake └── config.h.in ├── .ci ├── install.sh ├── docker │ ├── env.list │ ├── ubuntu-bionic │ └── ubuntu-xenial ├── install_macos.sh ├── script.sh └── install_linux.sh ├── CHANGELOG.md ├── setup.cfg ├── include └── dartpy │ ├── types.h │ ├── BodyNode.h │ ├── Skeleton.h │ ├── collections.h │ ├── metaprogramming.h │ ├── get_signature.h │ ├── detail │ ├── JointAndNodeRegistry.h │ └── JointTemplateMultiplexer.h │ ├── util.h │ ├── pointers.h │ └── template_registry.h ├── chimera ├── chimera.cpp └── templates │ ├── variable.mstch.cpp │ ├── enum.mstch.cpp │ ├── module.mstch.cpp │ ├── function.mstch.cpp │ └── cxx_record.mstch.cpp ├── test_resources └── r2d2.urdf ├── package.xml ├── .travis.yml ├── LICENSE ├── .gitignore ├── setup.py ├── README.md ├── CMakeLists.txt └── scripts └── grasp_fuze_bottle.py /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/unit/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/wam/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/regression/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/rigid_cubes/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/comprehensive/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/rigid_cubes_offscreen/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/generated/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | sources.txt 3 | -------------------------------------------------------------------------------- /tests/assets/urdf/invalid.urdf: -------------------------------------------------------------------------------- 1 | This is not a valid URDF file. 2 | -------------------------------------------------------------------------------- /tests/assets/urdf/invalid_mesh.stl: -------------------------------------------------------------------------------- 1 | This is not a valid STL file. 2 | -------------------------------------------------------------------------------- /tests/assets/urdf/KR5/meshes/palm.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/KR5/meshes/palm.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam1.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam1.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam2.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam2.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam3.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam3.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam4.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam4.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam5.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam5.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam6.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam6.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam7.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam7.STL -------------------------------------------------------------------------------- /tests/assets/urdf/KR5/meshes/bicep.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/KR5/meshes/bicep.STL -------------------------------------------------------------------------------- /tests/assets/urdf/KR5/meshes/elbow.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/KR5/meshes/elbow.STL -------------------------------------------------------------------------------- /tests/assets/urdf/KR5/meshes/wrist.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/KR5/meshes/wrist.STL -------------------------------------------------------------------------------- /tests/assets/urdf/KR5/meshes/base_link.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/KR5/meshes/base_link.STL -------------------------------------------------------------------------------- /tests/assets/urdf/KR5/meshes/forearm.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/KR5/meshes/forearm.STL -------------------------------------------------------------------------------- /tests/assets/urdf/KR5/meshes/shoulder.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/KR5/meshes/shoulder.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam1.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam1.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam2.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam2.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam3.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam3.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam4.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam4.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam5.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam5.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam6.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam6.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam7.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam7.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam_base.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam_base.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/images/lpu_128x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/images/lpu_128x.jpg -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam_base.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam_base.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam1_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam1_collision.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam2_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam2_collision.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam3_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam3_collision.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam4_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam4_collision.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam5_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam5_collision.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam6_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam6_collision.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam7_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam7_collision.STL -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LF1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LF1.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LF2.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LF2.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LF3.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LF3.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_NK2.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_NK2.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RF1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RF1.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RF2.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RF2.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RF3.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RF3.stl -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/images/lpu_128x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/images/lpu_128x.jpg -------------------------------------------------------------------------------- /examples/wam/assets/meshes/images/base_gray_128x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/images/base_gray_128x.jpg -------------------------------------------------------------------------------- /examples/wam/assets/meshes/images/forearm_256x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/images/forearm_256x.jpg -------------------------------------------------------------------------------- /examples/wam/assets/meshes/images/shoulder_256x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/images/shoulder_256x.jpg -------------------------------------------------------------------------------- /examples/wam/assets/meshes/images/upperarm_128x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/images/upperarm_128x.jpg -------------------------------------------------------------------------------- /examples/wam/assets/meshes/images/wrist_yaw_128x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/images/wrist_yaw_128x.jpg -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/images/forearm_256x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/images/forearm_256x.jpg -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam1_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam1_collision.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam2_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam2_collision.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam3_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam3_collision.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam4_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam4_collision.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam5_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam5_collision.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam6_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam6_collision.STL -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam7_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam7_collision.STL -------------------------------------------------------------------------------- /examples/wam/assets/meshes/wam/wam_base_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/examples/wam/assets/meshes/wam/wam_base_collision.STL -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(drchubo) 3 | find_package(catkin REQUIRED) 4 | catkin_package() 5 | 6 | -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/images/base_gray_128x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/images/base_gray_128x.jpg -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/images/shoulder_256x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/images/shoulder_256x.jpg -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/images/upperarm_128x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/images/upperarm_128x.jpg -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/images/wrist_yaw_128x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/images/wrist_yaw_128x.jpg -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LAP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LAP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LAR_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LAR_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LEP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LEP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LHP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LHP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LHR_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LHR_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LHY_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LHY_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LKP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LKP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LSP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LSP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LSR_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LSR_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LSY_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LSY_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LWP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LWP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LWR_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LWR_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_LWY_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_LWY_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_NK1_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_NK1_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_NKY_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_NKY_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RAP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RAP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RAR_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RAR_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_REP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_REP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RHP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RHP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RHR_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RHR_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RHY_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RHY_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RKP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RKP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RSP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RSP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RSR_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RSR_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RSY_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RSY_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RWP_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RWP_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RWR_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RWR_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_RWY_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_RWY_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_TSY_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_TSY_merged.stl -------------------------------------------------------------------------------- /tests/assets/urdf/wam/meshes/wam/wam_base_collision.STL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/wam/meshes/wam/wam_base_collision.STL -------------------------------------------------------------------------------- /cmake/config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef DARTPY_CONFIG_H_ 2 | #define DARTPY_CONFIG_H_ 3 | 4 | #cmakedefine DARTPY_HAS_STD_SHARED_GET_POINTER 5 | 6 | #endif // ifndef DARTPY_CONFIG_H_ 7 | -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/meshes/convhull_Torso_merged.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/personalrobotics/dartpy/HEAD/tests/assets/urdf/drchubo/meshes/convhull_Torso_merged.stl -------------------------------------------------------------------------------- /.ci/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | 4 | if [ "$TRAVIS_OS_NAME" = "linux" ]; then '.ci/install_linux.sh'; fi 5 | if [ "$TRAVIS_OS_NAME" = "osx" ]; then '.ci/install_macos.sh'; fi 6 | -------------------------------------------------------------------------------- /.ci/docker/env.list: -------------------------------------------------------------------------------- 1 | TRAVIS_BRANCH 2 | TRAVIS_BUILD_DIR 3 | TRAVIS_OS_NAME 4 | TRAVIS_PULL_REQUEST 5 | 6 | BUILD_NAME 7 | BUILD_TYPE 8 | CODECOV 9 | COMPILER 10 | PYTHON_VERSION 11 | SUDO 12 | -------------------------------------------------------------------------------- /.ci/install_macos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -x 3 | # e option is disabled for now 4 | 5 | brew update > /dev/null 6 | 7 | # TODO: the list isn't complete 8 | brew install dartsim 9 | brew install boost 10 | brew install boost-python3 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## dartpy 0 (prerelease) 2 | 3 | ### 0.0.3 (20XX-XX-XX) 4 | 5 | * Added skel file parsing functions: [#64](https://github.com/personalrobotics/dartpy/pull/64) 6 | 7 | ### 0.0.2 (2018-05-23) 8 | 9 | * Updated C++ DART version to 6.5.0 10 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | 3 | # This flag says that the code is written to work on both Python 2 and Python 4 | # 3. If at all possible, it is good practice to do this so that we do not need 5 | # to generate wheels for each Python version that you support. 6 | 7 | universal=1 -------------------------------------------------------------------------------- /tests/assets/urdf/invalid_mesh.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/assets/urdf/missing_mesh.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/assets/urdf/missing_package.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/assets/urdf/testWorld.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/assets/urdf/primitive_geometry.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/assets/urdf/drchubo/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | drchubo 4 | 0.0.1 5 | The drchubo package 6 | Robert W. Ellenberg 7 | BSD 8 | catkin 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /include/dartpy/types.h: -------------------------------------------------------------------------------- 1 | #ifndef DARTPY_TYPES_H_ 2 | #define DARTPY_TYPES_H_ 3 | 4 | namespace dart { 5 | namespace python { 6 | 7 | struct JointType { 8 | enum Enum { 9 | PRISMATIC, 10 | REVOLUTE, 11 | SCREW, 12 | WELD, 13 | UNIVERSAL, 14 | BALL, 15 | EULER, 16 | PLANAR, 17 | TRANSLATIONAL, 18 | FREE, 19 | }; 20 | }; 21 | 22 | } 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /chimera/chimera.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | // #include 4 | #include 5 | #include 6 | //#include TODO: make this optional 7 | #include 8 | #include 9 | #include 10 | #include 11 | -------------------------------------------------------------------------------- /examples/rigid_cubes/main_vispy.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import dart 5 | from dart.gui.vispy.viewer import Viewer 6 | 7 | 8 | def main(): 9 | file_path = os.path.join(os.path.dirname(__file__), 'cubes.skel') 10 | world = dart.utils.skel.readWorld(file_path) 11 | # world = World.create() 12 | viewer = Viewer(world) 13 | 14 | if sys.flags.interactive == 0: 15 | viewer.app.run() 16 | 17 | 18 | if __name__ == '__main__': 19 | main() 20 | -------------------------------------------------------------------------------- /examples/rigid_cubes_offscreen/main_opengl.py: -------------------------------------------------------------------------------- 1 | import dartpy as dart 2 | from OpenGL.GLUT import * 3 | from dartpy.gui import SimWindow 4 | 5 | 6 | def main(): 7 | file_path = os.path.join(os.path.dirname(__file__), 'cubes.skel') 8 | world = dart.utils.skel.readWorld(file_path) 9 | 10 | window = SimWindow() 11 | window.setWorld(world) 12 | 13 | glutInit(sys.argv) 14 | window.initWindow(640, 480, "Rigid Cubes") 15 | glutMainLoop() 16 | 17 | 18 | if __name__ == '__main__': 19 | main() 20 | -------------------------------------------------------------------------------- /examples/rigid_cubes/main_opengl.py: -------------------------------------------------------------------------------- 1 | import dartpy as dart 2 | from OpenGL.GLUT import * 3 | from dartpy.gui import SimWindow 4 | 5 | 6 | def main(): 7 | file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cubes.skel') 8 | world = dart.utils.skel.readWorld(file_path) 9 | 10 | window = SimWindow() 11 | window.setWorld(world) 12 | 13 | glutInit(sys.argv) 14 | window.initWindow(640, 480, "Rigid Cubes") 15 | glutMainLoop() 16 | 17 | 18 | if __name__ == '__main__': 19 | main() 20 | -------------------------------------------------------------------------------- /include/dartpy/BodyNode.h: -------------------------------------------------------------------------------- 1 | #ifndef DARTPY_BODYNODE_H_ 2 | #define DARTPY_BODYNODE_H_ 3 | #include 4 | #include 5 | 6 | namespace dart { 7 | namespace python { 8 | 9 | dart::dynamics::Joint* BodyNode_moveTo2( 10 | dart::dynamics::BodyNode* _bodyNode, 11 | boost::python::object _jointType, 12 | dart::dynamics::BodyNode* _newParent, 13 | boost::python::object _jointProperties); 14 | 15 | } // namespace python 16 | } // namespace dart 17 | 18 | #endif // ifndef DARTPY_BODYNODE_H_ 19 | -------------------------------------------------------------------------------- /tests/util.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | import os 3 | import os.path 4 | 5 | 6 | def get_path_to_this_file(): 7 | return inspect.getfile(inspect.currentframe()) 8 | 9 | 10 | def get_asset_path(rel_path, check_existing=False): 11 | if rel_path.startswith("/"): 12 | full_path = rel_path 13 | else: 14 | full_path = os.path.join(os.path.dirname(__file__), "assets", rel_path) 15 | if check_existing and not os.path.exists(full_path): 16 | raise IOError("File %s does not exist" % full_path) 17 | 18 | return full_path 19 | -------------------------------------------------------------------------------- /chimera/templates/variable.mstch.cpp: -------------------------------------------------------------------------------- 1 | {{{header}}} 2 | {{#includes}} 3 | #include <{{{.}}}> 4 | {{/includes}} 5 | {{{precontent}}} 6 | #include 7 | #include 8 | 9 | /* postinclude */ 10 | 11 | void {{variable.mangled_name}}() 12 | { 13 | ::boost::python::object parent_object(::boost::python::scope(){{! 14 | }}{{#variable.scope}}{{#name}}.attr("{{name}}"){{/name}}{{/variable.scope}}); 15 | ::boost::python::scope parent_scope(parent_object); 16 | 17 | ::boost::python::scope().attr("{{variable.name}}") = {{{variable.qualified_name}}}; 18 | } 19 | {{{postcontent}}} 20 | {{{footer}}} 21 | -------------------------------------------------------------------------------- /include/dartpy/Skeleton.h: -------------------------------------------------------------------------------- 1 | #ifndef DARTPY_SKELETON_H_ 2 | #define DARTPY_SKELETON_H_ 3 | #include 4 | #include 5 | 6 | namespace dart { 7 | namespace python { 8 | 9 | boost::python::object Skeleton_createJointAndBodyNodePair( 10 | dart::dynamics::Skeleton* _skeleton, 11 | boost::python::object _jointType, 12 | boost::python::object _bodyType, 13 | dart::dynamics::BodyNode* _parent, 14 | boost::python::object _jointPropertiesPython, 15 | boost::python::object _bodyPropertiesPython); 16 | 17 | } // namespace python 18 | } // namespace dart 19 | 20 | #endif // ifndef DARTPY_SKELETON_H_ 21 | -------------------------------------------------------------------------------- /.ci/docker/ubuntu-bionic: -------------------------------------------------------------------------------- 1 | FROM ubuntu:bionic 2 | 3 | RUN apt-get -y update 4 | RUN apt-get install -y software-properties-common 5 | RUN add-apt-repository ppa:dartsim/ppa -y 6 | RUN add-apt-repository ppa:personalrobotics/ppa -y 7 | RUN apt-get -y update 8 | RUN apt-get install -y \ 9 | sudo \ 10 | build-essential \ 11 | cmake \ 12 | pkg-config \ 13 | wget \ 14 | git \ 15 | libboost-dev \ 16 | libboost-python-dev \ 17 | libdart6-all-dev \ 18 | python3-pip \ 19 | python3-dartpy \ 20 | python3-dev \ 21 | python3-numpy \ 22 | python3-boost-numpy-eigen \ 23 | chimera 24 | RUN pip3 install -U pytest 25 | -------------------------------------------------------------------------------- /chimera/templates/enum.mstch.cpp: -------------------------------------------------------------------------------- 1 | {{{header}}} 2 | {{#includes}} 3 | #include <{{{.}}}> 4 | {{/includes}} 5 | {{{precontent}}} 6 | #include 7 | #include 8 | 9 | /* postinclude */ 10 | 11 | void {{enum.mangled_name}}() 12 | { 13 | ::boost::python::object parent_object(::boost::python::scope(){{! 14 | }}{{#enum.scope}}{{#name}}.attr("{{name}}"){{/name}}{{/enum.scope}}); 15 | ::boost::python::scope parent_scope(parent_object); 16 | 17 | ::boost::python::enum_<{{{enum.type}}}>("{{enum.name}}"){{#enum.values}} 18 | .value("{{name}}", {{{qualified_name}}}){{/enum.values}} 19 | ; 20 | } 21 | {{{postcontent}}} 22 | {{{footer}}} 23 | -------------------------------------------------------------------------------- /.ci/docker/ubuntu-xenial: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | 3 | RUN apt-get -y update 4 | RUN apt-get install -y software-properties-common 5 | RUN add-apt-repository ppa:dartsim/ppa -y 6 | RUN add-apt-repository ppa:personalrobotics/ppa -y 7 | RUN apt-get -y update 8 | RUN apt-get install -y \ 9 | sudo \ 10 | build-essential \ 11 | cmake \ 12 | pkg-config \ 13 | wget \ 14 | git \ 15 | libboost-dev \ 16 | libboost-python-dev \ 17 | libboost-python-numpy-dev \ 18 | libdart6-all-dev \ 19 | python3-pip \ 20 | python3-dartpy \ 21 | python3-dev \ 22 | python3-numpy \ 23 | python3-boost-numpy-eigen \ 24 | chimera 25 | RUN pip3 install -U pytest 26 | -------------------------------------------------------------------------------- /tests/regression/test_issue81_get_joints.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import dartpy 3 | 4 | from tests.util import get_asset_path 5 | 6 | 7 | def test_shape_is_accessible_from_shape_frame(): 8 | world = dartpy.utils.skel.readWorld(get_asset_path('skel/cubes.skel')) 9 | assert world is not None 10 | assert hasattr(world, 'getNumSkeletons') 11 | assert world.getNumSkeletons() > 0 12 | 13 | assert hasattr(world, 'getSkeleton') 14 | skel = world.getSkeleton(0) 15 | assert skel is not None 16 | 17 | assert hasattr(skel, 'getJoints') 18 | joints = skel.getJoints() 19 | assert len(joints) is 1 20 | 21 | 22 | if __name__ == "__main__": 23 | pytest.main() 24 | -------------------------------------------------------------------------------- /tests/comprehensive/test_collision_detector.py: -------------------------------------------------------------------------------- 1 | import platform 2 | 3 | import pytest 4 | from dartpy.utils import DartLoader 5 | from dartpy.simulation import World 6 | 7 | from tests.util import get_asset_path 8 | 9 | 10 | def test_parse_joint_properties(): 11 | loader = DartLoader() 12 | robot = loader.parseSkeleton(get_asset_path('urdf/joint_properties.urdf')) 13 | assert robot is not None 14 | 15 | world = World.create() 16 | world.addSkeleton(robot) 17 | 18 | cs = world.getConstraintSolver() 19 | assert cs is not None 20 | 21 | cd = cs.getCollisionDetector() 22 | assert cd is not None 23 | 24 | if __name__ == "__main__": 25 | pytest.main() 26 | -------------------------------------------------------------------------------- /.ci/script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | 4 | mkdir build 5 | cd build 6 | if [ "$TRAVIS_OS_NAME" = "linux" ]; then 7 | cmake .. -DDARTPY_PYTHON_VERSION=$PYTHON_VERSION 8 | fi 9 | 10 | if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$TRAVIS_BRANCH" != "*-binding" ]; then 11 | make binding 12 | fi 13 | 14 | # Don't actually build dartpy because the build time exceeds Travis CI time limit. 15 | # make -j4 16 | # $SUDO make install 17 | 18 | if [ "$TRAVIS_OS_NAME" = "linux" ]; then 19 | # Run pytest for Python tests of dartpy 20 | which pytest 21 | pytest --version 22 | make pytest 23 | 24 | cd $TRAVIS_BUILD_DIR 25 | 26 | # Install dartpy as package name "dart" 27 | $SUDO pip3 install -e . 28 | fi 29 | -------------------------------------------------------------------------------- /examples/wam/main_vispy.py: -------------------------------------------------------------------------------- 1 | from OpenGL.GLUT import * 2 | from dartpy.simulation import World 3 | from dartpy.utils import DartLoader 4 | 5 | from dart.gui.vispy.viewer import Viewer 6 | 7 | 8 | def main(): 9 | root_path = os.path.join(os.path.dirname(__file__), 'assets') 10 | file_path = os.path.join(root_path, 'wam.urdf') 11 | urdfLoader = DartLoader() 12 | urdfLoader.addPackageDirectory("herb_description", root_path) 13 | wam = urdfLoader.parseSkeleton(file_path) 14 | 15 | world = World.create() 16 | world.addSkeleton(wam) 17 | 18 | viewer = Viewer(world) 19 | 20 | if sys.flags.interactive == 0: 21 | viewer.app.run() 22 | 23 | 24 | if __name__ == '__main__': 25 | main() 26 | -------------------------------------------------------------------------------- /examples/wam/main_opengl.py: -------------------------------------------------------------------------------- 1 | from OpenGL.GLUT import * 2 | from dartpy.gui import SimWindow 3 | from dartpy.simulation import World 4 | from dartpy.utils import DartLoader 5 | 6 | 7 | def main(): 8 | root_path = os.path.join(os.path.dirname(__file__), 'assets') 9 | file_path = os.path.join(root_path, 'wam.urdf') 10 | urdfLoader = DartLoader() 11 | urdfLoader.addPackageDirectory("herb_description", root_path) 12 | wam = urdfLoader.parseSkeleton(file_path) 13 | 14 | world = World.create() 15 | world.addSkeleton(wam) 16 | 17 | window = SimWindow() 18 | window.setWorld(world) 19 | 20 | glutInit(sys.argv) 21 | window.initWindow(640, 480, "Rigid Cubes") 22 | glutMainLoop() 23 | 24 | 25 | if __name__ == '__main__': 26 | main() 27 | -------------------------------------------------------------------------------- /src/Skeleton.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace dart { 5 | namespace python { 6 | 7 | //============================================================================== 8 | boost::python::object Skeleton_createJointAndBodyNodePair( 9 | dart::dynamics::Skeleton* _skeleton, 10 | boost::python::object _jointType, 11 | boost::python::object _bodyType, 12 | dart::dynamics::BodyNode* _parent, 13 | boost::python::object _jointPropertiesPython, 14 | boost::python::object _bodyPropertiesPython) 15 | { 16 | return JointAndNodeTemplateRegistry 17 | ::mSkeleton_createJointAndBodyNodePair_registry 18 | [make_array(_jointType, _bodyType)] 19 | (_skeleton, _parent, _jointPropertiesPython, _bodyPropertiesPython); 20 | } 21 | 22 | } // namespace python 23 | } // namespace dart 24 | -------------------------------------------------------------------------------- /include/dartpy/collections.h: -------------------------------------------------------------------------------- 1 | #ifndef DARTPY_COLLECTIONS_H_ 2 | #define DARTPY_COLLECTIONS_H_ 3 | #include 4 | #include 5 | 6 | namespace dart { 7 | namespace python { 8 | namespace util { 9 | 10 | template 11 | struct vector_to_python 12 | { 13 | vector_to_python() 14 | { 15 | boost::python::to_python_converter< 16 | std::vector, vector_to_python>(); 17 | } 18 | 19 | static PyObject* convert(const std::vector& vec) 20 | { 21 | boost::python::list* py_list = new boost::python::list(); 22 | 23 | for (const T& element : vec) 24 | py_list->append(ValueType(element)); 25 | 26 | return py_list->ptr(); 27 | } 28 | }; 29 | 30 | } // namespace util 31 | } // namespace python 32 | } // namespace dart 33 | 34 | #endif // ifndef DARTPY_COLLECTIONS_H_ 35 | -------------------------------------------------------------------------------- /examples/rigid_cubes_offscreen/main_vispy.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import dart 5 | from dart.gui.vispy.viewer import Viewer 6 | 7 | 8 | def main(): 9 | file_path = os.path.join(os.path.dirname(__file__), 'cubes.skel') 10 | world = dart.utils.skel.readWorld(file_path) 11 | # world = World.create() 12 | viewer = Viewer(world, show=False) 13 | 14 | # viewer.update() 15 | size = viewer.size 16 | image = viewer.getFrame() 17 | 18 | # Now, we display this image with matplotlib to check. 19 | import matplotlib.pyplot as plt 20 | plt.figure(figsize=(size[0] / 100., size[1] / 100.), dpi=100) 21 | plt.imshow(image, interpolation='none') 22 | plt.show() 23 | 24 | print(image) 25 | 26 | if sys.flags.interactive == 0: 27 | viewer.app.run() 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /tests/regression/test_get_shape.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import dartpy 3 | 4 | from tests.util import get_asset_path 5 | 6 | 7 | def test_shape_is_accessible_from_shape_frame(): 8 | world = dartpy.utils.skel.readWorld(get_asset_path('skel/cubes.skel')) 9 | assert world is not None 10 | assert hasattr(world, 'getNumSkeletons') 11 | assert world.getNumSkeletons() > 0 12 | 13 | assert hasattr(world, 'getSkeleton') 14 | skel = world.getSkeleton(0) 15 | assert skel is not None 16 | 17 | assert hasattr(skel, 'getRootBodyNode') 18 | body = skel.getRootBodyNode() 19 | assert body is not None 20 | 21 | assert hasattr(body, 'getShapeNode') 22 | shapeNode = body.getShapeNode(0) 23 | assert shapeNode is not None 24 | 25 | assert hasattr(shapeNode, 'getShape') 26 | shape = shapeNode.getShape() 27 | assert shape is not None 28 | 29 | 30 | if __name__ == "__main__": 31 | pytest.main() 32 | -------------------------------------------------------------------------------- /tests/assets/urdf/KR5/ground.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /chimera/templates/module.mstch.cpp: -------------------------------------------------------------------------------- 1 | {{{header}}} 2 | {{#includes}} 3 | #include <{{{.}}}> 4 | {{/includes}} 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | /* main postinclude */ 11 | 12 | BOOST_PYTHON_MODULE({{module.name}}) 13 | { 14 | ::boost::python::docstring_options options(true, true, false); 15 | 16 | {{{precontent}}} 17 | {{#module.namespaces}}{{#name}} 18 | ::boost::python::scope(){{! 19 | }}{{#scope}}{{#name}}.attr("{{name}}"){{/name}}{{/scope}}.attr("{{name}}") = {{! 20 | }}::boost::python::object(::boost::python::handle<>({{! 21 | }}::boost::python::borrowed(::PyImport_AddModule({{! 22 | }}"{{module.name}}{{#scope}}{{#name}}.{{name}}{{/name}}{{/scope}}.{{name}}")))); 23 | {{/name}}{{/module.namespaces}} 24 | 25 | {{#module.bindings}} 26 | void {{.}}(); 27 | try { 28 | {{.}}(); 29 | } catch(...) { 30 | std::cerr << "Exception in: {{.}}" << std::endl; 31 | throw; 32 | } 33 | 34 | {{/module.bindings}} 35 | {{{postcontent}}} 36 | } 37 | {{{footer}}} 38 | -------------------------------------------------------------------------------- /chimera/templates/function.mstch.cpp: -------------------------------------------------------------------------------- 1 | {{{header}}} 2 | {{#includes}} 3 | #include <{{{.}}}> 4 | {{/includes}} 5 | {{{precontent}}} 6 | #include 7 | #include 8 | 9 | /* postinclude */ 10 | 11 | void {{function.mangled_name}}() 12 | { 13 | ::boost::python::object parent_object(::boost::python::scope(){{! 14 | }}{{#function.scope}}{{#name}}.attr("{{name}}"){{/name}}{{/function.scope}}); 15 | ::boost::python::scope parent_scope(parent_object); 16 | 17 | {{#function.overloads}}{{! 18 | }}::boost::python::def("{{name}}", []({{#params}}{{{type}}} {{name}}{{^last}}, {{/last}}{{/params}}) -> {{{return_type}}} { {{! 19 | }}return {{{qualified_call}}}({{#params}}{{name}}{{^last}}, {{/last}}{{/params}}); }{{! 20 | }}{{#return_value_policy}}, ::boost::python::return_value_policy<::boost::python::{{{.}}} >(){{/return_value_policy}}{{! 21 | }}{{#params?}}, ({{#params}}::boost::python::arg("{{name}}"){{^last}}, {{/last}}{{/params}}){{/params?}}); 22 | {{/function.overloads}} 23 | 24 | } 25 | {{{postcontent}}} 26 | {{{footer}}} 27 | -------------------------------------------------------------------------------- /src/template_registry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace dart { 4 | namespace python { 5 | 6 | //============================================================================== 7 | JointTemplateRegistry::RegistryType< 8 | detail::BodyNode_moveTo2_factory> 9 | JointTemplateRegistry::mBodyNode_moveTo2_registry; 10 | 11 | //============================================================================== 12 | JointTemplateRegistry::RegistryType< 13 | detail::BodyNode_moveTo3_factory> 14 | JointTemplateRegistry::mBodyNode_moveTo3_registry; 15 | 16 | //============================================================================== 17 | JointTemplateRegistry::RegistryType< 18 | detail::BodyNode_copyTo3_factory> 19 | JointTemplateRegistry::mBodyNode_copyTo3_registry; 20 | 21 | //============================================================================== 22 | JointAndNodeTemplateRegistry::RegistryType< 23 | detail::Skeleton_createJointAndBodyNodePair> 24 | JointAndNodeTemplateRegistry::mSkeleton_createJointAndBodyNodePair_registry; 25 | 26 | } // namespace python 27 | } // namespace dart 28 | -------------------------------------------------------------------------------- /.ci/install_linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | 4 | # Install DART 5 | if [ $(lsb_release -sc) = "trusty" ]; then 6 | sudo apt-add-repository ppa:libccd-debs -y 7 | sudo apt-add-repository ppa:fcl-debs -y 8 | fi 9 | sudo apt-add-repository ppa:dartsim -y 10 | sudo apt-add-repository ppa:personalrobotics -y 11 | sudo apt-get update -q 12 | sudo apt-get install cmake libboost-dev libboost-python-dev libboost-python-numpy-dev libdart6-all-dev 13 | sudo apt-get install python-dev python-numpy python-boost-numpy-eigen # for Python 2 14 | sudo apt-get install python3-dev python3-numpy python3-boost-numpy-eigen # for Python 3 15 | 16 | # Install Chimera 17 | if [ $(lsb_release -sc) = "trusty" ]; then 18 | # For installing chimera dependencies: llvm-3.7, llvm-3.7-tools, and libclang-3.7-dev 19 | sudo add-apt-repository ppa:renemilk/llvm -y 20 | sudo apt-get update -q 21 | fi 22 | sudo apt-get install chimera -y 23 | 24 | # Install dependencies for unittests 25 | sudo apt-get install python3-pip -y 26 | sudo pip3 install pytest -U 27 | 28 | # Install dartpy for running Python tests without building dartpy 29 | sudo apt-get install python3-dartpy 30 | -------------------------------------------------------------------------------- /test_resources/r2d2.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | dartpy 7 | 5.1.0 8 | 9 | Python bindings for DART, the Dynamic Animation and Robotics Toolkit. 10 | 11 | https://github.com/personalrobotics/dartpy 12 | https://github.com/personalrobotics/dartpy.git 13 | https://github.com/personalrobotics/dartpy/issues 14 | Michael Koval 15 | Michael Koval 16 | Pras Velagapudi 17 | BSD 18 | cmake 19 | boost 20 | dart 21 | python 22 | 24 | boost_numpy_eigen 25 | 26 | catkin 27 | 28 | cmake 29 | 30 | 31 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | dist: trusty 4 | 5 | matrix: 6 | include: 7 | - os: linux 8 | language: cpp 9 | env: 10 | - BUILD_NAME=TRUSTY_PYTHON_34 11 | - SUDO=sudo 12 | - PYTHON_VERSION=3.4 13 | - os: linux 14 | language: cpp 15 | services: docker 16 | env: 17 | - BUILD_NAME=XENIAL_PYTHON_35 18 | - DOCKER_FILE="ubuntu-xenial" 19 | - PYTHON_VERSION=3.5 20 | - os: linux 21 | language: cpp 22 | services: docker 23 | env: 24 | - BUILD_NAME=BIONIC_PYTHON_36 25 | - DOCKER_FILE="ubuntu-bionic" 26 | - PYTHON_VERSION=3.6 27 | - os: osx 28 | osx_image: xcode9.3 29 | compiler: clang 30 | env: 31 | - BUILD_NAME=OSX_PYTHON_37 32 | - PYTHON_VERSION=3.7 33 | 34 | install: 35 | - if [ -n "$DOCKER_FILE" ]; then 36 | docker build -t "$DOCKER_FILE" -f ".ci/docker/$DOCKER_FILE" .; 37 | docker run -itd -v $TRAVIS_BUILD_DIR:$TRAVIS_BUILD_DIR --env-file .ci/docker/env.list --name dartpy-docker "$DOCKER_FILE"; 38 | else 39 | '.ci/install.sh'; 40 | fi 41 | 42 | script: 43 | - if [ -n "$DOCKER_FILE" ]; then 44 | docker exec dartpy-docker /bin/sh -c "cd $TRAVIS_BUILD_DIR && ./.ci/script.sh"; 45 | else 46 | '.ci/script.sh'; 47 | fi 48 | 49 | after_failure: 50 | - cat Testing/Temporary/LastTest.log 51 | - cat Testing/Temporary/LastTestsFailed.log 52 | -------------------------------------------------------------------------------- /include/dartpy/metaprogramming.h: -------------------------------------------------------------------------------- 1 | #ifndef DARTPY_TEMPLATE_METAPROGRAMMING_H_ 2 | #define DARTPY_TEMPLATE_METAPROGRAMMING_H_ 3 | 4 | /// List of types. 5 | template 6 | struct typelist 7 | { 8 | }; 9 | 10 | /// Concatenate two typelists. 11 | // Source: http://stackoverflow.com/a/9122122/111426 12 | template 13 | struct typelist_cat; 14 | 15 | template 16 | struct typelist_cat, typelist> 17 | { 18 | typedef typelist type; 19 | }; 20 | 21 | 22 | /// Cartesian product of two typelists. 23 | // Source: http://stackoverflow.com/a/9122122/111426 24 | template struct typelist_product; 25 | 26 | template 27 | struct typelist_product, typelist> 28 | { 29 | // the cartesian product of {S} and {Ts...} 30 | // is a list of pairs -- here: a typelist of 2-element typelists 31 | typedef typelist...> S_cross_Ts; 32 | 33 | // the cartesian product of {Ss...} and {Ts...} (computed recursively) 34 | typedef typename typelist_product, typelist>::type Ss_cross_Ts; 35 | 36 | // concatenate both products 37 | typedef typename typelist_cat::type type; 38 | }; 39 | 40 | template 41 | struct typelist_product, typelist> 42 | { 43 | typedef typelist<> type; 44 | }; 45 | 46 | 47 | #endif // ifndef DARTPY_TEMPLATE_METAPROGRAMMING_H_ 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2017, Personal Robotics Laboratory, Carnegie Mellon University 2 | Copyright (c) 2017-2018, Personal Robotics Laboratory, University of Washington 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /include/dartpy/get_signature.h: -------------------------------------------------------------------------------- 1 | #ifndef DART_PYTHON_GET_SIGNATURE_H_ 2 | #define DART_PYTHON_GET_SIGNATURE_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // Source: https://mail.python.org/pipermail/cplusplus-sig/2014-February/017103.html 12 | 13 | namespace boost { 14 | namespace python { 15 | namespace detail { 16 | 17 | template 18 | struct fun_sign 19 | { 20 | typedef T type; 21 | }; 22 | 23 | template 24 | struct fun_sign< 25 | T, 26 | typename enable_if< 27 | mpl::greater< 28 | mpl::size, 29 | mpl::size_t<1> 30 | > 31 | >::type 32 | > 33 | { 34 | typedef typename mpl::erase< 35 | T, 36 | typename mpl::next< 37 | typename mpl::begin< 38 | T 39 | >::type 40 | >::type 41 | >::type type; 42 | }; 43 | 44 | template 45 | typename disable_if, typename fun_sign::types>::type>::type 46 | get_signature(T, void* = 0) 47 | { 48 | return typename fun_sign::types>::type(); 49 | } 50 | 51 | } // namespace detail 52 | } // namespace python 53 | } // namespace boost 54 | 55 | #endif // ifndef DART_PYTHON_GET_SIGNATURE_H_ 56 | -------------------------------------------------------------------------------- /src/BodyNode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace dart { 6 | namespace python { 7 | 8 | //============================================================================== 9 | dart::dynamics::Joint* BodyNode_moveTo2( 10 | dart::dynamics::BodyNode* _bodyNode, 11 | boost::python::object _jointType, 12 | dart::dynamics::BodyNode* _newParent, 13 | boost::python::object _jointProperties) 14 | { 15 | return JointTemplateRegistry::mBodyNode_moveTo2_registry 16 | [make_array(_jointType)] 17 | (_bodyNode, _newParent, _jointProperties); 18 | } 19 | 20 | //============================================================================== 21 | dart::dynamics::Joint* BodyNode_moveTo3( 22 | dart::dynamics::BodyNode* _bodyNode, 23 | boost::python::object _jointType, 24 | const dart::dynamics::SkeletonPtr& _newSkeleton, 25 | dart::dynamics::BodyNode* _newParent, 26 | boost::python::object _jointProperties) 27 | { 28 | return JointTemplateRegistry::mBodyNode_moveTo3_registry 29 | [make_array(_jointType)] 30 | (_bodyNode, _newSkeleton, _newParent, _jointProperties); 31 | } 32 | 33 | 34 | //============================================================================== 35 | boost::python::object BodyNode_copyTo3( 36 | boost::python::object _jointType, 37 | dart::dynamics::BodyNode* _bodyNode, 38 | dart::dynamics::BodyNode* _newParent, 39 | boost::python::object _jointProperties, 40 | bool _recursive) 41 | { 42 | return JointTemplateRegistry::mBodyNode_copyTo3_registry 43 | [make_array(_jointType)] 44 | (_bodyNode, _newParent, _jointProperties, _recursive); 45 | } 46 | 47 | } // namespace python 48 | } // namespace dart 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### CMake ### 4 | CMakeCache.txt 5 | CMakeFiles 6 | Makefile 7 | cmake_install.cmake 8 | install_manifest.txt 9 | 10 | 11 | ### C++ ### 12 | # Compiled Object files 13 | *.slo 14 | *.lo 15 | *.o 16 | *.obj 17 | 18 | # Precompiled Headers 19 | *.gch 20 | *.pch 21 | 22 | # Compiled Dynamic libraries 23 | *.so 24 | *.dylib 25 | *.dll 26 | 27 | # Fortran module files 28 | *.mod 29 | 30 | # Compiled Static libraries 31 | *.lai 32 | *.la 33 | *.a 34 | *.lib 35 | 36 | # Executables 37 | *.exe 38 | *.out 39 | *.app 40 | 41 | 42 | ### Python ### 43 | # Byte-compiled / optimized / DLL files 44 | __pycache__/ 45 | *.py[cod] 46 | .pytest_cache 47 | 48 | # C extensions 49 | *.so 50 | 51 | # Distribution / packaging 52 | .Python 53 | env/ 54 | build/ 55 | develop-eggs/ 56 | dist/ 57 | downloads/ 58 | eggs/ 59 | .eggs/ 60 | lib/ 61 | lib64/ 62 | parts/ 63 | sdist/ 64 | var/ 65 | *.egg-info/ 66 | .installed.cfg 67 | *.egg 68 | 69 | # PyInstaller 70 | # Usually these files are written by a python script from a template 71 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 72 | *.manifest 73 | *.spec 74 | 75 | # Installer logs 76 | pip-log.txt 77 | pip-delete-this-directory.txt 78 | 79 | # Unit test / coverage reports 80 | htmlcov/ 81 | .tox/ 82 | .coverage 83 | .coverage.* 84 | .cache 85 | nosetests.xml 86 | coverage.xml 87 | *,cover 88 | 89 | # Translations 90 | *.mo 91 | *.pot 92 | 93 | # Django stuff: 94 | *.log 95 | 96 | # Sphinx documentation 97 | docs/_build/ 98 | 99 | # PyBuilder 100 | target/ 101 | 102 | 103 | ### Vim ### 104 | [._]*.s[a-w][a-z] 105 | [._]s[a-w][a-z] 106 | *.un~ 107 | Session.vim 108 | .netrwhist 109 | *~ 110 | -------------------------------------------------------------------------------- /include/dartpy/detail/JointAndNodeRegistry.h: -------------------------------------------------------------------------------- 1 | #ifndef DARTPY_DETAIL_JOINTANDNODEREGISTRY_H_ 2 | #define DARTPY_DETAIL_JOINTANDNODEREGISTRY_H_ 3 | #include 4 | #include 5 | 6 | using dart::dynamics::BodyNode; 7 | using dart::dynamics::BodyNodePtr; 8 | using dart::dynamics::Joint; 9 | using dart::dynamics::JointPtr; 10 | using dart::dynamics::Skeleton; 11 | using dart::dynamics::TemplateBodyNodePtr; 12 | 13 | 14 | namespace dart { 15 | namespace python { 16 | namespace detail { 17 | 18 | //============================================================================== 19 | template 20 | struct Skeleton_createJointAndBodyNodePair 21 | { 22 | static boost::python::object execute( 23 | Skeleton* _skeleton, BodyNode* _parent, 24 | boost::python::object _jointPropertiesPython, 25 | boost::python::object _bodyPropertiesPython) 26 | { 27 | typename JointType::Properties jointProperties; 28 | if (!_jointPropertiesPython.is_none()) 29 | { 30 | jointProperties = boost::python::extract( 31 | _jointPropertiesPython); 32 | } 33 | 34 | typename NodeType::Properties bodyProperties; 35 | if (!_bodyPropertiesPython.is_none()) 36 | { 37 | // Workaround for the ambiguous overload error of operator= 38 | const typename NodeType::Properties tmp 39 | = boost::python::extract( 40 | _bodyPropertiesPython); 41 | bodyProperties = std::move(tmp); 42 | } 43 | 44 | auto ret = _skeleton->createJointAndBodyNodePair( 45 | _parent, jointProperties, bodyProperties); 46 | 47 | return boost::python::make_tuple( 48 | JointPtr(ret.first), TemplateBodyNodePtr(ret.second)); 49 | } 50 | }; 51 | 52 | } // namespace detail 53 | } // namespace python 54 | } // namespace dart 55 | 56 | #endif // ifndef DARTPY_DETAIL_JOINTANDNODEREGISTRY_H_ 57 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Make sure pytest is installed 2 | execute_process( 3 | COMMAND ${PYTHON_EXECUTABLE} -c "import pytest; print(pytest.__version__)" 4 | RESULT_VARIABLE pytest_not_found 5 | OUTPUT_VARIABLE pytest_version 6 | ERROR_QUIET 7 | ) 8 | if(pytest_not_found) 9 | message(STATUS "Running the tests requires pytest. Please install it manually" 10 | " (try: ${PYTHON_EXECUTABLE} -m pip install pytest)" 11 | ) 12 | set(DARTPY_PYTEST_FOUND FALSE) 13 | elseif(pytest_version VERSION_LESS 3.0) 14 | message(STATUS "Running the tests requires pytest >= 3.0. Found: ${pytest_version}" 15 | "Please update it (try: ${PYTHON_EXECUTABLE} -m pip install -U pytest)" 16 | ) 17 | set(DARTPY_PYTEST_FOUND FALSE) 18 | else() 19 | set(DARTPY_PYTEST_FOUND TRUE) 20 | endif() 21 | 22 | # Check if dartpy is installed 23 | execute_process( 24 | COMMAND ${PYTHON_EXECUTABLE} -c "import boost_numpy_eigen" 25 | RESULT_VARIABLE boost_numpy_eigen_not_found 26 | ERROR_QUIET 27 | ) 28 | if(boost_numpy_eigen_not_found) 29 | message(STATUS "Running the tests requires boost_numpy_eigen. Please install it manually" 30 | " (try: sudo apt install python3-boost-numpy-eigen)" 31 | ) 32 | set(DARTPY_BOOST_NUMPY_EIGEN_FOUND FALSE) 33 | else() 34 | set(DARTPY_BOOST_NUMPY_EIGEN_FOUND TRUE) 35 | endif() 36 | 37 | # Check if dartpy is installed 38 | execute_process( 39 | COMMAND ${PYTHON_EXECUTABLE} -c "import sys; sys.path.insert(0,\"${CMAKE_BINARY_DIR}\"); import dartpy" 40 | RESULT_VARIABLE dartpy_not_found 41 | ERROR_QUIET 42 | ) 43 | if(dartpy_not_found) 44 | message(STATUS "Running the tests requires dartpy. Please install it manually" 45 | " (try: sudo apt install python3-dartpy)" 46 | ) 47 | set(DARTPY_DARTPY_FOUND FALSE) 48 | else() 49 | set(DARTPY_DARTPY_FOUND TRUE) 50 | endif() 51 | 52 | set(DARTPY_TEST_FILES 53 | comprehensive/test_collision_detector.py 54 | regression/test_get_shape.py 55 | unit/test_dart_loader.py 56 | ) 57 | 58 | # Add custom target to run the tests 59 | add_custom_target(pytest 60 | COMMAND ${CMAKE_COMMAND} -E echo "Running pytest by: ${PYTHON_EXECUTABLE} -m pytest [sources]" 61 | COMMAND PYTHONPATH=${CMAKE_BINARY_DIR} ${PYTHON_EXECUTABLE} -m pytest ${DARTPY_TEST_FILES} 62 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 63 | ) 64 | -------------------------------------------------------------------------------- /tests/unit/test_dart_loader.py: -------------------------------------------------------------------------------- 1 | import platform 2 | 3 | import pytest 4 | from dartpy.utils import DartLoader 5 | 6 | from tests.util import get_asset_path 7 | 8 | 9 | def test_parse_skeleton_non_existing_path_returns_null(): 10 | loader = DartLoader() 11 | assert loader.parseSkeleton(get_asset_path('skel/test/does_not_exist.urdf')) is None 12 | 13 | 14 | def test_parse_skeleton_invalid_urdf_returns_null(): 15 | loader = DartLoader() 16 | assert loader.parseSkeleton(get_asset_path('urdf/invalid.urdf')) is None 17 | 18 | 19 | def test_parse_skeleton_missing_mesh_returns_null(): 20 | loader = DartLoader() 21 | assert loader.parseSkeleton(get_asset_path('urdf/missing_mesh.urdf')) is None 22 | 23 | 24 | def test_parse_skeleton_invalid_mesh_returns_null(): 25 | loader = DartLoader() 26 | assert loader.parseSkeleton(get_asset_path('urdf/invalid_mesh.urdf')) is None 27 | 28 | 29 | def test_parse_skeleton_missing_package_returns_null(): 30 | loader = DartLoader() 31 | assert loader.parseSkeleton(get_asset_path('urdf/missing_package.urdf')) is None 32 | 33 | 34 | def test_parse_skeleton_loads_primitive_geometry(): 35 | loader = DartLoader() 36 | assert loader.parseSkeleton(get_asset_path('urdf/primitive_geometry.urdf')) is not None 37 | 38 | 39 | # Failing with following errors: 40 | # TypeError: No to_python (by-value) converter found for C++ type: std::shared_ptr 41 | # 42 | # def test_parse_world(): 43 | # loader = DartLoader() 44 | # assert loader.parseWorld(get_asset_path('urdf/testWorld.urdf')) is not None 45 | 46 | 47 | def test_parse_joint_properties(): 48 | loader = DartLoader() 49 | robot = loader.parseSkeleton(get_asset_path('urdf/joint_properties.urdf')) 50 | assert robot is not None 51 | 52 | joint1 = robot.getJoint(1) 53 | assert joint1 is not None 54 | assert joint1.getDampingCoefficient(0) == pytest.approx(1.2, 1e-12) 55 | assert joint1.getCoulombFriction(0) == pytest.approx(2.3, 1e-12) 56 | 57 | joint2 = robot.getJoint(2) 58 | assert joint2 is not None 59 | assert joint2.getPositionLowerLimit(0) == -float("inf") 60 | assert joint2.getPositionUpperLimit(0) == float("inf") 61 | if not platform.linux_distribution()[1] == '14.04': 62 | assert joint2.isCyclic(0) 63 | 64 | 65 | if __name__ == "__main__": 66 | pytest.main() 67 | -------------------------------------------------------------------------------- /tests/assets/urdf/issue838.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/skel_parser.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* precontent */ 13 | #include 14 | #include 15 | 16 | /* postinclude */ 17 | 18 | void skel_parser() 19 | { 20 | ::boost::python::object parent_object(::boost::python::scope().attr("utils").attr("skel")); 21 | ::boost::python::scope parent_scope(parent_object); 22 | 23 | ::boost::python::def("readWorld", [](const dart::common::Uri & uri) -> dart::simulation::WorldPtr { return dart::utils::SkelParser::readWorld(uri); }, (::boost::python::arg("uri"))); 24 | ::boost::python::def("readWorld", [](const dart::common::Uri & uri, const dart::common::ResourceRetrieverPtr & retriever) -> dart::simulation::WorldPtr { return dart::utils::SkelParser::readWorld(uri, retriever); }, (::boost::python::arg("uri"), ::boost::python::arg("retriever"))); 25 | ::boost::python::def("readWorldXML", [](const std::string & xmlString) -> dart::simulation::WorldPtr { return dart::utils::SkelParser::readWorldXML(xmlString); }, (::boost::python::arg("xmlString"))); 26 | ::boost::python::def("readWorldXML", [](const std::string & xmlString, const dart::common::Uri & baseUri) -> dart::simulation::WorldPtr { return dart::utils::SkelParser::readWorldXML(xmlString, baseUri); }, (::boost::python::arg("xmlString"), ::boost::python::arg("baseUri"))); 27 | ::boost::python::def("readWorldXML", [](const std::string & xmlString, const dart::common::Uri & baseUri, const dart::common::ResourceRetrieverPtr & retriever) -> dart::simulation::WorldPtr { return dart::utils::SkelParser::readWorldXML(xmlString, baseUri, retriever); }, (::boost::python::arg("xmlString"), ::boost::python::arg("baseUri"), ::boost::python::arg("retriever"))); 28 | ::boost::python::def("readSkeleton", [](const dart::common::Uri & uri) -> dart::dynamics::SkeletonPtr { return dart::utils::SkelParser::readSkeleton(uri); }, (::boost::python::arg("uri"))); 29 | ::boost::python::def("readSkeleton", [](const dart::common::Uri & uri, const dart::common::ResourceRetrieverPtr & retriever) -> dart::dynamics::SkeletonPtr { return dart::utils::SkelParser::readSkeleton(uri, retriever); }, (::boost::python::arg("uri"), ::boost::python::arg("retriever"))); 30 | 31 | } 32 | 33 | /* footer */ 34 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | import os 3 | import platform 4 | from codecs import open # To use a consistent encoding 5 | from setuptools import setup, Extension 6 | from setuptools.command.build_ext import build_ext 7 | 8 | # Get the current directory path. 9 | here = os.path.abspath(os.path.dirname(__file__)) 10 | 11 | # Extract the description from the top-level README. 12 | with open(os.path.join(here, 'README.md'), encoding='utf-8') as f: 13 | long_description = f.read() 14 | description = 'dartpy provides python bindings for DART.' 15 | 16 | # Set the dependencies depending on the platform 17 | system = platform.system() 18 | if system == 'Linux': 19 | distro = platform.linux_distribution()[1] 20 | if distro == '14.04': 21 | install_requires = ['numpy', 'pyassimp', 'pytest'] 22 | else: 23 | install_requires = ['numpy', 'pyassimp', 'pytest'] 24 | else: 25 | install_requires = ['numpy', 'pyassimp', 'pytest'] 26 | 27 | 28 | # See: http://www.astropython.org/snippet/2009/10/chdir-context-manager 29 | @contextlib.contextmanager 30 | def chdir(dirname=None): 31 | """ Context manager for changing directories. """ 32 | curdir = os.getcwd() 33 | try: 34 | if dirname is not None: 35 | os.chdir(dirname) 36 | yield 37 | finally: 38 | os.chdir(curdir) 39 | 40 | 41 | # See: https://github.com/libdynd/dynd-python/blob/master/setup.py 42 | class cmake_build_ext(build_ext): 43 | """ Wrapper class that builds the extension using CMake. """ 44 | 45 | def run(self): 46 | """ Build using CMake from the specified build directory. """ 47 | self.mkpath(self.build_temp) 48 | with chdir(self.build_temp): 49 | self.spawn(['cmake', here]) 50 | self.spawn(['make']) 51 | 52 | 53 | # Set up the python package wrapping this extension. 54 | setup( 55 | name='dartpy', 56 | version='0.0.1', 57 | description=description, 58 | long_description=long_description, 59 | ext_modules=[Extension('dartpy', sources=[])], 60 | url='https://github.com/personalrobotics/dartpy', 61 | author='Michael Koval', 62 | author_email='mkoval@cs.cmu.edu', 63 | maintainer='Jeongseok Lee', 64 | maintainer_email='jslee02@cs.uw.edu', 65 | license='BSD', 66 | keywords=['dartsim', 'physics', 'robotics', 'simulation'], 67 | classifiers=[ 68 | 'Development Status :: 1 - Planning', 69 | 'License :: OSI Approved :: BSD License', 70 | 'Intended Audience :: Developers', 71 | ], 72 | # cmdclass={'build_ext': cmake_build_ext}, 73 | install_requires=install_requires 74 | ) 75 | -------------------------------------------------------------------------------- /tests/assets/urdf/ground.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /include/dartpy/util.h: -------------------------------------------------------------------------------- 1 | #ifndef DART_PYTHON_UTIL_H_ 2 | #define DART_PYTHON_UTIL_H_ 3 | #include 4 | #include 5 | 6 | // See below. Based off of: http://stackoverflow.com/a/25403872/111426 7 | #define DISCARD_FUNCTION_RETURN(_FUNC_)\ 8 | ::dart::python::util::discard_function_return 9 | #define DISCARD_METHOD_RETURN(_CLASS_, _FUNC_)\ 10 | ::dart::python::util::discard_method_return<_CLASS_, decltype(&_FUNC_), &_FUNC_> 11 | 12 | namespace dart { 13 | namespace python { 14 | namespace util { 15 | 16 | // Define a wrapper function that returns void. This requires variadic 17 | // templates and C++11 perfect forwarding gymnastics. 18 | // Source: http://stackoverflow.com/a/25403872/111426 19 | template 20 | void discard_function_return(Args&&... args) 21 | { 22 | fn(std::forward(args)...); 23 | } 24 | 25 | // This is the same as discard_function_return for class methods. It takes an 26 | // additional template argument (the class) and an additional function argument 27 | // (the instance). This is compatible with Boost.Python. 28 | template 29 | void discard_method_return(T *instance, Args&&... args) 30 | { 31 | (instance->*fn)(std::forward(args)...); 32 | } 33 | 34 | // from_python converter for iterable collections. The container_type must 35 | // have: (1) have a container_type::value_type typedef and (2) a constructor 36 | // that accepts two forward_iterator. 37 | // 38 | // Source: 39 | // https://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/ 40 | template 41 | struct collection_from_python 42 | { 43 | typedef typename container_type::value_type content_type; 44 | 45 | collection_from_python() 46 | { 47 | ::boost::python::converter::registry::push_back( 48 | &convertible, 49 | &construct, 50 | ::boost::python::type_id() 51 | ); 52 | } 53 | 54 | static void *convertible(PyObject *object_py_raw) 55 | { 56 | PyObject *iterator_py_raw = PyObject_GetIter(object_py_raw); 57 | if (iterator_py_raw) { 58 | Py_DECREF(iterator_py_raw); 59 | return object_py_raw; 60 | } else { 61 | PyErr_Clear(); 62 | return NULL; 63 | } 64 | } 65 | 66 | static void construct( 67 | PyObject *object_py_raw, 68 | boost::python::converter::rvalue_from_python_stage1_data *data) 69 | { 70 | using ::boost::python::borrowed; 71 | using ::boost::python::converter::rvalue_from_python_storage; 72 | using ::boost::python::handle; 73 | using ::boost::python::object; 74 | using ::boost::python::stl_input_iterator; 75 | using ::std::make_pair; 76 | 77 | // Wrap the PyObject in a Boost.Python class. 78 | object object_py(handle<>(borrowed(object_py_raw))); 79 | 80 | // Allocate storage for the output object using placement-new. 81 | void *storage 82 | = reinterpret_cast *>(data) 83 | ->storage.bytes; 84 | 85 | new (storage) container_type( 86 | stl_input_iterator(object_py), 87 | stl_input_iterator() 88 | ); 89 | 90 | data->convertible = storage; 91 | } 92 | }; 93 | 94 | } // namespace util 95 | } // namespace python 96 | } // namespace dart 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dartpy [![Build Status](https://travis-ci.org/personalrobotics/dartpy.svg?branch=master)](https://travis-ci.org/personalrobotics/dartpy) # 2 | 3 | > :warning: **Warning:** `dartpy` is under heavy development. See the open 4 | > issues on [`dartpy`](https://github.com/personalrobotics/dartpy/issues) and 5 | > [Chimera](https://github.com/personalrobotics/chimera/issues) for insight 6 | > into the current state of the project. Please report any issues you 7 | > encounter on the appropriate repository. This repo will be mreged into the 8 | > main repository of DART once becomes stable. 9 | 10 | Python bindings for [DART][dart], the Dynamic Animation and Robotics Toolkit. 11 | 12 | ## Installation 13 | 14 | ### On Ubuntu 14.04 / 16.04 / 18.04 15 | 16 | You can install `dartpy` using `apt-get` as: 17 | 18 | **14.04** 19 | 20 | ```shell 21 | $ sudo add-apt-repository ppa:libccd-debs/ppa 22 | $ sudo add-apt-repository ppa:fcl-debs/ppa 23 | $ sudo add-apt-repository ppa:dartsim/ppa 24 | $ sudo add-apt-repository ppa:personalrobotics/ppa 25 | $ sudo apt-get update 26 | 27 | $ sudo apt-get install python-dartpy # for Python 2 28 | $ sudo apt-get install python3-dartpy # for Python 3 29 | ``` 30 | 31 | **16.04 / 18.04** 32 | 33 | ```shell 34 | $ sudo add-apt-repository ppa:dartsim/ppa 35 | $ sudo add-apt-repository ppa:personalrobotics/ppa 36 | $ sudo apt-get update 37 | 38 | $ sudo apt-get install python-dartpy # for Python 2 39 | $ sudo apt-get install python3-dartpy # for Python 3 40 | ``` 41 | 42 | All set! Import `dartpy` in Python and enjoy! Please see [Usage](#usage) section for more information. 43 | 44 | If you want to build `dartpy` from source, please see this [wiki page](https://github.com/personalrobotics/dartpy/wiki/Building-from-Source). 45 | 46 | ### On macOS 47 | 48 | ```shell 49 | $ brew install personalrobotics/tap/dartpy 50 | ``` 51 | 52 | ## Usage 53 | 54 | Once `dartpy` is installed, you should be able to open a Python terminal and 55 | `import dartpy`. Since `dartpy` is mostly auto-generated using Chimera, the 56 | DART Python API mostly matches the DART C++ API. 57 | 58 | There are a few exceptions: 59 | 60 | ### Template Functions 61 | 62 | Template functions take the template parameters as regular arguments, e.g. the 63 | C++ code: 64 | ```c++ 65 | auto joint = bodynode.moveTo(newParent); 66 | ``` 67 | becomes the Python code 68 | ```python 69 | joint = bodynode.moveTo(dartpy.dynamics.FreeJoint, newParent) 70 | ``` 71 | 72 | Due to limitations of C++, this functionality requires the template arguments 73 | to be registered with `dartpy`. Follow [the instructions](https://github.com/personalrobotics/dartpy/wiki/Bindings-for-Extension-Libraries#template-member-functions) 74 | to register your custom types for use as template arguments. 75 | 76 | ## License 77 | 78 | `dartpy` is licensed under [the BSD-2-Clause license](https://opensource.org/licenses/BSD-2-Clause). See [LICENSE](https://github.com/personalrobotics/dartpy/blob/master/LICENSE) for more information. 79 | 80 | ## Authors 81 | 82 | `dartpy` is developed by the [Personal Robotics Lab][prl] in the [Robotics 83 | Institute][ri] at [Carnegie Mellon University][cmu] by [Michael Koval][mkoval] 84 | ([**@mkoval**][mkoval_github]) and [Pras Velagapudi][psigen] 85 | ([**@psigen**][psigen_github]). 86 | 87 | 88 | [chimera]: https://github.com/personalrobotics/chimera 89 | [cmake]: https://cmake.org/ 90 | [cmu]: http://www.cmu.edu 91 | [dart]: http://dartsim.github.io/ 92 | [mkoval]: http://mkoval.org 93 | [mkoval_github]: https://github.com/mkoval 94 | [prl]: https://personalrobotics.ri.cmu.edu 95 | [prl_dev]: https://personalrobotics.cs.washington.edu/software/development-environment/ 96 | [psigen]: http://www.snowbotic.com/ 97 | [psigen_github]: http://github.com/psigen 98 | [ri]: https://www.ri.cmu.edu 99 | [ubuntu1404]: http://releases.ubuntu.com/14.04/ 100 | -------------------------------------------------------------------------------- /tests/assets/urdf/joint_properties.urdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /include/dartpy/detail/JointTemplateMultiplexer.h: -------------------------------------------------------------------------------- 1 | #ifndef DARTPY_DETAIL_JOINTTEMPLATEMULTIPLEXER_H_ 2 | #define DARTPY_DETAIL_JOINTTEMPLATEMULTIPLEXER_H_ 3 | #include 4 | #include 5 | 6 | namespace dart { 7 | namespace python { 8 | namespace detail { 9 | 10 | //============================================================================== 11 | template 12 | struct BodyNode_moveTo2_factory 13 | { 14 | static dart::dynamics::Joint* execute( 15 | dart::dynamics::BodyNode* _bodyNode, 16 | dart::dynamics::BodyNode* _newParent, 17 | boost::python::object _jointPropertiesPython) 18 | { 19 | typename JointType::Properties jointProperties; 20 | 21 | if (!_jointPropertiesPython.is_none()) 22 | { 23 | jointProperties = boost::python::extract( 24 | _jointPropertiesPython); 25 | } 26 | 27 | return _bodyNode->moveTo(_newParent); 28 | } 29 | }; 30 | 31 | //============================================================================== 32 | template 33 | struct BodyNode_moveTo3_factory 34 | { 35 | static dart::dynamics::Joint* execute( 36 | dart::dynamics::BodyNode* _bodyNode, 37 | const dart::dynamics::SkeletonPtr &_newSkeleton, 38 | dart::dynamics::BodyNode* _newParent, 39 | boost::python::object _jointPropertiesPython) 40 | { 41 | typename JointType::Properties jointProperties; 42 | 43 | if (!_jointPropertiesPython.is_none()) 44 | { 45 | jointProperties = boost::python::extract( 46 | _jointPropertiesPython); 47 | } 48 | 49 | return _bodyNode->moveTo( 50 | _newSkeleton, _newParent, jointProperties); 51 | } 52 | }; 53 | 54 | //============================================================================== 55 | template 56 | struct BodyNode_copyTo3_factory 57 | { 58 | static boost::python::object execute( 59 | dart::dynamics::BodyNode* _bodyNode, 60 | dart::dynamics::BodyNode* _newParent, 61 | boost::python::object _jointPropertiesPython, 62 | bool _recursive) 63 | { 64 | typename JointType::Properties jointProperties; 65 | 66 | if (!_jointPropertiesPython.is_none()) 67 | { 68 | jointProperties = boost::python::extract( 69 | _jointPropertiesPython); 70 | } 71 | 72 | const auto ret = _bodyNode->copyTo(_newParent, jointProperties); 73 | return boost::python::make_tuple(ret.first, ret.second); 74 | } 75 | }; 76 | 77 | //============================================================================== 78 | template 79 | struct BodyNode_split_factory 80 | { 81 | static dart::dynamics::SkeletonPtr execute( 82 | dart::dynamics::BodyNode* _bodyNode, 83 | const std::string& _skeletonName, 84 | boost::python::object _jointPropertiesPython) 85 | { 86 | typename JointType::Properties jointProperties; 87 | 88 | if (!_jointPropertiesPython.is_none()) 89 | { 90 | jointProperties = boost::python::extract( 91 | _jointPropertiesPython); 92 | } 93 | 94 | return _bodyNode->split(_skeletonName, jointProperties); 95 | } 96 | }; 97 | 98 | //============================================================================== 99 | template 100 | struct BodyNode_changeParentJointType_factory 101 | { 102 | static dart::dynamics::JointPtr execute( 103 | dart::dynamics::BodyNode* _bodyNode, 104 | boost::python::object _jointPropertiesPython) 105 | { 106 | typename JointType::Properties jointProperties; 107 | 108 | if (!_jointPropertiesPython.is_none()) 109 | { 110 | jointProperties = boost::python::extract( 111 | _jointPropertiesPython); 112 | } 113 | 114 | return _bodyNode->changeParentJointType(jointProperties); 115 | } 116 | }; 117 | 118 | } // namespace detail 119 | } // namespace python 120 | } // namespace dart 121 | 122 | #endif // ifndef DARTPY_DETAIL_JOINTTEMPLATEMULTIPLEXER_H_ 123 | -------------------------------------------------------------------------------- /chimera/templates/cxx_record.mstch.cpp: -------------------------------------------------------------------------------- 1 | {{{header}}} 2 | {{#includes}} 3 | #include <{{{.}}}> 4 | {{/includes}} 5 | {{{precontent}}} 6 | #include 7 | #include 8 | 9 | namespace { 10 | 11 | {{#class.comment?}}{{! 12 | }}constexpr char {{class.mangled_name}}_docstring[] = R"CHIMERA_STRING({{! 13 | }}{{#class.comment}}{{! 14 | }}{{{.}}} 15 | {{/class.comment}}{{! 16 | }})CHIMERA_STRING"; 17 | {{/class.comment?}} 18 | 19 | {{#class.methods}}{{! 20 | }}{{#comment?}}{{! 21 | }}constexpr char {{mangled_name}}_docstring[] = R"CHIMERA_STRING({{! 22 | }}{{#comment}}{{! 23 | }}{{{.}}} 24 | {{/comment}}{{! 25 | }})CHIMERA_STRING"; 26 | 27 | {{/comment?}}{{! 28 | }}{{/class.methods}} 29 | 30 | } // namespace 31 | 32 | void {{class.mangled_name}}() 33 | { 34 | ::boost::python::object parent_object(::boost::python::scope(){{! 35 | }}{{#class.scope}}{{#name}}.attr("{{name}}"){{/name}}{{/class.scope}}); 36 | ::boost::python::scope parent_scope(parent_object); 37 | 38 | ::boost::python::class_<{{{class.type}}}{{^class.is_copyable}}, {{! 39 | }}::boost::noncopyable{{/class.is_copyable}}{{#class.held_type}}, {{! 40 | }}{{{.}}}{{/class.held_type}}{{#class.bases?}}, {{! 41 | }}::boost::python::bases<{{! 42 | }}{{#class.bases}}{{{qualified_name}}}{{^last}}, {{/last}}{{/class.bases}}{{! 43 | }} >{{/class.bases?}} >("{{class.name}}"{{! 44 | }}{{#class.comment?}}, {{class.mangled_name}}_docstring{{/class.comment?}}{{! 45 | }}, boost::python::no_init){{! 46 | 47 | /* constructors */}} 48 | {{#class.constructors}}{{! 49 | }}{{#overloads}}{{! 50 | }}.def("__init__", ::boost::python::make_constructor({{! 51 | }}[]({{#params}}{{{type}}} {{name}}{{^last}}, {{/last}}{{/params}}){{! 52 | }} -> {{{class.type}}} * { {{! 53 | }}return new {{{class.type}}}({{#params}}{{name}}{{^last}}, {{/last}}{{/params}}); }{{! 54 | }}, ::boost::python::default_call_policies(){{! 55 | }}{{#params?}}, ({{#params}}::boost::python::arg("{{name}}"){{^last}}, {{/last}}{{/params}}){{/params?}})) 56 | {{/overloads}}{{! 57 | }}{{/class.constructors}}{{! 58 | 59 | /* member functions */}} 60 | {{#class.methods}}{{! 61 | }}{{^is_static}}{{! 62 | }}{{#overloads}}{{! 63 | }}.def("{{name}}", []({{#is_const}}const {{/is_const}}{{{class.type}}} *self{{#params}}, {{{type}}} {{name}}{{/params}}) -> {{{return_type}}} { {{! 64 | }}return self->{{{call}}}({{#params}}{{name}}{{^last}}, {{/last}}{{/params}}); }{{! 65 | }}{{#return_value_policy}}, ::boost::python::return_value_policy<::boost::python::{{{.}}} >(){{/return_value_policy}}{{! 66 | }}{{#comment?}}, {{mangled_name}}_docstring{{/comment?}}{{! 67 | }}{{#params?}}, ({{#params}}::boost::python::arg("{{name}}"){{^last}}, {{/last}}{{/params}}){{/params?}}) 68 | {{/overloads}}{{! 69 | }}{{/is_static}}{{! 70 | }}{{/class.methods}}{{! 71 | 72 | /* static member functions */}} 73 | {{#class.methods}}{{! 74 | }}{{#is_static}}{{! 75 | }}{{#overloads}}{{! 76 | }}.def("{{name}}", []({{#params}}{{{type}}} {{name}}{{^last}}, {{/last}}{{/params}}) -> {{{return_type}}} { {{! 77 | }}return {{{qualified_call}}}({{#params}}{{name}}{{^last}}, {{/last}}{{/params}}); }{{! 78 | }}{{#return_value_policy}}, ::boost::python::return_value_policy<::boost::python::{{{.}}} >(){{/return_value_policy}}{{! 79 | }}{{#params?}}, ({{#params}}::boost::python::arg("{{name}}"){{^last}}, {{/last}}{{/params}}){{/params?}}) 80 | {{/overloads}}{{! 81 | }}{{/is_static}}{{! 82 | }}{{/class.methods}} 83 | {{#class.static_methods}}{{! 84 | }}.staticmethod("{{.}}") 85 | {{/class.static_methods}}{{! 86 | 87 | /* fields */}} 88 | {{#class.fields}}{{! 89 | }}{{#is_assignable}}.def_readwrite{{/is_assignable}}{{! 90 | }}{{^is_assignable}}.def_readonly{{/is_assignable}}{{! 91 | }}("{{name}}", &{{{qualified_name}}}) 92 | {{/class.fields}}{{! 93 | 94 | /* static fields */ 95 | /* TODO: Add make_setter if this property is assignable */}} 96 | {{#class.static_fields}}{{! 97 | }}.add_static_property("{{name}}", {{! 98 | }}::boost::python::make_getter({{{qualified_name}}})) 99 | {{/class.static_fields}} 100 | ; 101 | } 102 | {{{postcontent}}} 103 | {{{footer}}} 104 | -------------------------------------------------------------------------------- /tests/assets/skel/cubes.skel: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0.001 6 | 0 -9.81 0 7 | dart 8 | 9 | 10 | 11 | 12 | 0 -0.375 0 0 0 0 13 | 14 | 0 0 0 0 0 0 15 | 16 | 17 | 2.5 0.05 2.5 18 | 19 | 20 | 0.95 0.95 0.95 21 | 22 | 23 | 0 0 0 0 0 0 24 | 25 | 26 | 2.5 0.05 2.5 27 | 28 | 29 | 30 | 31 | 32 | world 33 | ground 34 | 35 | 36 | 37 | 38 | 39 | 1 40 | 0 -0.325 0 0 0 0 41 | 42 | 1 43 | 0 0 0 44 | 45 | 46 | 0 0 0 0 0 0 47 | 48 | 49 | 0.1 0.05 0.1 50 | 51 | 52 | 0.8 0.3 0.3 53 | 54 | 55 | 0 0 0 0 0 0 56 | 57 | 58 | 0.1 0.05 0.1 59 | 60 | 61 | 62 | 63 | 64 | 65 | world 66 | box 67 | 68 | 69 | 70 | 71 | 72 | 1 73 | 0 -0.275 0 0 0 0 74 | 75 | 1 76 | 0 0 0 77 | 78 | 79 | 0 0 0 0 0 0 80 | 81 | 82 | 0.05 0.05 0.05 83 | 84 | 85 | 0.3 0.8 0.3 86 | 87 | 88 | 0 0 0 0 0 0 89 | 90 | 91 | 0.05 0.05 0.05 92 | 93 | 94 | 95 | 96 | 97 | 98 | world 99 | link_1 100 | 101 | 102 | 103 | 104 | 105 | 1 106 | 0.05 -0.195 0 0 0 0 107 | 108 | 1 109 | 0 0 0 110 | 111 | 112 | 0 0 0 0 0 0 113 | 114 | 115 | 0.05 0.05 0.05 116 | 117 | 118 | 0.8 0.8 0.4 119 | 120 | 121 | 0 0 0 0 0 0 122 | 123 | 124 | 0.05 0.05 0.05 125 | 126 | 127 | 128 | 129 | 130 | 131 | world 132 | link_1 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /examples/rigid_cubes/cubes.skel: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0.001 6 | 0 -9.81 0 7 | dart 8 | 9 | 10 | 11 | 12 | 0 -0.375 0 0 0 0 13 | 14 | 0 0 0 0 0 0 15 | 16 | 17 | 2.5 0.05 2.5 18 | 19 | 20 | 0.95 0.95 0.95 21 | 22 | 23 | 0 0 0 0 0 0 24 | 25 | 26 | 2.5 0.05 2.5 27 | 28 | 29 | 30 | 31 | 32 | world 33 | ground 34 | 35 | 36 | 37 | 38 | 39 | 1 40 | 0 -0.325 0 0 0 0 41 | 42 | 1 43 | 0 0 0 44 | 45 | 46 | 0 0 0 0 0 0 47 | 48 | 49 | 0.1 0.05 0.1 50 | 51 | 52 | 0.8 0.3 0.3 53 | 54 | 55 | 0 0 0 0 0 0 56 | 57 | 58 | 0.1 0.05 0.1 59 | 60 | 61 | 62 | 63 | 64 | 65 | world 66 | box 67 | 68 | 69 | 70 | 71 | 72 | 1 73 | 0 -0.275 0 0 0 0 74 | 75 | 1 76 | 0 0 0 77 | 78 | 79 | 0 0 0 0 0 0 80 | 81 | 82 | 0.05 0.05 0.05 83 | 84 | 85 | 0.3 0.8 0.3 86 | 87 | 88 | 0 0 0 0 0 0 89 | 90 | 91 | 0.05 0.05 0.05 92 | 93 | 94 | 95 | 96 | 97 | 98 | world 99 | link_1 100 | 101 | 102 | 103 | 104 | 105 | 1 106 | 0.05 -0.195 0 0 0 0 107 | 108 | 1 109 | 0 0 0 110 | 111 | 112 | 0 0 0 0 0 0 113 | 114 | 115 | 0.05 0.05 0.05 116 | 117 | 118 | 0.8 0.8 0.4 119 | 120 | 121 | 0 0 0 0 0 0 122 | 123 | 124 | 0.05 0.05 0.05 125 | 126 | 127 | 128 | 129 | 130 | 131 | world 132 | link_1 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /examples/rigid_cubes_offscreen/cubes.skel: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0.001 6 | 0 -9.81 0 7 | dart 8 | 9 | 10 | 11 | 12 | 0 -0.375 0 0 0 0 13 | 14 | 0 0 0 0 0 0 15 | 16 | 17 | 2.5 0.05 2.5 18 | 19 | 20 | 0.95 0.95 0.95 21 | 22 | 23 | 0 0 0 0 0 0 24 | 25 | 26 | 2.5 0.05 2.5 27 | 28 | 29 | 30 | 31 | 32 | world 33 | ground 34 | 35 | 36 | 37 | 38 | 39 | 1 40 | 0 -0.325 0 0 0 0 41 | 42 | 1 43 | 0 0 0 44 | 45 | 46 | 0 0 0 0 0 0 47 | 48 | 49 | 0.1 0.05 0.1 50 | 51 | 52 | 0.8 0.3 0.3 53 | 54 | 55 | 0 0 0 0 0 0 56 | 57 | 58 | 0.1 0.05 0.1 59 | 60 | 61 | 62 | 63 | 64 | 65 | world 66 | box 67 | 68 | 69 | 70 | 71 | 72 | 1 73 | 0 -0.275 0 0 0 0 74 | 75 | 1 76 | 0 0 0 77 | 78 | 79 | 0 0 0 0 0 0 80 | 81 | 82 | 0.05 0.05 0.05 83 | 84 | 85 | 0.3 0.8 0.3 86 | 87 | 88 | 0 0 0 0 0 0 89 | 90 | 91 | 0.05 0.05 0.05 92 | 93 | 94 | 95 | 96 | 97 | 98 | world 99 | link_1 100 | 101 | 102 | 103 | 104 | 105 | 1 106 | 0.05 -0.195 0 0 0 0 107 | 108 | 1 109 | 0 0 0 110 | 111 | 112 | 0 0 0 0 0 0 113 | 114 | 115 | 0.05 0.05 0.05 116 | 117 | 118 | 0.8 0.8 0.4 119 | 120 | 121 | 0 0 0 0 0 0 122 | 123 | 124 | 0.05 0.05 0.05 125 | 126 | 127 | 128 | 129 | 130 | 131 | world 132 | link_1 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /include/dartpy/pointers.h: -------------------------------------------------------------------------------- 1 | #ifndef DART_PYTHON_POINTERS_H_ 2 | #define DART_PYTHON_POINTERS_H_ 3 | #include 4 | #include 5 | #include "types.h" 6 | 7 | #ifdef BOOST_CONFIG_HPP 8 | #error "pointers.h must be included before any Boost headers" 9 | #endif 10 | 11 | #include "get_signature.h" 12 | #include 13 | 14 | #include 15 | // TODO(JS): This includes Boost headers, which conflicts with 16 | // the above ifdef statement. Confirm whether this doesn't cause 17 | // any issues. 18 | 19 | namespace boost { 20 | 21 | #ifndef DARTPY_HAS_STD_SHARED_GET_POINTER 22 | template 23 | T* get_pointer(const std::shared_ptr& p) 24 | { 25 | return p.get(); 26 | } 27 | #endif // ifndef DARTPY_HAS_STD_SHARED_GET_POINTER 28 | 29 | template 30 | BodyNodeT* get_pointer( 31 | const dart::dynamics::TemplateBodyNodePtr& p) 32 | { 33 | return p.get(); 34 | } 35 | 36 | template 37 | NodeT* get_pointer( 38 | const dart::dynamics::TemplateNodePtr& p) 39 | { 40 | return p.get(); 41 | } 42 | 43 | template 44 | JointT* get_pointer( 45 | const dart::dynamics::TemplateJointPtr& p) 46 | { 47 | return p.get(); 48 | } 49 | 50 | template 51 | DegreeOfFreedomT* get_pointer( 52 | const dart::dynamics::TemplateDegreeOfFreedomPtr< 53 | DegreeOfFreedomT, BodyNodeT>& p) 54 | { 55 | return p.get(); 56 | } 57 | 58 | } // namespace boost 59 | 60 | // We CANNOT include anything that defines get_pointer() before we define our 61 | // own overrides. This file does so indirectly. 62 | #include 63 | #include 64 | 65 | namespace boost { 66 | namespace python { 67 | 68 | template 69 | struct pointee> 70 | { 71 | using type = BodyNodeT; 72 | }; 73 | 74 | template 75 | struct pointee> 76 | { 77 | using type = NodeT; 78 | }; 79 | 80 | template 81 | struct pointee> 82 | { 83 | using type = JointT; 84 | }; 85 | 86 | template 87 | struct pointee> 89 | { 90 | using type = DegreeOfFreedomT; 91 | }; 92 | 93 | } // namespace python 94 | } // namespace boost 95 | 96 | namespace boost { 97 | namespace python { 98 | namespace detail { 99 | 100 | // attempting to instantiate this type will result in a compiler error, 101 | // if that happens it means you're trying to use return_by_smart_pointer 102 | // on a function/method that doesn't return a pointer! 103 | template 104 | struct return_by_smart_ptr_requires_a_pointer_return_type 105 | # if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) 106 | {} 107 | # endif 108 | ; 109 | 110 | 111 | // this is where all the work is done, first the plain pointer is 112 | // converted to a smart pointer, and then the smart pointer is embedded 113 | // in a Python object 114 | template 115 | struct make_owning_smart_ptr_holder 116 | { 117 | template 118 | static PyObject *execute(T* p) 119 | { 120 | Ptr ptr(p); 121 | return objects::make_ptr_instance 123 | >::execute(ptr); 124 | } 125 | }; 126 | 127 | } // namespace detail 128 | 129 | template 130 | struct return_by_smart_ptr 131 | { 132 | template 133 | struct apply 134 | { 135 | typedef typename mpl::if_c< 136 | boost::is_pointer::value, 137 | to_python_indirect >, 139 | detail::return_by_smart_ptr_requires_a_pointer_return_type 140 | >::type type; 141 | }; 142 | }; 143 | 144 | template 145 | struct smart_ptr_from_python 146 | { 147 | smart_ptr_from_python() 148 | { 149 | converter::registry::insert(&convertible, &construct, type_id() 150 | #ifndef BOOST_PYTHON_NO_PY_SIGNATURES 151 | , &converter::expected_from_python_type_direct::get_pytype 152 | #endif 153 | ); 154 | } 155 | 156 | private: 157 | static void *convertible(PyObject *p) 158 | { 159 | if (p == Py_None) { 160 | return p; 161 | } 162 | return converter::get_lvalue_from_python(p, 163 | converter::registered::converters); 164 | } 165 | 166 | static void construct(PyObject* source, 167 | converter::rvalue_from_python_stage1_data* data) 168 | { 169 | void *const storage 170 | = ((converter::rvalue_from_python_storage*)data)->storage.bytes; 171 | 172 | // Deal with the "None" case. 173 | if (data->convertible == source) { 174 | new (storage) Ptr(); 175 | } else { 176 | #if 0 177 | boost::shared_ptr hold_convertible_ref_count( 178 | (void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); 179 | // use aliasing constructor 180 | new (storage) Ptr( 181 | hold_convertible_ref_count, 182 | static_cast(data->convertible)); 183 | #endif 184 | new (storage) Ptr(static_cast(data->convertible)); 185 | } 186 | 187 | data->convertible = storage; 188 | } 189 | }; 190 | 191 | }} // namespace boost::python 192 | 193 | #endif // ifndef DART_PYTHON_POINTERS_H_ 194 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(dartpy) 3 | 4 | if(NOT DARTPY_PYTHON_VERSION) 5 | set(DARTPY_PYTHON_VERSION 3.4 CACHE STRING "Choose the target Python version (e.g., 3.4, 2.7)" FORCE) 6 | endif() 7 | 8 | # TODO: This should be set by DART. 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-deprecated -Wno-deprecated-declarations") 10 | 11 | find_package(PythonInterp ${DARTPY_PYTHON_VERSION} REQUIRED) 12 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c 13 | "from distutils.sysconfig import get_python_lib;\ 14 | print(get_python_lib(plat_specific=True, prefix=''))" 15 | OUTPUT_VARIABLE PYTHON_SITE_PACKAGES 16 | OUTPUT_STRIP_TRAILING_WHITESPACE 17 | ) 18 | 19 | # Find boost with python components. The name of python component varies 20 | # depending on the platform, boost version, and python version. 21 | if(APPLE) 22 | find_package(Boost REQUIRED 23 | COMPONENTS 24 | python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} thread 25 | ) 26 | else() # LINUX assumed 27 | if(${PYTHON_VERSION_MAJOR} EQUAL 3) 28 | find_package(Boost 29 | COMPONENTS 30 | python-py${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} thread 31 | ) 32 | if(NOT Boost_FOUND) 33 | find_package(Boost REQUIRED COMPONENTS python3 thread) 34 | endif() 35 | else() # Python 2 assumed 36 | find_package(Boost REQUIRED COMPONENTS python thread) 37 | endif() 38 | endif() 39 | 40 | find_package(DART 6.6.1 REQUIRED 41 | COMPONENTS 42 | collision-bullet 43 | # collision-ode 44 | optimizer-nlopt 45 | planning 46 | utils-urdf 47 | gui-osg 48 | CONFIG 49 | ) 50 | 51 | # Check if DART is built with octomap so that it supports VoxelGridShape 52 | include(CheckCXXSourceCompiles) 53 | set(CMAKE_REQUIRED_DEFINITIONS "") 54 | set(CMAKE_REQUIRED_FLAGS "-std=c++11") 55 | set(CMAKE_REQUIRED_INCLUDES ${DART_INCLUDE_DIRS}) 56 | set(CMAKE_REQUIRED_LIBRARIES ${DART_LIBRARIES}) 57 | check_cxx_source_compiles( 58 | " 59 | #include 60 | int main() 61 | { 62 | auto voxel = new dart::dynamics::VoxelGridShape(); 63 | delete voxel; 64 | return 0; 65 | } 66 | " 67 | DART_HAS_VOXELGRIDSHAPE 68 | ) 69 | 70 | find_package(PythonLibs ${DARTPY_PYTHON_VERSION} REQUIRED) 71 | find_package(chimera QUIET) 72 | 73 | include_directories(SYSTEM 74 | ${Boost_INCLUDE_DIRS} 75 | ${DART_INCLUDE_DIRS} 76 | ${PYTHON_INCLUDE_DIRS} 77 | ) 78 | 79 | # Check whether the CXX compiler and boost::python support get_pointer for 80 | # std::shared_ptr references. 81 | include(CheckCXXSourceCompiles) 82 | set(CMAKE_REQUIRED_INCLUDES 83 | ${Boost_INCLUDE_DIRS} 84 | ${PYTHON_INCLUDE_DIRS} 85 | ) 86 | set(CMAKE_REQUIRED_LIBRARIES 87 | ${Boost_LIBRARIES} 88 | ${PYTHON_LIBRARIES} 89 | ) 90 | check_cxx_source_compiles( 91 | " 92 | #include 93 | #include 94 | int main() { std::shared_ptr ptr; int *p = boost::get_pointer(ptr); } 95 | " 96 | DARTPY_HAS_STD_SHARED_GET_POINTER 97 | ) 98 | 99 | unset(CMAKE_REQUIRED_INCLUDES) 100 | unset(CMAKE_REQUIRED_LIBRARIES) 101 | 102 | # Generate a header file for the DARTPY_HAS_STD_SHARED_GET_POINTER flag. 103 | configure_file("cmake/config.h.in" 104 | "include/dartpy/config.h" 105 | ) 106 | 107 | include_directories( 108 | "include" 109 | "${CMAKE_CURRENT_BINARY_DIR}/include" 110 | ) 111 | 112 | # If chimera is available on this system, create a target to build bindings. 113 | if(DART_HAS_VOXELGRIDSHAPE) 114 | set(CHIMERA_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/chimera/chimera.yml") 115 | else() 116 | set(CHIMERA_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/chimera/chimera_without_voxel.yml") 117 | endif() 118 | if(chimera_FOUND) 119 | add_chimera_binding(TARGET "${PROJECT_NAME}_CHIMERA" 120 | MODULE "${PROJECT_NAME}" 121 | CONFIGURATION "${CHIMERA_CONFIG}" 122 | SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/chimera/chimera.cpp" 123 | DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/src/generated" 124 | DEBUG EXCLUDE_FROM_ALL 125 | ) 126 | target_link_libraries("${PROJECT_NAME}_CHIMERA" 127 | ${Boost_LIBRARIES} 128 | ${DART_LIBRARIES} 129 | ${PYTHON_LIBRARIES} 130 | ) 131 | add_custom_target(binding DEPENDS "${PROJECT_NAME}_CHIMERA_REBUILD") 132 | else() 133 | add_custom_target(binding 134 | COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red "ERROR: Cannot generate bindings without \\'chimera\\' installed." 135 | COMMAND false 136 | ) 137 | endif() 138 | 139 | # Create a target to build generated bindings. 140 | set(SOURCES_TXT "${CMAKE_CURRENT_SOURCE_DIR}/src/generated/sources.txt") 141 | if(EXISTS "${SOURCES_TXT}") 142 | file(STRINGS "${SOURCES_TXT}" SOURCES_GENERATED_RELATIVE NO_HEX_CONVERSION) 143 | 144 | set(SOURCES_GENERATED) 145 | foreach(relative_path ${SOURCES_GENERATED_RELATIVE}) 146 | list(APPEND SOURCES_GENERATED "${CMAKE_CURRENT_SOURCE_DIR}/src/generated/${relative_path}") 147 | endforeach() 148 | 149 | add_library("${PROJECT_NAME}" MODULE 150 | ${SOURCES_GENERATED} 151 | src/BodyNode.cpp 152 | src/Skeleton.cpp 153 | src/skel_parser.cpp 154 | src/template_registry.cpp 155 | ) 156 | target_link_libraries("${PROJECT_NAME}" 157 | ${Boost_LIBRARIES} 158 | ${DART_LIBRARIES} 159 | ${PYTHON_LIBRARIES} 160 | ) 161 | set_target_properties("${PROJECT_NAME}" PROPERTIES 162 | PREFIX "" 163 | SUFFIX ".so" # python uses '.so' extension even on macOS 164 | ) 165 | if(CMAKE_COMPILER_IS_GNUCXX) 166 | target_compile_options("${PROJECT_NAME}" 167 | PRIVATE -fabi-version=6 168 | ) 169 | endif() 170 | 171 | install(TARGETS "${PROJECT_NAME}" 172 | LIBRARY DESTINATION "${PYTHON_SITE_PACKAGES}" 173 | ) 174 | else() 175 | add_custom_target(${PROJECT_NAME} ALL 176 | COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red "ERROR: Generate bindings using \\'make binding\\' before attempting to build." 177 | COMMAND false 178 | ) 179 | endif() 180 | 181 | add_subdirectory(tests) 182 | -------------------------------------------------------------------------------- /include/dartpy/template_registry.h: -------------------------------------------------------------------------------- 1 | #ifndef DARTPY_TEMPLATE_REGISTRY_H_ 2 | #define DARTPY_TEMPLATE_REGISTRY_H_ 3 | #include 4 | #include 5 | #include 6 | #include "metaprogramming.h" 7 | #include "detail/JointTemplateMultiplexer.h" 8 | #include "detail/JointAndNodeRegistry.h" 9 | 10 | namespace dart { 11 | namespace python { 12 | 13 | using AllJointTypes = typelist< 14 | dart::dynamics::FreeJoint, 15 | dart::dynamics::PrismaticJoint, 16 | dart::dynamics::RevoluteJoint, 17 | dart::dynamics::ScrewJoint, 18 | dart::dynamics::WeldJoint, 19 | dart::dynamics::UniversalJoint, 20 | dart::dynamics::BallJoint, 21 | dart::dynamics::EulerJoint, 22 | dart::dynamics::PlanarJoint, 23 | dart::dynamics::TranslationalJoint>; 24 | 25 | using AllBodyNodeTypes = typelist< 26 | dart::dynamics::BodyNode, 27 | dart::dynamics::SoftBodyNode>; 28 | 29 | 30 | /// Gets the PyTypeObject object associated with a C++ class. 31 | template 32 | boost::python::object get_pytype() 33 | { 34 | const boost::python::converter::registration* registration 35 | = boost::python::converter::registry::query(typeid(T)); 36 | if (!registration) 37 | { 38 | throw std::runtime_error("Type is not known to Boost.Python."); 39 | } 40 | 41 | PyTypeObject* const class_object = registration->get_class_object(); 42 | return boost::python::object(boost::python::handle<>( 43 | boost::python::borrowed(class_object))); 44 | } 45 | 46 | 47 | /// Registry that maps Python type objects to a factory function. 48 | template 49 | using TemplateRegistryKey 50 | = std::array; 51 | 52 | template 53 | using TemplateRegistry 54 | = std::map, std::function>; 55 | 56 | 57 | // Source: http://en.cppreference.com/w/cpp/language/sizeof... 58 | template 59 | constexpr auto make_array(Ts... ts) 60 | -> std::array::type, sizeof...(ts)> 61 | { 62 | // Double braces are required for aggregate initialization. 63 | // See: http://stackoverflow.com/a/11735045/111426 64 | return {{ ts... }}; 65 | } 66 | 67 | 68 | /// Helper class for registering all types in a typelist. 69 | template 70 | struct register_all_types {}; 71 | 72 | // Base case. 73 | template 74 | struct register_all_types> 75 | { 76 | static void register_type() 77 | { 78 | // Do nothing. 79 | } 80 | }; 81 | 82 | // Specialization for a manually constructed typelist. 83 | template 84 | struct register_all_types> 85 | { 86 | static void register_type() 87 | { 88 | Registry::template register_type(); 89 | register_all_types>::register_type(); 90 | } 91 | }; 92 | 93 | // Specialization for the output of typelist_product. 94 | template 95 | struct register_all_types, Types...>> 96 | { 97 | static void register_type() 98 | { 99 | Registry::template register_type(); 100 | register_all_types>::register_type(); 101 | } 102 | }; 103 | 104 | 105 | struct JointTemplateRegistry 106 | { 107 | template