You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #433 adds obstacle-aware planning through RobotQueryPoints, which maps a selected joint configuration to world-frame query points and, when requested, their analytic Jacobians. This is evaluated repeatedly by the obstacle factors, so the implementation precomputes the robot topology/traversal once and replays a compact traversal in the optimizer's hot loop.
GTDynamics already has a general robot-tree traversal in Robot::forwardKinematics(). The simulator's forward-dynamics path calls that routine before solving for accelerations. However, the existing routine has a different interface and purpose: it operates on gtsam::Values, computes poses and twists for the reachable links, rebuilds a breadth-first traversal per call, and does not directly produce the query-point Jacobians required by the obstacle factors.
Consequently, #433 contains a second implementation of robot-tree traversal. Calling forward dynamics from obstacle evaluation would be incorrect and unnecessarily expensive; calling the current general forward-kinematics routine would still leave the Jacobian propagation problem and would likely add overhead in the optimization loop. Nevertheless, maintaining two independent implementations of the topology and joint-propagation rules creates a long-term risk of behavioral drift.
Timing: This issue is intentionally a follow-up to #433. It is relevant only after #433 has been merged, and should not block or expand that PR.
Proposal
Introduce an immutable, precompiled kinematic traversal abstraction that can be constructed once from a Robot and reused by clients that need to propagate state through the robot tree.
The shared layer should own only the common structural information and traversal rules, for example:
validated root and parent/child relationships;
deterministic traversal order;
references or indices for links and joints;
the mapping needed to propagate a child pose from its parent and joint value;
optional filtering to a selected set of joints, links, or descendant subtrees.
Clients would remain responsible for choosing which quantities they compute:
Robot::forwardKinematics() can use the traversal to produce its existing poses and twists in gtsam::Values;
RobotQueryPoints can use it to compute only the required link poses, query-point positions, and analytic Jacobians;
dynamics code can continue to use the general forward-kinematics API and its subsequent acceleration solve.
This should be a reusable kinematics primitive, not an attempt to route collision checking through forward dynamics.
Performance requirements
The refactor must preserve the reason RobotQueryPoints has a specialized implementation:
no topology search or BFS construction during factor evaluation;
no gtsam::Values assembly in the obstacle-factor hot path;
no pose/twist/dynamics quantities computed unless requested;
no additional heap allocation proportional to the robot size per evaluation, where practical;
analytic query-point Jacobians remain available;
the compiled traversal is immutable after construction and safe for concurrent read-only evaluation.
A benchmark should compare the implementation from #433 with the shared-traversal version for representative robot sizes, numbers of query points, and Jacobian-on/Jacobian-off evaluations. The goal should be no meaningful regression in obstacle-factor evaluation time.
Suggested implementation sequence
Add tests that compare the existing Robot::forwardKinematics() and RobotQueryPoints pose results for the same configurations.
Extract the immutable traversal description without changing public behavior.
Migrate RobotQueryPoints to the shared representation while retaining its specialized evaluation buffers and outputs.
Migrate Robot::forwardKinematics() to the same traversal if doing so keeps its API and behavior clear.
Add equivalence, branched-tree, fixed-link, selected-joint, Jacobian, concurrency, and performance tests.
Acceptance criteria
There is one canonical implementation of robot-tree topology and traversal ordering.
Existing forward-kinematics and obstacle-factor APIs retain their behavior.
Context
PR #433 adds obstacle-aware planning through
RobotQueryPoints, which maps a selected joint configuration to world-frame query points and, when requested, their analytic Jacobians. This is evaluated repeatedly by the obstacle factors, so the implementation precomputes the robot topology/traversal once and replays a compact traversal in the optimizer's hot loop.GTDynamics already has a general robot-tree traversal in
Robot::forwardKinematics(). The simulator's forward-dynamics path calls that routine before solving for accelerations. However, the existing routine has a different interface and purpose: it operates ongtsam::Values, computes poses and twists for the reachable links, rebuilds a breadth-first traversal per call, and does not directly produce the query-point Jacobians required by the obstacle factors.Consequently, #433 contains a second implementation of robot-tree traversal. Calling forward dynamics from obstacle evaluation would be incorrect and unnecessarily expensive; calling the current general forward-kinematics routine would still leave the Jacobian propagation problem and would likely add overhead in the optimization loop. Nevertheless, maintaining two independent implementations of the topology and joint-propagation rules creates a long-term risk of behavioral drift.
Proposal
Introduce an immutable, precompiled kinematic traversal abstraction that can be constructed once from a
Robotand reused by clients that need to propagate state through the robot tree.The shared layer should own only the common structural information and traversal rules, for example:
Clients would remain responsible for choosing which quantities they compute:
Robot::forwardKinematics()can use the traversal to produce its existing poses and twists ingtsam::Values;RobotQueryPointscan use it to compute only the required link poses, query-point positions, and analytic Jacobians;This should be a reusable kinematics primitive, not an attempt to route collision checking through forward dynamics.
Performance requirements
The refactor must preserve the reason
RobotQueryPointshas a specialized implementation:gtsam::Valuesassembly in the obstacle-factor hot path;A benchmark should compare the implementation from #433 with the shared-traversal version for representative robot sizes, numbers of query points, and Jacobian-on/Jacobian-off evaluations. The goal should be no meaningful regression in obstacle-factor evaluation time.
Suggested implementation sequence
Robot::forwardKinematics()andRobotQueryPointspose results for the same configurations.RobotQueryPointsto the shared representation while retaining its specialized evaluation buffers and outputs.Robot::forwardKinematics()to the same traversal if doing so keeps its API and behavior clear.Acceptance criteria