Fetch-Planning
A whole-body motion planning library for the Fetch mobile manipulator. Mirrors the Autolife-Planning interface (same public API, same module layout) but targets the 11-DOF Fetch robot with a nonholonomic differential-drive base, an IKFast analytic IK backend, and whole-body VAMP collision checking.
Status: early scaffold / under active development. The public interface is stable; build steps and examples below describe the target state.
Motivation
Autolife-Planning wraps OMPL over a VAMP collision backend for the Autolife humanoid. Fetch-Planning is a sister library that ports the same stack to Fetch. The key differences from a "default Fetch in VAMP" setup are:
- Whole-body — the planner reasons over the mobile base + torso + arm (11 DOF), not just the 8-DOF arm_with_torso chain.
- Nonholonomic base — the base
(x, y, θ)is constrained to differential-drive motion (forward/backward along the heading, in-place rotation, no lateral sliding). This is enforced in OMPL via aCompoundStateSpace(ReedsSheppStateSpace + RealVectorStateSpace)so every planner automatically respects the curvature constraint. - IKFast backend — in addition to TRAC-IK and Pink, Fetch-Planning
ships a pre-generated OpenRAVE
ikfastanalytic solver for Fetch's 8-DOFarm_with_torsochain. IKFast gives ~40 µs / solve and dense null-space sweeps. - Kinodynamic planning —
MotionPlanner.plan_kinodynamic(FLASK, flatness-based kinodynamic RRT-Connect) returns time-parameterised trajectories that respect joint and base velocity / acceleration limits with an exactly nonholonomic base, ready for feed-forward + PID tracking. See docs/planning/kinodynamic.md.
Everything else — the public API (create_ik_solver, create_planner,
SE3Pose, PlannerConfig, IKConfig, constrained planning via CasADi),
the overall module layout, the VAMP/OMPL stack — is byte-identical to
Autolife-Planning so downstream code can switch robots by changing a
single import.
Architecture
┌───────────────────────────────────────────────────────────────┐
│ fetch_planning/ (Python) │
│ │
│ create_planner(...) create_ik_solver(...) │
│ │ │ │
│ ▼ ▼ │
│ MotionPlanner IKSolverBase │
│ │ ├── TracIKSolver (pytracik) │
│ │ ├── PinkIKSolver (pinocchio+pink) │
│ │ └── IKFastSolver (ikfast_fetch) │
└────────┼───────────────────────────────────────────────────────┘
│
┌────────▼───────────────────────────────────────────────────────┐
│ _ompl_vamp (C++/nanobind extension) │
│ │
│ ┌───────────── OMPL frontend ────────────┐ │
│ │ │ │
│ │ arm-only subgroups: │ │
│ │ RealVectorStateSpace(N) │ │
│ │ │ │
│ │ subgroups touching the base: │ │
│ │ CompoundStateSpace │ │
│ │ ├── ReedsSheppStateSpace(ρ=0.2) │ ← nonholonomic │
│ │ └── RealVectorStateSpace(arm_dof) │ │
│ │ │ │
│ │ Planners: RRT-Connect, KPIECE, PRM*, │ │
│ │ BIT*, RRT*, … │ │
│ └────────────────┬───────────────────────┘ │
│ │ │
│ ▼ │
│ StateValidityChecker + MotionValidator │
│ │ │
└───────────────────┼────────────────────────────────────────────┘
│
┌───────────────────▼────────────────────────────────────────────┐
│ VAMP backend (header-only, SIMD) │
│ │
│ third_party/vamp → H-tr/vamp @ fetch-planning branch │
│ vamp::robots::FetchWholeBody (11 DOF spherized model) │
└────────────────────────────────────────────────────────────────┘
Robot layout (11 DOF)
| Index | Joint | Group | Notes |
|---|---|---|---|
| 0 | base_x_joint |
base | world frame |
| 1 | base_y_joint |
base | world frame |
| 2 | base_theta_joint |
base | heading (nonholonomic with 0,1) |
| 3 | torso_lift_joint |
torso | prismatic 0 – 0.386 m |
| 4 | shoulder_pan_joint |
arm | |
| 5 | shoulder_lift_joint |
arm | |
| 6 | upperarm_roll_joint |
arm | ikfast free-param #2 |
| 7 | elbow_flex_joint |
arm | |
| 8 | forearm_roll_joint |
arm | |
| 9 | wrist_flex_joint |
arm | |
| 10 | wrist_roll_joint |
arm |
Planning subgroups (fetch_planning.fetch.PLANNING_SUBGROUPS):
fetch_base— 3 DOF, nonholonomicfetch_arm— 7 DOF (arm only, torso+base fixed)fetch_arm_with_torso— 8 DOF (arm + torso, base fixed) ← ikfast chainfetch_base_arm— 10 DOF (base + arm, torso fixed)fetch_whole_body— 11 DOF (everything)
Implementation plan
This repo is being built up in phases. See the issue tracker for task status.
Phase 1 — scaffold & public API ✅
- Copy Autolife-Planning structure, rename to
fetch_planning/ - Rewrite
fetch.pyfor the Fetch 11-DOF layout - Vendor Fetch URDFs + spherized meshes under
fetch_planning/resources/robot/fetch/ -
CMakeLists.txtwired for the three extensions:_ompl_vamp,pytracik,ikfast_fetch - Public entry points (
create_planner,create_ik_solver) importable without errors
Phase 2 — whole-body Fetch VAMP model ✅
VAMP stays pinned to upstream; the Fetch-specific spherized models live alongside the OMPL bridge, not in a fork.
-
ext/ompl_vamp/include/vamp/robots/fetch_whole_body.hh— 11-DOF spherized Fetch model whosesphere_fkapplies the(x, y, θ)base transform before the arm FK. Mirrors the pattern used byautolife_body_coupled.hh. -
ext/ompl_vamp/include/vamp/robots/fetch_base.hh— 3-DOF base-only spherized model for base-only planning subgroups. -
third_party/vamppinned to upstreamH-tr/vamp@main(no fork).
Phase 3 — OMPL frontend adaptations ✅
-
ext/ompl_vamp/validity.hpp: usesvamp::robots::FetchWholeBody;extract_real_statehandlesCompoundStateTypewhen the base is part of the active subgroup. -
ext/ompl_vamp/planner.hpp: whenactive_indicesinclude any base joint, constructsCompoundStateSpace(SE2StateSpace(ρ) + RealVectorStateSpace(N))where the SE2 component is eitherDubinsStateSpace(forward-only, default) orReedsSheppStateSpace(reverse allowed). Both inherit fromSE2StateSpace, so OMPL's built-in distance/interpolate functions make every planner respect the nonholonomic constraint for free. - Motion validator for the compound space: reads the base state via
state->as<CompoundState>()->as<SE2StateSpace::StateType>(0), the arm state via...->as<RealVectorStateSpace::StateType>(1), packs both into aFetchWholeBody::Configuration, and calls VAMP.
Phase 4 — IK backends ✅
- Vendor
ikfast_fetch_module.cpp(8-DOFTransform6D, free params =torso_lift+upperarm_roll) -
fetch_planning/kinematics/ikfast_solver.pyimplementingIKSolverBasewith a seed-aware random-restart sampler over the two free parameters -
create_ik_solver(backend="ikfast")factory route -
trac_ik+pinkbackends working on Fetch chains (arm,arm_with_torso,whole_body)
Phase 5 — examples, build, ship ✅
-
examples/ik/basic.py+basic_vis.py+trac_ik_vis.py— Fetch arm FK/IK round-trip for each backend -
examples/planning/motion.py—fetch_armplanning over a table pointcloud -
examples/planning/nonholonomic.py—fetch_whole_bodynonholonomic base + arm motion around obstacles -
examples/planning/{subgroup,multilevel_single_step,time_parameterization}.py,examples/planning/constrained/,examples/planning/cost/,examples/ik/constrained*.py— constrained / cost / multilevel parity with Autolife-Planning -
pixi run buildsucceeds end-to-end; examples run
Phase 6 — testing & CI ✅
-
tests/smoke-test suite covering public entry points on every Fetch chain and every installed IK backend - GitHub Actions workflow (
.github/workflows/test.yml) that installs pixi, builds the native extensions, and runs the smoke tests on every push and PR
Usage (target interface)
import numpy as np
from fetch_planning.kinematics import create_ik_solver
from fetch_planning.planning import create_planner
from fetch_planning.types import SE3Pose, IKConfig, PlannerConfig
from fetch_planning.fetch import HOME_JOINTS
# --- IK (three interchangeable backends) ---
solver = create_ik_solver("arm_with_torso", backend="ikfast")
target = solver.fk(HOME_JOINTS[3:]) # torso + 7 arm joints
target.position[0] += 0.10
result = solver.solve(target, seed=HOME_JOINTS[3:])
print(result.joint_positions)
# --- Whole-body motion planning with nonholonomic base ---
planner = create_planner(
"fetch_whole_body",
config=PlannerConfig(planner_name="rrtc", time_limit=5.0),
pointcloud=table_points,
)
start = HOME_JOINTS.copy()
goal = HOME_JOINTS.copy()
goal[0], goal[1], goal[2] = 1.0, 0.5, 0.3 # drive to new base pose
goal[4] += 0.5 # and rotate shoulder
result = planner.plan(start, goal)
if result.success:
for waypoint in result.path:
print(waypoint)
Project layout
Fetch-Planning/
├── CMakeLists.txt # three extensions: _ompl_vamp, pytracik, ikfast_fetch
├── pyproject.toml # scikit-build-core
├── pixi.toml # conda env + build tasks
├── .gitmodules # vamp, ompl, cricket, foam
│
├── fetch_planning/ # Python package (mirrors autolife_planning/)
│ ├── fetch.py # 11-DOF Fetch layout (joint groups, HOME, …)
│ ├── types/ # SE3Pose, IKConfig, PlannerConfig, …
│ ├── trajectory/ # TOPP-RA time parameterization
│ ├── kinematics/ # TracIK / Pink / IKFast solvers + factory
│ ├── planning/ # MotionPlanner, SymbolicContext, Constraint
│ ├── envs/ # PyBullet scene wrapper
│ └── resources/robot/fetch/ # fetch.urdf + fetch_spherized.urdf + meshes
│
├── ext/
│ ├── ompl_vamp/ # nanobind OMPL↔VAMP bridge
│ │ └── include/vamp/robots/
│ │ ├── fetch_whole_body.hh # 11-DOF spherized Fetch (base+torso+arm)
│ │ └── fetch_base.hh # 3-DOF base-only spherized Fetch
│ ├── time_parameterization/ # vendored TOPP-RA C++ core (nanobind)
│ ├── trac_ik/ # vendored TRAC-IK C++ (pybind11)
│ └── ikfast_fetch/ # ikfast_fetch_module.cpp — OpenRAVE analytic IK
│
├── tests/ # pytest smoke tests (chains × backends)
│
└── third_party/
├── vamp/ # H-tr/vamp @ main (unmodified upstream)
└── ompl/ # ompl/ompl (upstream)
Dependencies
- Build: cmake ≥ 3.20, ninja, C++17 compiler, nanobind, pybind11, Boost (serialization + filesystem + system), Eigen3, LAPACK
- Runtime (conda): python ≥ 3.10, numpy, scipy, pinocchio, pink, orocos-kdl, nlopt
- Optional: pybullet (visualization), casadi (constrained planning)
Pixi handles all of this — pixi install then pixi run build.
Testing
Smoke tests live under tests/ and exercise the public entry points
(create_ik_solver, create_planner) across every Fetch chain and every
installed IK backend. Run them locally with:
pixi run test
The .github/workflows/test.yml action runs the same suite on every push
and pull request against main.
License & attribution
- The
ikfast_fetchanalytic solver is generated by OpenRAVE'sikfast(Apache 2.0, © Rosen Diankov). - VAMP is from the KavrakiLab (BSD); we pin
third_party/vampto upstream unmodified and keep the Fetch-specific spherized models underext/ompl_vamp/include/vamp/robots/. - The time parameterizer vendors the C++ core of
toppra (MIT, © Hung Pham)
unmodified under
ext/time_parameterization/toppra/. - Everything else © 2026 H-tr, same license as Autolife-Planning.
Metadata
Release files for fetch-planning 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
Total release size: 144.5 MB
Release files / fetch_planning-0.3.0-cp314-cp314-manylinux_2_34_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp314-cp314-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 14.7 MB |
| Tags | CPython 3.14 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
05b699c2c6a1cd1ba4987b45e61c23e6d8752adb235bce4f75933cfc33bccbae
|
|
BLAKE2b-256 checksum How to use checksums |
543ca10f13e33cad722f8446a1f3f28ae7509f466ac7575ae0c522b7d5074bf6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fetch_planning-0.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 14.2 MB |
| Tags | CPython 3.14 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
3b7052dad87e350ebb9c5118c7183b25c9304948d02744d42fe6a0e79edd2535
|
|
BLAKE2b-256 checksum How to use checksums |
32c04bfead2cc451f99f520a54570addd353ee2b9cbe5dc070cca93d394bbe14
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fetch_planning-0.3.0-cp313-cp313-manylinux_2_34_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp313-cp313-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 14.7 MB |
| Tags | CPython 3.13 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
6380c7a7bb13e2af7788ffbc62db62738dcd7035db2d161db4db41aab8873728
|
|
BLAKE2b-256 checksum How to use checksums |
d9dd7f59d6b0ff03608a19518eddb047fe35a69b8d7b624a3009485b88ca0d86
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fetch_planning-0.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 14.2 MB |
| Tags | CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
49e41894c7e8dcad2d3b267d1c59b1e60006bb2ce8c5ec47292a1e056c826cfd
|
|
BLAKE2b-256 checksum How to use checksums |
c7cfd231744f13ebad664a6e8d846cfa3b99d74346dd027fccf3cff75fbc78cf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fetch_planning-0.3.0-cp312-cp312-manylinux_2_34_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp312-cp312-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 14.7 MB |
| Tags | CPython 3.12 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
52270d194eadfcd0410d3938af2a466987d9e1172f69b6892885af5cfdcd4f31
|
|
BLAKE2b-256 checksum How to use checksums |
8559c2ed9fd28b0a22bdade33d8ed8bdc2d3dc9b86efd951bf84718db929b866
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fetch_planning-0.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 14.2 MB |
| Tags | CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
757f96cee7d9168374808b51ab028ad5324fce283c6fe22a42b035c8c8f32b00
|
|
BLAKE2b-256 checksum How to use checksums |
81421a2ff506dff96969915d1db51e0edaa2641025034409e632080f5ea82186
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fetch_planning-0.3.0-cp311-cp311-manylinux_2_34_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp311-cp311-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 14.7 MB |
| Tags | CPython 3.11 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
71c0986dcbe4896fd01ffddf6647f713cdccf84bfdb3fddcc6453855c32059c5
|
|
BLAKE2b-256 checksum How to use checksums |
c403e1771e7bb582084f8db9af915f10162db16894346087eae25c3b3b9be4b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fetch_planning-0.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 14.2 MB |
| Tags | CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
f891f017793c3aa6dfaf939007d75d843c45553f95c6cd4ddec39c46420936b0
|
|
BLAKE2b-256 checksum How to use checksums |
5ea76dc9e0ec2cd5592862d3f11f4dd6441f9428f22291bb13fa7e15f70cca86
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fetch_planning-0.3.0-cp310-cp310-manylinux_2_34_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp310-cp310-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 14.7 MB |
| Tags | CPython 3.10 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
1ef5f119991c91f227744aab2568a1572c07d24b80cd8202d95a1ee7f7227e48
|
|
BLAKE2b-256 checksum How to use checksums |
226953ae2852a1412e2a73ff393e944812eeed586421fe5f663770ac5eccb330
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / fetch_planning-0.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | fetch_planning-0.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 14.2 MB |
| Tags | CPython 3.10 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
df65d00d0e725990c0032683b261a6159c160d597c9521aeb0cacb41ad31e771
|
|
BLAKE2b-256 checksum How to use checksums |
ebf7bd62b12c9ddc035219478de79276725dcc650cd14aeb88835f5831028ddc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency log