plainmp 0.3.6.dev1__tar.gz → 0.3.8__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.
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/.github/workflows/build_and_test.yaml +1 -1
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/.github/workflows/check_format.yaml +4 -3
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/CMakeLists.txt +31 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/PKG-INFO +2 -1
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/bindings/kinematics.cpp +4 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/bindings/ompl_wrapper.cpp +23 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/kinematics/kinematics.cpp +27 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/kinematics/kinematics.hpp +3 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/algorithm_selector.cpp +2 -0
- plainmp-0.3.8/cpp/plainmp/ompl/plainmp_rrtc_wrap.hpp +167 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/pyproject.toml +5 -3
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/kinematics.pyi +10 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/ompl_solver.py +15 -1
- plainmp-0.3.8/tests/cpp/test_batch_nearest.cpp +99 -0
- plainmp-0.3.8/tests/cpp/test_plainmp_rrtc.cpp +286 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/tests/test_kinematics.py +76 -0
- plainmp-0.3.8/tests/test_plainmp_rrtc.py +144 -0
- plainmp-0.3.8/third/ompl_rrtc/LICENSE +33 -0
- plainmp-0.3.8/third/ompl_rrtc/batch_nearest.hpp +173 -0
- plainmp-0.3.8/third/ompl_rrtc/plainmp_rrtc.cpp +231 -0
- plainmp-0.3.8/third/ompl_rrtc/plainmp_rrtc.hpp +71 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/uv.lock +1267 -1
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/.flake8 +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/.gitattributes +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/.github/workflows/check_mpl_requirement.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/.github/workflows/check_pypi_install.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/.github/workflows/release.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/.gitignore +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/LICENSE-BSD3 +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/README.md +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/.gitignore +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/LICENSE-MPL2 +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/add_header.sh +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/bindings/bindings.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/bindings/constraint.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/bindings/kdtree.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/bindings/primitive.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/bindings/python.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/collision/kdtree.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/collision/kdtree.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/collision/primitive_sdf.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/composite_constraint.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_com_in_polytope.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_com_in_polytope.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_config_point.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_config_point.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_fixed_zaxis.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_fixed_zaxis.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_link_pose.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_link_pose.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_link_position_bound.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_link_position_bound.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_relative_pose.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_relative_pose.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_sphere_collision.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/primitive_sphere_collision.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/sequential_constraint.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/constraints/sequential_constraint.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/kinematics/algorithm.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/kinematics/data_structure.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/kinematics/kinematic_model_wrapper.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/kinematics/kinematic_model_wrapper.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/kinematics/transform.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/.gitignore +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/algorithm_selector.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/custom_goal_samplable_region.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/custom_goal_samplable_region.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/generate_sequence.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/motion_validator.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/motion_validator.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/ompl_thin_wrap.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/unidirectional_modified.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/cpp/plainmp/ompl/unidirectional_modified.hpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/attach_box_ik_and_plan.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/bench/.gitignore +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/bench/fetch_plan.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/bench/panda_plan.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/beta/humanoid_lift_and_place_box.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/beta/humanoid_planning.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/fetch_ik.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/fetch_plan.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/misc/fetch_visualize_coll_spheres.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/misc/panda_visualize_coll_spheres.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/misc/pr2_visualize_coll_spheres.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/openarm/openarm_dualarm.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/openarm/openarm_larm.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/openarm/openarm_rarm.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/openarm_gravity_compensation.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/panda_plan.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/pr2_dualarm_ik_and_plan.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/pr2_rarm_ik_and_plan.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/example/pr2_with_mobile_base.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/format.sh +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/__init__.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/assets/openarm_v10.urdf +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/fetch.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/jaxon.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/openarm_v10/collision_spheres.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/openarm_v10/openarm_v10_dual.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/openarm_v10/openarm_v10_larm.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/openarm_v10/openarm_v10_rarm.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/panda.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/pr2_base_only.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/pr2_common/aux.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/pr2_common/collision_spheres.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/pr2_common/end_effectors.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/pr2_dualarm.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/pr2_larm.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/conf/pr2_rarm.yaml +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/constraint.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/constraint.pyi +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/ik.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/kdtree.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/kdtree.pyi +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/kinematics.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/manifold_rrt/__init__.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/manifold_rrt/_manifold_rrt_algorithms.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/manifold_rrt/manifold_rrt_solver.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/nlp_solver/__init__.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/nlp_solver/osqp_sqp.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/nlp_solver/sqp_based_solver.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/parallel.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/problem.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/psdf.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/psdf.pyi +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/robot_spec.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/script/bubblify_to_plainmp.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/trajectory.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/src/plainmp/utils.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/tests/test_constraints.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/tests/test_ik.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/tests/test_kdtree.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/tests/test_manifold_rrt.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/tests/test_ompl_solver.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/tests/test_psdf.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/tests/test_robot_spec.py +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/ompl-ertconnect/CMakeLists.txt +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/ompl-ertconnect/README.md +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/ompl-ertconnect/ertconnect/ERT.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/ompl-ertconnect/ertconnect/ERTConnect.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/ompl-ertconnect/ertconnect/ert/PlannerData.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/ompl-ertconnect/ertconnect/src/ERT.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/ompl-ertconnect/ertconnect/src/ERTConnect.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/.gitignore +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/CMakeLists.txt +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/README.md +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/LICENSE +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_exception/exception.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_model/color.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_model/joint.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_model/link.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_model/model.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_model/pose.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_model/types.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_model/utils.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_parser/exportdecl.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_parser/urdf_parser.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/include/urdf_world/types.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/src/joint.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/src/link.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/src/model.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/src/pose.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/tinyxml/CMakeLists.txt +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/tinyxml/tinystr.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/tinyxml/tinystr.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/tinyxml/tinyxml.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/tinyxml/tinyxml.h +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/tinyxml/tinyxmlerror.cpp +0 -0
- {plainmp-0.3.6.dev1 → plainmp-0.3.8}/third/urdf_parser/tinyxml/tinyxmlparser.cpp +0 -0
|
@@ -26,9 +26,10 @@ jobs:
|
|
|
26
26
|
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
27
27
|
with:
|
|
28
28
|
enable-cache: true
|
|
29
|
+
version: "0.7.6"
|
|
29
30
|
|
|
30
31
|
- name: Install formatters
|
|
31
|
-
run: uv sync --
|
|
32
|
+
run: uv sync --only-group lint
|
|
32
33
|
|
|
33
34
|
- name: install clang-format
|
|
34
35
|
run: |
|
|
@@ -44,9 +45,9 @@ jobs:
|
|
|
44
45
|
|
|
45
46
|
- name: Fail if format.sh modified files
|
|
46
47
|
run: |
|
|
47
|
-
if ! git diff --quiet; then
|
|
48
|
+
if ! git diff --quiet -- . ':!uv.lock'; then
|
|
48
49
|
echo "::error::Files are not properly formatted. Please run ./format.sh locally and commit the changes."
|
|
49
50
|
echo "--- git diff (summary) ---"
|
|
50
|
-
git --no-pager diff
|
|
51
|
+
git --no-pager diff -- . ':!uv.lock'
|
|
51
52
|
exit 1
|
|
52
53
|
fi
|
|
@@ -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.
|
|
3
|
+
Version: 0.3.8
|
|
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
|
|
|
@@ -78,6 +78,10 @@ void bind_kinematics_submodule(nb::module_& m) {
|
|
|
78
78
|
nb::arg("joint_ids"), nb::arg("positions"),
|
|
79
79
|
nb::arg("base_type") = BaseType::FIXED, nb::arg("accurate") = true)
|
|
80
80
|
.def("get_link_ids", &utils::_KinematicModel::get_link_ids)
|
|
81
|
+
.def("get_link_mass", &utils::_KinematicModel::get_link_mass,
|
|
82
|
+
nb::arg("link_id"))
|
|
83
|
+
.def("set_link_mass", &utils::_KinematicModel::set_link_mass,
|
|
84
|
+
nb::arg("link_id"), nb::arg("mass"))
|
|
81
85
|
.def("get_joint_ids", &utils::_KinematicModel::get_joint_ids);
|
|
82
86
|
}
|
|
83
87
|
|
|
@@ -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,
|
|
@@ -275,6 +275,33 @@ std::vector<size_t> KinematicModel<Scalar>::get_link_ids(
|
|
|
275
275
|
return link_ids;
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
+
template <typename Scalar>
|
|
279
|
+
Scalar KinematicModel<Scalar>::get_link_mass(size_t link_id) const {
|
|
280
|
+
for (size_t i = 0; i < com_link_ids_.size(); i++) {
|
|
281
|
+
if (com_link_ids_[i] == link_id) {
|
|
282
|
+
return link_masses_[i];
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
throw std::invalid_argument("no mass data for link id " +
|
|
286
|
+
std::to_string(link_id));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
template <typename Scalar>
|
|
290
|
+
void KinematicModel<Scalar>::set_link_mass(size_t link_id, Scalar mass) {
|
|
291
|
+
if (!std::isfinite(mass) || mass < 0) {
|
|
292
|
+
throw std::invalid_argument("mass must be finite and non-negative");
|
|
293
|
+
}
|
|
294
|
+
for (size_t i = 0; i < com_link_ids_.size(); i++) {
|
|
295
|
+
if (com_link_ids_[i] == link_id) {
|
|
296
|
+
total_mass_ += mass - link_masses_[i];
|
|
297
|
+
link_masses_[i] = mass;
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
throw std::invalid_argument("no mass data for link id " +
|
|
302
|
+
std::to_string(link_id));
|
|
303
|
+
}
|
|
304
|
+
|
|
278
305
|
template <typename Scalar>
|
|
279
306
|
size_t KinematicModel<Scalar>::add_new_link(
|
|
280
307
|
size_t parent_id,
|
|
@@ -128,6 +128,9 @@ class KinematicModel {
|
|
|
128
128
|
|
|
129
129
|
std::vector<size_t> get_link_ids(std::vector<std::string> link_names) const;
|
|
130
130
|
|
|
131
|
+
Scalar get_link_mass(size_t link_id) const;
|
|
132
|
+
void set_link_mass(size_t link_id, Scalar mass);
|
|
133
|
+
|
|
131
134
|
const Transform& get_link_pose(size_t link_id) const {
|
|
132
135
|
if (!transform_cache_.is_cached(link_id)) {
|
|
133
136
|
build_cache_until(link_id);
|
|
@@ -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.
|
|
7
|
+
version = "0.3.8"
|
|
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"]
|
|
@@ -56,3 +56,13 @@ class KinematicModel:
|
|
|
56
56
|
"""
|
|
57
57
|
...
|
|
58
58
|
def get_joint_ids(self, joint_names: List[str]) -> List[int]: ...
|
|
59
|
+
def get_link_ids(self, link_names: List[str]) -> List[int]: ...
|
|
60
|
+
def get_link_mass(self, link_id: int) -> float:
|
|
61
|
+
"""Return the mass in kg. Raises ValueError if the link has no inertial data."""
|
|
62
|
+
...
|
|
63
|
+
def set_link_mass(self, link_id: int, mass: float) -> None:
|
|
64
|
+
"""Set a finite, non-negative mass in kg, preserving the local COM.
|
|
65
|
+
|
|
66
|
+
Raises ValueError for invalid masses or links without inertial data.
|
|
67
|
+
"""
|
|
68
|
+
...
|
|
@@ -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.
|
|
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
|
+
}
|