plainmp 0.3.6.dev1__tar.gz → 0.3.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/.github/workflows/build_and_test.yaml +1 -1
  2. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/.github/workflows/check_format.yaml +1 -1
  3. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/CMakeLists.txt +31 -0
  4. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/PKG-INFO +2 -1
  5. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/bindings/ompl_wrapper.cpp +23 -0
  6. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/algorithm_selector.cpp +2 -0
  7. plainmp-0.3.7/cpp/plainmp/ompl/plainmp_rrtc_wrap.hpp +167 -0
  8. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/pyproject.toml +5 -3
  9. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/ompl_solver.py +15 -1
  10. plainmp-0.3.7/tests/cpp/test_batch_nearest.cpp +99 -0
  11. plainmp-0.3.7/tests/cpp/test_plainmp_rrtc.cpp +286 -0
  12. plainmp-0.3.7/tests/test_plainmp_rrtc.py +144 -0
  13. plainmp-0.3.7/third/ompl_rrtc/LICENSE +33 -0
  14. plainmp-0.3.7/third/ompl_rrtc/batch_nearest.hpp +173 -0
  15. plainmp-0.3.7/third/ompl_rrtc/plainmp_rrtc.cpp +231 -0
  16. plainmp-0.3.7/third/ompl_rrtc/plainmp_rrtc.hpp +71 -0
  17. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/uv.lock +1267 -1
  18. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/.flake8 +0 -0
  19. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/.gitattributes +0 -0
  20. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/.github/workflows/check_mpl_requirement.yaml +0 -0
  21. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/.github/workflows/check_pypi_install.yaml +0 -0
  22. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/.github/workflows/release.yaml +0 -0
  23. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/.gitignore +0 -0
  24. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/LICENSE-BSD3 +0 -0
  25. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/README.md +0 -0
  26. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/.gitignore +0 -0
  27. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/LICENSE-MPL2 +0 -0
  28. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/add_header.sh +0 -0
  29. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/bindings/bindings.hpp +0 -0
  30. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/bindings/constraint.cpp +0 -0
  31. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/bindings/kdtree.cpp +0 -0
  32. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/bindings/kinematics.cpp +0 -0
  33. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/bindings/primitive.cpp +0 -0
  34. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/bindings/python.cpp +0 -0
  35. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/collision/kdtree.cpp +0 -0
  36. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/collision/kdtree.hpp +0 -0
  37. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/collision/primitive_sdf.hpp +0 -0
  38. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/composite_constraint.hpp +0 -0
  39. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive.hpp +0 -0
  40. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_com_in_polytope.cpp +0 -0
  41. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_com_in_polytope.hpp +0 -0
  42. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_config_point.cpp +0 -0
  43. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_config_point.hpp +0 -0
  44. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_fixed_zaxis.cpp +0 -0
  45. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_fixed_zaxis.hpp +0 -0
  46. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_link_pose.cpp +0 -0
  47. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_link_pose.hpp +0 -0
  48. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_link_position_bound.cpp +0 -0
  49. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_link_position_bound.hpp +0 -0
  50. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_relative_pose.cpp +0 -0
  51. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_relative_pose.hpp +0 -0
  52. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_sphere_collision.cpp +0 -0
  53. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/primitive_sphere_collision.hpp +0 -0
  54. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/sequential_constraint.cpp +0 -0
  55. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/constraints/sequential_constraint.hpp +0 -0
  56. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/kinematics/algorithm.cpp +0 -0
  57. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/kinematics/data_structure.hpp +0 -0
  58. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/kinematics/kinematic_model_wrapper.cpp +0 -0
  59. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/kinematics/kinematic_model_wrapper.hpp +0 -0
  60. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/kinematics/kinematics.cpp +0 -0
  61. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/kinematics/kinematics.hpp +0 -0
  62. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/kinematics/transform.hpp +0 -0
  63. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/.gitignore +0 -0
  64. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/algorithm_selector.hpp +0 -0
  65. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/custom_goal_samplable_region.cpp +0 -0
  66. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/custom_goal_samplable_region.hpp +0 -0
  67. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/generate_sequence.py +0 -0
  68. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/motion_validator.cpp +0 -0
  69. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/motion_validator.hpp +0 -0
  70. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/ompl_thin_wrap.hpp +0 -0
  71. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/unidirectional_modified.cpp +0 -0
  72. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/cpp/plainmp/ompl/unidirectional_modified.hpp +0 -0
  73. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/attach_box_ik_and_plan.py +0 -0
  74. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/bench/.gitignore +0 -0
  75. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/bench/fetch_plan.py +0 -0
  76. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/bench/panda_plan.py +0 -0
  77. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/beta/humanoid_lift_and_place_box.py +0 -0
  78. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/beta/humanoid_planning.py +0 -0
  79. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/fetch_ik.py +0 -0
  80. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/fetch_plan.py +0 -0
  81. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/misc/fetch_visualize_coll_spheres.py +0 -0
  82. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/misc/panda_visualize_coll_spheres.py +0 -0
  83. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/misc/pr2_visualize_coll_spheres.py +0 -0
  84. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/openarm/openarm_dualarm.py +0 -0
  85. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/openarm/openarm_larm.py +0 -0
  86. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/openarm/openarm_rarm.py +0 -0
  87. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/openarm_gravity_compensation.py +0 -0
  88. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/panda_plan.py +0 -0
  89. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/pr2_dualarm_ik_and_plan.py +0 -0
  90. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/pr2_rarm_ik_and_plan.py +0 -0
  91. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/example/pr2_with_mobile_base.py +0 -0
  92. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/format.sh +0 -0
  93. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/__init__.py +0 -0
  94. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/assets/openarm_v10.urdf +0 -0
  95. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/fetch.yaml +0 -0
  96. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/jaxon.yaml +0 -0
  97. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/openarm_v10/collision_spheres.yaml +0 -0
  98. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/openarm_v10/openarm_v10_dual.yaml +0 -0
  99. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/openarm_v10/openarm_v10_larm.yaml +0 -0
  100. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/openarm_v10/openarm_v10_rarm.yaml +0 -0
  101. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/panda.yaml +0 -0
  102. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/pr2_base_only.yaml +0 -0
  103. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/pr2_common/aux.yaml +0 -0
  104. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/pr2_common/collision_spheres.yaml +0 -0
  105. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/pr2_common/end_effectors.yaml +0 -0
  106. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/pr2_dualarm.yaml +0 -0
  107. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/pr2_larm.yaml +0 -0
  108. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/conf/pr2_rarm.yaml +0 -0
  109. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/constraint.py +0 -0
  110. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/constraint.pyi +0 -0
  111. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/ik.py +0 -0
  112. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/kdtree.py +0 -0
  113. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/kdtree.pyi +0 -0
  114. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/kinematics.py +0 -0
  115. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/kinematics.pyi +0 -0
  116. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/manifold_rrt/__init__.py +0 -0
  117. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/manifold_rrt/_manifold_rrt_algorithms.py +0 -0
  118. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/manifold_rrt/manifold_rrt_solver.py +0 -0
  119. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/nlp_solver/__init__.py +0 -0
  120. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/nlp_solver/osqp_sqp.py +0 -0
  121. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/nlp_solver/sqp_based_solver.py +0 -0
  122. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/parallel.py +0 -0
  123. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/problem.py +0 -0
  124. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/psdf.py +0 -0
  125. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/psdf.pyi +0 -0
  126. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/robot_spec.py +0 -0
  127. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/script/bubblify_to_plainmp.py +0 -0
  128. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/trajectory.py +0 -0
  129. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/src/plainmp/utils.py +0 -0
  130. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/tests/test_constraints.py +0 -0
  131. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/tests/test_ik.py +0 -0
  132. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/tests/test_kdtree.py +0 -0
  133. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/tests/test_kinematics.py +0 -0
  134. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/tests/test_manifold_rrt.py +0 -0
  135. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/tests/test_ompl_solver.py +0 -0
  136. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/tests/test_psdf.py +0 -0
  137. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/tests/test_robot_spec.py +0 -0
  138. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/ompl-ertconnect/CMakeLists.txt +0 -0
  139. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/ompl-ertconnect/README.md +0 -0
  140. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/ompl-ertconnect/ertconnect/ERT.h +0 -0
  141. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/ompl-ertconnect/ertconnect/ERTConnect.h +0 -0
  142. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/ompl-ertconnect/ertconnect/ert/PlannerData.h +0 -0
  143. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/ompl-ertconnect/ertconnect/src/ERT.cpp +0 -0
  144. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/ompl-ertconnect/ertconnect/src/ERTConnect.cpp +0 -0
  145. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/.gitignore +0 -0
  146. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/CMakeLists.txt +0 -0
  147. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/README.md +0 -0
  148. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/LICENSE +0 -0
  149. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_exception/exception.h +0 -0
  150. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_model/color.h +0 -0
  151. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_model/joint.h +0 -0
  152. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_model/link.h +0 -0
  153. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_model/model.h +0 -0
  154. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_model/pose.h +0 -0
  155. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_model/types.h +0 -0
  156. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_model/utils.h +0 -0
  157. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_parser/exportdecl.h +0 -0
  158. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_parser/urdf_parser.h +0 -0
  159. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/include/urdf_world/types.h +0 -0
  160. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/src/joint.cpp +0 -0
  161. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/src/link.cpp +0 -0
  162. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/src/model.cpp +0 -0
  163. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/src/pose.cpp +0 -0
  164. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/tinyxml/CMakeLists.txt +0 -0
  165. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/tinyxml/tinystr.cpp +0 -0
  166. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/tinyxml/tinystr.h +0 -0
  167. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/tinyxml/tinyxml.cpp +0 -0
  168. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/tinyxml/tinyxml.h +0 -0
  169. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/tinyxml/tinyxmlerror.cpp +0 -0
  170. {plainmp-0.3.6.dev1 → plainmp-0.3.7}/third/urdf_parser/tinyxml/tinyxmlparser.cpp +0 -0
@@ -64,7 +64,7 @@ jobs:
64
64
  - name: Build and install source distribution
65
65
  run: |
66
66
  uv build --sdist
67
- uv sync --locked --no-install-project
67
+ uv sync --no-install-project
68
68
  uv pip install --python .venv/bin/python dist/*.tar.gz
69
69
 
70
70
  - name: Test
@@ -28,7 +28,7 @@ jobs:
28
28
  enable-cache: true
29
29
 
30
30
  - name: Install formatters
31
- run: uv sync --locked --only-group lint
31
+ run: uv sync --only-group lint
32
32
 
33
33
  - name: install clang-format
34
34
  run: |
@@ -6,6 +6,17 @@ if(NOT CMAKE_BUILD_TYPE)
6
6
  endif(NOT CMAKE_BUILD_TYPE)
7
7
  set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS_INIT} -fPIC")
8
8
 
9
+ option(PLAINMP_MARCH_NATIVE "Optimize C++ code for the build machine's CPU" ON)
10
+ if(PLAINMP_MARCH_NATIVE)
11
+ include(CheckCXXCompilerFlag)
12
+ check_cxx_compiler_flag("-march=native" PLAINMP_HAS_MARCH_NATIVE)
13
+ if(PLAINMP_HAS_MARCH_NATIVE)
14
+ add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-march=native>)
15
+ else()
16
+ message(WARNING "The C++ compiler does not support -march=native; building without it")
17
+ endif()
18
+ endif()
19
+
9
20
  find_package(Eigen3 REQUIRED)
10
21
  ADD_DEFINITIONS(-DEIGEN_NO_DEBUG)
11
22
  ADD_DEFINITIONS(-DEIGEN_DONT_VECTORIZE)
@@ -45,6 +56,7 @@ add_custom_target(generate_sequence_table
45
56
  )
46
57
 
47
58
  file(GLOB_RECURSE SRC_FILES cpp/*.cpp)
59
+ list(APPEND SRC_FILES third/ompl_rrtc/plainmp_rrtc.cpp)
48
60
  include_directories(cpp)
49
61
  if(CMAKE_VERSION VERSION_LESS 3.18)
50
62
  set(DEV_MODULE Development)
@@ -65,6 +77,7 @@ find_package(nanobind CONFIG REQUIRED)
65
77
  # Match the optimization of the former pybind11 target. LTO is also needed by
66
78
  # the statically linked ERTConnect planner with OMPL 1.6 and GCC 9.
67
79
  nanobind_add_module(_plainmp NOMINSIZE LTO ${SRC_FILES})
80
+ target_include_directories(_plainmp PRIVATE third)
68
81
  add_dependencies(_plainmp generate_sequence_table)
69
82
 
70
83
  if (TARGET ompl::ompl)
@@ -77,3 +90,21 @@ if(ompl_VERSION VERSION_LESS "1.7.0")
77
90
  target_compile_definitions(_plainmp PRIVATE OMPL_OLD_VERSION)
78
91
  endif()
79
92
  install(TARGETS _plainmp DESTINATION .)
93
+
94
+ option(PLAINMP_BUILD_TESTS "Build native planner tests" OFF)
95
+ if(PLAINMP_BUILD_TESTS)
96
+ enable_testing()
97
+ add_executable(test_batch_nearest tests/cpp/test_batch_nearest.cpp)
98
+ target_include_directories(test_batch_nearest PRIVATE third)
99
+ add_test(NAME batch_nearest_native COMMAND test_batch_nearest)
100
+ add_executable(test_plainmp_rrtc tests/cpp/test_plainmp_rrtc.cpp
101
+ third/ompl_rrtc/plainmp_rrtc.cpp cpp/plainmp/ompl/motion_validator.cpp)
102
+ target_include_directories(test_plainmp_rrtc PRIVATE third)
103
+ add_dependencies(test_plainmp_rrtc generate_sequence_table)
104
+ if(TARGET ompl::ompl)
105
+ target_link_libraries(test_plainmp_rrtc PRIVATE ompl::ompl)
106
+ else()
107
+ target_link_libraries(test_plainmp_rrtc PRIVATE ${OMPL_LIBRARIES})
108
+ endif()
109
+ add_test(NAME plainmp_rrtc_native COMMAND test_plainmp_rrtc)
110
+ endif()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: plainmp
3
- Version: 0.3.6.dev1
3
+ Version: 0.3.7
4
4
  Summary: Very fast motion planning for articulated robot, through a bit of premature-optimization (C++ core with Python bindings) *less than 1ms for moderate problems
5
5
  Author: Hirokazu Ishida
6
6
  License: MPL2.0 for C++ core and BSD3 for Python bindings
@@ -13,4 +13,5 @@ Requires-Dist: pyyaml
13
13
  Requires-Dist: robot_descriptions
14
14
  Requires-Dist: osqp<1.0.0
15
15
  Requires-Dist: tyro
16
+ Requires-Dist: matplotlib>=3.7.5
16
17
 
@@ -12,6 +12,7 @@
12
12
  #include "plainmp/bindings/bindings.hpp"
13
13
  #include "plainmp/constraints/primitive.hpp"
14
14
  #include "plainmp/ompl/ompl_thin_wrap.hpp"
15
+ #include "plainmp/ompl/plainmp_rrtc_wrap.hpp"
15
16
 
16
17
  namespace plainmp::bindings {
17
18
 
@@ -56,6 +57,28 @@ void bind_ompl_wrapper_submodule(nb::module_& m) {
56
57
  nb::arg("goal_sampler") = nb::none(),
57
58
  nb::arg("max_goal_sample_count") = nb::none());
58
59
 
60
+ nb::class_<PlainmpRRTCSettings>(ompl_m, "PlainmpRRTCSettings")
61
+ .def(nb::init<>())
62
+ .def_rw("max_samples", &PlainmpRRTCSettings::max_samples);
63
+
64
+ nb::class_<PlainmpRRTCPlanner>(ompl_m, "PlainmpRRTCPlanner")
65
+ .def(nb::init<const std::vector<double>&, const std::vector<double>&,
66
+ constraint::IneqConstraintBase::Ptr, size_t,
67
+ const ValidatorConfig&, std::optional<double>,
68
+ const std::optional<PlainmpRRTCSettings>&>(),
69
+ nb::arg("lower_bound"), nb::arg("upper_bound"),
70
+ nb::arg("constraint"), nb::arg("max_is_valid_call"),
71
+ nb::arg("validator_config"), nb::arg("range") = nb::none(),
72
+ nb::arg("settings") = nb::none())
73
+ .def("get_call_count", &PlainmpRRTCPlanner::getCallCount)
74
+ .def("get_node_count", &PlainmpRRTCPlanner::getNodeCount)
75
+ .def("get_ns_internal", &PlainmpRRTCPlanner::get_ns_internal)
76
+ .def("solve", &PlainmpRRTCPlanner::solve, nb::arg("start"),
77
+ nb::arg("goal").none(), nb::arg("refine_seq"),
78
+ nb::arg("timeout") = nb::none(),
79
+ nb::arg("goal_sampler") = nb::none(),
80
+ nb::arg("max_goal_sample_count") = nb::none());
81
+
59
82
  nb::class_<ERTConnectPlanner>(ompl_m, "ERTConnectPlanner")
60
83
  .def(nb::init<const std::vector<double>&, const std::vector<double>&,
61
84
  constraint::IneqConstraintBase::Ptr, size_t,
@@ -16,6 +16,7 @@
16
16
  #include <ompl/geometric/planners/rrt/RRTConnect.h>
17
17
  #include <ompl/geometric/planners/rrt/RRTstar.h>
18
18
  #include <optional>
19
+ #include "ompl_rrtc/plainmp_rrtc.hpp"
19
20
  #include "plainmp/ompl/unidirectional_modified.hpp"
20
21
 
21
22
  namespace plainmp::ompl_wrapper {
@@ -44,6 +45,7 @@ std::shared_ptr<ompl::base::Planner> get_algorithm(
44
45
  if (name == "KPIECE1") return create_with_range<ocustom::KPIECE1Modified>(si, range);
45
46
  if (name == "RRT") return create_with_range<ocustom::RRTModified>(si, range);
46
47
  if (name == "RRTConnect") return create_with_range<og::RRTConnect>(si, range);
48
+ if (name == "plainmp_rrtc") return create_with_range<PlainmpRRTC>(si, range);
47
49
  if (name == "RRTstar") return create_with_range<og::RRTstar>(si, range);
48
50
  if (name == "EST") return create_with_range<og::EST>(si, range);
49
51
  if (name == "BiEST") return create_with_range<og::BiEST>(si, range);
@@ -0,0 +1,167 @@
1
+ /* Copyright (C) 2026 Hirokazu Ishida
2
+ * This Source Code Form is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. See https://mozilla.org/MPL/2.0/.
4
+ */
5
+ #pragma once
6
+
7
+ #include "ompl_rrtc/plainmp_rrtc.hpp"
8
+ #include "plainmp/ompl/ompl_thin_wrap.hpp"
9
+
10
+ namespace plainmp::ompl_wrapper {
11
+
12
+ // Fixed-goal Python interface. Input conversion, returned matrix and optional
13
+ // OMPL refinement are boundary allocations; the search reuses constructor
14
+ // storage, including the termination condition and constraint input vector.
15
+ class PlainmpRRTCPlanner {
16
+ public:
17
+ PlainmpRRTCPlanner(
18
+ const std::vector<double>& lb,
19
+ const std::vector<double>& ub,
20
+ constraint::IneqConstraintBase::Ptr constraint,
21
+ size_t max_calls,
22
+ const ValidatorConfig& validator,
23
+ std::optional<double> range = std::nullopt,
24
+ const std::optional<PlainmpRRTCSettings>& settings = std::nullopt)
25
+ : validity_buffer_(lb.size()), stop_([this] {
26
+ return csi_->is_valid_call_count_ >= csi_->max_is_valid_call_ ||
27
+ timed_out();
28
+ }) {
29
+ if (!constraint || constraint->q_dim() != lb.size() || lb.empty() ||
30
+ lb.size() != ub.size())
31
+ throw std::invalid_argument("constraint and bounds dimensions differ");
32
+ for (size_t i = 0; i < lb.size(); ++i)
33
+ if (!std::isfinite(lb[i]) || !std::isfinite(ub[i]) || lb[i] >= ub[i])
34
+ throw std::invalid_argument("bounds must be finite and ordered");
35
+ const auto positive = [](double x) { return std::isfinite(x) && x > 0; };
36
+ if ((validator.type == ValidatorConfig::Type::BOX &&
37
+ (validator.box_width.size() != lb.size() ||
38
+ !std::all_of(validator.box_width.begin(), validator.box_width.end(),
39
+ positive))) ||
40
+ (validator.type == ValidatorConfig::Type::EUCLIDEAN &&
41
+ !positive(validator.resolution)))
42
+ throw std::invalid_argument(
43
+ "motion resolution must be positive and finite");
44
+ csi_ = std::make_unique<CollisionAwareSpaceInformation>(
45
+ lb, ub, constraint, max_calls, validator);
46
+ csi_->si_->setStateValidityChecker([this](const ob::State* state) {
47
+ if (csi_->is_valid_call_count_ >= csi_->max_is_valid_call_ ||
48
+ (timeout_ && csi_->is_valid_call_count_ % 64 == 0 && timed_out()))
49
+ return false;
50
+ validity_buffer_ = Eigen::Map<const Eigen::VectorXd>(
51
+ state->as<ob::RealVectorStateSpace::StateType>()->values,
52
+ validity_buffer_.size());
53
+ ++csi_->is_valid_call_count_;
54
+ return csi_->ineq_cst_->is_valid(validity_buffer_);
55
+ });
56
+ csi_->si_->setup();
57
+ planner_ = std::make_unique<PlainmpRRTC>(
58
+ csi_->si_, settings.value_or(PlainmpRRTCSettings{}));
59
+ if (range)
60
+ planner_->setRange(*range);
61
+ }
62
+
63
+ std::optional<Eigen::MatrixXd> solve(
64
+ const std::vector<double>& start,
65
+ const std::optional<std::vector<double>>& goal,
66
+ const std::vector<RefineType>& refine_seq,
67
+ std::optional<double> timeout,
68
+ const std::optional<GoalSamplerFn>& goal_sampler,
69
+ std::optional<size_t> /*max_goal_sample_count*/ = std::nullopt) {
70
+ if (goal_sampler || !goal)
71
+ throw std::invalid_argument(
72
+ "PlainmpRRTCPlanner requires a fixed goal; use OMPLSolver for IK "
73
+ "goals");
74
+ const size_t dimension = validity_buffer_.size();
75
+ const auto valid = [dimension](const std::vector<double>& q) {
76
+ return q.size() == dimension &&
77
+ std::all_of(q.begin(), q.end(),
78
+ [](double x) { return std::isfinite(x); });
79
+ };
80
+ if (!valid(start) || !valid(*goal))
81
+ throw std::invalid_argument(
82
+ "start and goal must have the space dimension and finite values");
83
+ if (timeout && (!std::isfinite(*timeout) || *timeout < 0))
84
+ throw std::invalid_argument("timeout must be nonnegative and finite");
85
+ for (auto refine : refine_seq)
86
+ if (refine != RefineType::SHORTCUT && refine != RefineType::BSPLINE)
87
+ throw std::invalid_argument("unknown refine type");
88
+ timeout_ = timeout;
89
+ csi_->resetCount();
90
+ solve_start_ = std::chrono::steady_clock::now();
91
+ const auto status = planner_->solveFixed(start.data(), goal->data(), stop_);
92
+ // As in the existing wrapper, exclude output matrix allocation/copy.
93
+ record_time();
94
+ if (status != ob::PlannerStatus::EXACT_SOLUTION)
95
+ return std::nullopt;
96
+
97
+ if (refine_seq.empty()) {
98
+ Eigen::MatrixXd result(planner_->pathSize(), dimension);
99
+ for (size_t i = 0; i < planner_->pathSize(); ++i)
100
+ result.row(i) =
101
+ Eigen::Map<const Eigen::VectorXd>(planner_->pathPoint(i), dimension)
102
+ .transpose();
103
+ return result;
104
+ }
105
+ og::PathGeometric path(csi_->si_);
106
+ path.getStates().reserve(planner_->pathSize());
107
+ ob::RealVectorStateSpace::StateType state;
108
+ for (size_t i = 0; i < planner_->pathSize(); ++i) {
109
+ state.values = const_cast<double*>(planner_->pathPoint(i));
110
+ path.append(&state);
111
+ }
112
+ og::PathSimplifier simplifier(csi_->si_);
113
+ for (auto refine : refine_seq) {
114
+ if (stop_)
115
+ break;
116
+ if (refine == RefineType::SHORTCUT) {
117
+ #ifdef OMPL_OLD_VERSION
118
+ simplifier.shortcutPath(path);
119
+ #else
120
+ simplifier.partialShortcutPath(path);
121
+ #endif
122
+ } else {
123
+ simplifier.smoothBSpline(path);
124
+ }
125
+ }
126
+ record_time();
127
+ Eigen::MatrixXd result(path.getStateCount(), dimension);
128
+ for (size_t i = 0; i < path.getStateCount(); ++i)
129
+ result.row(i) = Eigen::Map<const Eigen::VectorXd>(
130
+ path.getState(i)
131
+ ->as<ob::RealVectorStateSpace::StateType>()
132
+ ->values,
133
+ dimension)
134
+ .transpose();
135
+ return result;
136
+ }
137
+
138
+ size_t getCallCount() const {
139
+ return csi_->is_valid_call_count_;
140
+ }
141
+ size_t get_ns_internal() const {
142
+ return ns_internal_;
143
+ }
144
+ size_t getNodeCount() const {
145
+ return planner_->nodeCount();
146
+ }
147
+
148
+ private:
149
+ bool timed_out() const {
150
+ return timeout_ && std::chrono::duration<double>(
151
+ std::chrono::steady_clock::now() - solve_start_)
152
+ .count() >= *timeout_;
153
+ }
154
+ void record_time() {
155
+ ns_internal_ = std::chrono::duration_cast<std::chrono::nanoseconds>(
156
+ std::chrono::steady_clock::now() - solve_start_)
157
+ .count();
158
+ }
159
+ std::unique_ptr<CollisionAwareSpaceInformation> csi_;
160
+ std::unique_ptr<PlainmpRRTC> planner_;
161
+ Eigen::VectorXd validity_buffer_;
162
+ std::optional<double> timeout_;
163
+ std::chrono::steady_clock::time_point solve_start_;
164
+ size_t ns_internal_ = 0;
165
+ ob::PlannerTerminationCondition stop_;
166
+ };
167
+ } // namespace plainmp::ompl_wrapper
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "plainmp"
7
- version = "0.3.6.dev1"
7
+ version = "0.3.7"
8
8
  requires-python = ">=3.8"
9
9
  description = "Very fast motion planning for articulated robot, through a bit of premature-optimization (C++ core with Python bindings) *less than 1ms for moderate problems"
10
10
  authors = [{name = "Hirokazu Ishida"}]
@@ -12,12 +12,13 @@ license = {text = "MPL2.0 for C++ core and BSD3 for Python bindings"}
12
12
  dependencies = [
13
13
  "rospkg",
14
14
  "numpy",
15
- "scipy",
15
+ "scipy",
16
16
  "scikit-robot>=0.0.44",
17
17
  "pyyaml",
18
18
  "robot_descriptions",
19
19
  "osqp<1.0.0",
20
- "tyro"
20
+ "tyro",
21
+ "matplotlib>=3.7.5",
21
22
  ]
22
23
 
23
24
  [dependency-groups]
@@ -27,3 +28,4 @@ lint = ["autoflake", "black==22.6.0", "codespell", "flake8", "isort"]
27
28
  [tool.scikit-build]
28
29
  # see: https://scikit-build-core.readthedocs.io/en/latest/configuration/index.html#customizing-the-built-wheel
29
30
  wheel.install-dir = "plainmp"
31
+ wheel.license-files = ["LICENSE-BSD3", "cpp/LICENSE-MPL2", "third/ompl_rrtc/LICENSE"]
@@ -13,6 +13,8 @@ from plainmp.trajectory import Trajectory
13
13
  from ._plainmp.ompl import ( # noqa: F401
14
14
  ERTConnectPlanner,
15
15
  OMPLPlanner,
16
+ PlainmpRRTCPlanner,
17
+ PlainmpRRTCSettings,
16
18
  RefineType,
17
19
  ValidatorConfig,
18
20
  ValidatorType,
@@ -27,6 +29,7 @@ class Algorithm(Enum):
27
29
  KPIECE1 = "KPIECE1"
28
30
  LBKPIECE1 = "LBKPIECE1"
29
31
  RRTConnect = "RRTConnect"
32
+ PlainmpRRTC = "plainmp_rrtc"
30
33
  RRT = "RRT"
31
34
  RRTstar = "RRTstar"
32
35
  EST = "EST"
@@ -40,7 +43,7 @@ class Algorithm(Enum):
40
43
  class OMPLSolverConfig:
41
44
  n_max_call: int = 1000000
42
45
  n_max_ik_trial: int = 100
43
- algorithm: Algorithm = Algorithm.RRTConnect
46
+ algorithm: Algorithm = Algorithm.PlainmpRRTC
44
47
  algorithm_range: Optional[float] = 2.0
45
48
  refine_seq: Sequence[RefineType] = tuple()
46
49
  shortcut: bool = False
@@ -55,6 +58,7 @@ class OMPLSolverConfig:
55
58
  False # use goal sampler in unidirectional planner. Use only when the goal is not a point
56
59
  )
57
60
  max_goal_sampler_count: int = 100
61
+ plainmp_rrtc_settings: Optional[PlainmpRRTCSettings] = None
58
62
 
59
63
  def __post_init__(self):
60
64
  if len(self.refine_seq) > 0:
@@ -246,6 +250,16 @@ class OMPLSolver:
246
250
  self.config.ertconnect_omega_max,
247
251
  self.config.ertconnect_eps,
248
252
  )
253
+ elif self.config.algorithm == Algorithm.PlainmpRRTC:
254
+ planner = PlainmpRRTCPlanner(
255
+ problem.lb,
256
+ problem.ub,
257
+ problem.global_ineq_const,
258
+ self.config.n_max_call,
259
+ vconfig,
260
+ self.config.algorithm_range,
261
+ self.config.plainmp_rrtc_settings,
262
+ )
249
263
  else:
250
264
  planner = OMPLPlanner(
251
265
  problem.lb,
@@ -0,0 +1,99 @@
1
+ /* Copyright (C) 2026 Hirokazu Ishida
2
+ * This Source Code Form is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. See https://mozilla.org/MPL/2.0/.
4
+ */
5
+ // Run through CMake with -DPLAINMP_BUILD_TESTS=ON, then ctest --test-dir
6
+ // build/native.
7
+ #include <cmath>
8
+ #include <cstdlib>
9
+ #include <iostream>
10
+ #include <new>
11
+ #include <random>
12
+ #include <stdexcept>
13
+ #include <vector>
14
+ #include "ompl_rrtc/batch_nearest.hpp"
15
+
16
+ static size_t allocations = 0;
17
+ void* operator new(size_t size) {
18
+ ++allocations;
19
+ if (void* p = std::malloc(size ? size : 1))
20
+ return p;
21
+ throw std::bad_alloc();
22
+ }
23
+ void* operator new[](size_t size) {
24
+ return ::operator new(size);
25
+ }
26
+ void operator delete(void* p) noexcept {
27
+ std::free(p);
28
+ }
29
+ void operator delete[](void* p) noexcept {
30
+ std::free(p);
31
+ }
32
+ void operator delete(void* p, size_t) noexcept {
33
+ std::free(p);
34
+ }
35
+ void operator delete[](void* p, size_t) noexcept {
36
+ std::free(p);
37
+ }
38
+
39
+ void require(bool condition, const char* message) {
40
+ if (!condition)
41
+ throw std::runtime_error(message);
42
+ }
43
+
44
+ void test_nearest() {
45
+ using plainmp::ompl_wrapper::BatchNearest;
46
+ std::mt19937 rng(42);
47
+ std::uniform_real_distribution<double> uniform(-1, 1);
48
+ for (size_t dim : {1, 2, 7, 8, 14}) {
49
+ constexpr size_t capacity = 4096;
50
+ std::vector<double> points(capacity * dim), query(dim);
51
+ for (double& x : points)
52
+ x = uniform(rng);
53
+ BatchNearest tree, linear;
54
+ tree.allocate(points.data(), dim, capacity);
55
+ linear.allocate(points.data(), dim, capacity, false);
56
+ require(tree.nearest(query.data()).first == BatchNearest::none &&
57
+ linear.nearest(query.data()).first == BatchNearest::none,
58
+ "empty nearest");
59
+ for (bool duplicates : {false, true}) {
60
+ tree.clear();
61
+ linear.clear();
62
+ if (duplicates)
63
+ std::fill(points.begin(), points.end(), 0.0);
64
+ const size_t before = allocations;
65
+ for (size_t i = 0; i < capacity; ++i) {
66
+ tree.insert(i);
67
+ linear.insert(i);
68
+ if (i % 37 != 0 && i != capacity - 1)
69
+ continue;
70
+ for (double& x : query)
71
+ x = uniform(rng);
72
+ const auto actual = tree.nearest(query.data());
73
+ require(actual == linear.nearest(query.data()),
74
+ "KD-tree/linear mismatch");
75
+ double best = std::numeric_limits<double>::infinity();
76
+ size_t index = 0;
77
+ for (size_t j = 0; j <= i; ++j) {
78
+ double distance = 0;
79
+ for (size_t d = 0; d < dim; ++d) {
80
+ const double delta = points[j * dim + d] - query[d];
81
+ distance += delta * delta;
82
+ }
83
+ if (distance < best) {
84
+ best = distance;
85
+ index = j;
86
+ }
87
+ }
88
+ require(actual.first == index && actual.second == best,
89
+ "nearest disagrees with brute force");
90
+ }
91
+ require(allocations == before, "allocation inside nearest insert/query");
92
+ }
93
+ }
94
+ }
95
+
96
+ int main() {
97
+ test_nearest();
98
+ std::cout << "BatchNearest native tests passed\n";
99
+ }