tesseract_robotics.tesseract_motion_planners_descartes¶
Descartes graph-based Cartesian planner.
Overview¶
Descartes solves dense Cartesian paths by building a graph of IK solutions and finding the optimal path through it. Best for industrial toolpaths (welding, milling) where every waypoint must be reached.
from tesseract_robotics.tesseract_motion_planners_descartes import (
DescartesMotionPlannerD,
DescartesDefaultPlanProfileD,
DescartesLadderGraphSolverProfileD,
)
DescartesMotionPlannerD¶
from tesseract_robotics.tesseract_motion_planners_descartes import DescartesMotionPlannerD
from tesseract_robotics.tesseract_motion_planners import PlannerRequest
planner = DescartesMotionPlannerD("DescartesMotionPlannerTask")
request = PlannerRequest()
request.env = env
request.instructions = program
request.profiles = profiles
response = planner.solve(request)
DescartesMotionPlannerD is a tesseract_motion_planners.MotionPlanner: getName, solve,
terminate, clear and clone are the base class's, and solve releases the GIL.
Profiles¶
DescartesDefaultPlanProfileD¶
Per-waypoint configuration.
from tesseract_robotics.tesseract_motion_planners_descartes import DescartesDefaultPlanProfileD
profile = DescartesDefaultPlanProfileD()
# Target pose sampler settings
# Configure how many IK solutions to sample per waypoint
DescartesLadderGraphSolverProfileD¶
Solver configuration for the ladder graph.
from tesseract_robotics.tesseract_motion_planners_descartes import DescartesLadderGraphSolverProfileD
profile = DescartesLadderGraphSolverProfileD()
# Graph construction and search settings
Both profiles compare by value (== compares every field, as the C++ operator== does) and
are unhashable. DescartesMoveProfileD.createKey() and DescartesSolverProfileD.createKey()
return the key every profile of that kind carries, the key ProfileDictionary looks up:
Inspecting the samplers¶
The move profile's create* hooks return what the planner builds for one waypoint. str() on
the waypoint sampler shows its working frame, TCP frame, target pose and TCP offset:
sampler = DescartesDefaultMoveProfileD().createWaypointSampler(move, manip_info, env)
print(sampler) # Working Frame: base_link, TCP Frame: tool0 ...
samples = sampler.sample() # list[DescartesStateSampleD], one per IK solution
DescartesStateSampleD(state) builds a sample with cost 0, as DescartesStateSampleD(state, 0.0).
Tool-pose samplers¶
The functions behind DescartesDefaultMoveProfileD.target_pose_sample_* turn one tool pose into
candidate poses, returned as a tesseract_common.VectorIsometry3d:
| Function | Samples |
|---|---|
sampleFixed(tool_pose) |
the pose itself |
sampleToolAxis(tool_pose, axis, resolution, minimum, maximum) |
rotations of the pose about axis |
sampleToolXAxis / sampleToolYAxis / sampleToolZAxis(tool_pose, resolution, minimum, maximum) |
rotations about the tool's X / Y / Z axis |
The angles run from minimum in steps of resolution while they do not exceed maximum
(equal within tolerance counts), so both ends are included when the range is a whole number of
steps:
import numpy as np
from tesseract_robotics.tesseract_motion_planners_descartes import sampleToolZAxis
poses = sampleToolZAxis(tool_pose, resolution=np.pi / 2, minimum=-np.pi, maximum=np.pi / 2)
len(poses) # 4: -pi, -pi/2, 0, pi/2
They are useful without the planner, for example to seed IK over a tool axis the process is indifferent to.
How It Works¶
- Sample waypoints: For each Cartesian waypoint, compute all IK solutions
- Build graph: Create nodes for each solution, edges between consecutive waypoints
- Edge costs: Based on joint motion between solutions
- Find path: Dijkstra's algorithm finds minimum-cost path
Waypoint 1 Waypoint 2 Waypoint 3
○──────────────○──────────────○
│ │ │
○──────────────○──────────────○
│ │ │
○──────────────○──────────────○
(IK solutions)
Use Cases¶
- Welding: Dense linear paths with tool orientation constraints
- Milling: Toolpaths from CAM software
- Painting: Spray patterns with coverage requirements
- Inspection: Camera positioning paths
Limitations¶
- Computationally expensive: O(n × k²) where n=waypoints, k=IK solutions
- Requires IK solutions: Won't work if waypoints are unreachable
- No obstacle avoidance: Use with collision checking post-filter
Tips¶
- Use for dense Cartesian paths where every point matters
- Combine with TrajOpt for smoothing afterward
- Reduce waypoint density if planning is too slow
- Check reachability before planning - Descartes fails if any waypoint is unreachable
Auto-generated API Reference¶
tesseract_motion_planners_descartes Python bindings
DescartesPlanProfileD
module-attribute
¶
DescartesDefaultPlanProfileD
module-attribute
¶
DescartesStateD
¶
DescartesStateSampleD
¶
DescartesEdgeEvaluatorD
¶
DescartesWaypointSamplerD
¶
DescartesStateEvaluatorD
¶
DescartesSolverProfileD
¶
DescartesLadderGraphSolverProfileD
¶
Bases: DescartesSolverProfileD
num_threads
property
writable
¶
Number of threads to use during planning (default: 1)
DescartesMoveProfileD
¶
Bases: Profile
createKinematicGroup
¶
createKinematicGroup(manip_info: ManipulatorInfo, env: Environment) -> tesseract_robotics.tesseract_kinematics._tesseract_kinematics.KinematicGroup
The kinematic group for manip_info's manipulator and IK solver
createWaypointSampler
¶
createWaypointSampler(move_instruction: MoveInstructionPoly, composite_manip_info: ManipulatorInfo, env: Environment) -> DescartesWaypointSamplerD
createEdgeEvaluator
¶
createEdgeEvaluator(move_instruction: MoveInstructionPoly, composite_manip_info: ManipulatorInfo, env: Environment) -> DescartesEdgeEvaluatorD
createStateEvaluator
¶
createStateEvaluator(move_instruction: MoveInstructionPoly, composite_manip_info: ManipulatorInfo, env: Environment) -> DescartesStateEvaluatorD
DescartesDefaultMoveProfileD
¶
DescartesMotionPlannerD
¶
Bases: MotionPlanner
cast_DescartesSolverProfileD
¶
cast_DescartesSolverProfileD(profile: DescartesLadderGraphSolverProfileD) -> tesseract_robotics.tesseract_command_language._tesseract_command_language.Profile
Cast DescartesLadderGraphSolverProfileD to Profile for use with ProfileDictionary
cast_DescartesMoveProfileD
¶
cast_DescartesMoveProfileD(profile: DescartesMoveProfileD) -> tesseract_robotics.tesseract_command_language._tesseract_command_language.Profile
Cast a DescartesMoveProfileD (including Python subclasses) to Profile for use with ProfileDictionary
cast_DescartesPlanProfileD
¶
cast_DescartesPlanProfileD(profile: DescartesMoveProfileD) -> tesseract_robotics.tesseract_command_language._tesseract_command_language.Profile
Cast a DescartesMoveProfileD to Profile (legacy alias of cast_DescartesMoveProfileD)
sampleToolAxis
¶
sampleToolAxis(tool_pose: Isometry3d, axis: Annotated[NDArray[float64], dict(shape=3, order=C)] | Sequence[float], resolution: float, minimum: float, maximum: float) -> tesseract_robotics.tesseract_common._tesseract_common.VectorIsometry3d
Given a tool pose create samples from [minimum, maximum] around the provided axis.
sampleToolXAxis
¶
sampleToolXAxis(tool_pose: Isometry3d, resolution: float, minimum: float, maximum: float) -> tesseract_robotics.tesseract_common._tesseract_common.VectorIsometry3d
Given a tool pose create samples from [minimum, maximum] around the x axis.
sampleToolYAxis
¶
sampleToolYAxis(tool_pose: Isometry3d, resolution: float, minimum: float, maximum: float) -> tesseract_robotics.tesseract_common._tesseract_common.VectorIsometry3d
Given a tool pose create samples from [minimum, maximum] around the y axis.
sampleToolZAxis
¶
sampleToolZAxis(tool_pose: Isometry3d, resolution: float, minimum: float, maximum: float) -> tesseract_robotics.tesseract_common._tesseract_common.VectorIsometry3d
Given a tool pose create samples from [minimum, maximum] around the z axis.
sampleFixed
¶
sampleFixed(tool_pose: Isometry3d) -> tesseract_robotics.tesseract_common._tesseract_common.VectorIsometry3d
This will return the tool pose as the only sample.