Add motion planning pages: end effector frames, waypoints, pose clouds, plan verification#5098
Add motion planning pages: end effector frames, waypoints, pose clouds, plan verification#5098btshrewsbury-viam wants to merge 22 commits into
Conversation
…s, plan verification Add four new pages under Motion Planning and wire them into navigation: - Frame System > End effector frames: how Move targets a named frame, the frame attribute, WorldState transforms, and WorldState vs the world state store service. - Move an arm > Moving through multiple waypoints: multi-goal PlanRequest with armplanning.PlanMotion, continuous trajectory, return_partial_plan. - Move an arm > Pose clouds: relax a goal into a region with NewPoseInFrameWithGoalCloud; briefly noted and linked from the constraints page. - Verifying a Motion Plan: armplanning.PlanMotion vs Move, assembling a PlanRequest, reading the Plan, and the motion service plan DoCommand verb. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ Deploy Preview for viam-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
| layout: "docs" | ||
| type: "docs" | ||
| description: "How the motion service moves a named frame to a target pose, and how the frame attribute and WorldState transforms control which point on the robot that frame represents." | ||
| --- |
There was a problem hiding this comment.
Keeping a few general questions here as I review this:
- What can we expect readers to already be familiar with when they read this page?
- Do we need to summarize what a pose is? Should there be a reference section, perhaps in the overview that we link readers to for more details?
- Same question for world state.
There was a problem hiding this comment.
Yeah, I think we need to define pose and frame clearly in a place that we can reference elsewhere. Currently thinking the overview page might be the best place for that, but I'll continue to assess as I review.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
Apply house-style fixes from the doc review: remove the negation-based opening and the "Understanding..." learning-objective leak, replace the vague "targets frames" wording with what Move actually does, convert "is not treated as hardware" to the positive "resolves to a frame", reframe the world state store contrast positively (noun-plus-job), and trim the description under the Hugo length limit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdVfSBN5zBzSHStG1HoPDK
Apply house-style and accuracy fixes across the move-an-arm motion pages, and add diagrams for the concepts that read better visually. - Pose clouds: rework the example around a grasped cup with a target frame and an orientation constraint, add a units/default table and a PoseCloud snippet, and add two diagrams (the cup pose cloud and the tilted-surface target frame with the orientation-vector tolerance). - Multiple waypoints: answer the start-state and frame-system questions against source, and add a single-Move-vs-multi-goal contrast diagram. - Verify a plan and constraints: convert negations to positive statements, replace jargon, and fix a banned idiom in a heading. All code is verified against the RDK source (NewPoseInFrameWithGoalCloud, PoseCloud, OrientationConstraint, armplanning.PlanMotion, PlanRequest). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdVfSBN5zBzSHStG1HoPDK
Use arm.JointPositions to seed the start state from the arm's current position (with arm.FromRobot), and explain the extra/nil parameter. Correct the PlanRequest description (the world state is optional, not required), and fix grammar and code-comment typos. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdVfSBN5zBzSHStG1HoPDK
Dan Gottlieb (dgottlieb)
left a comment
There was a problem hiding this comment.
This all looks great. Biggest question is the orientation axis on the images.
There was a problem hiding this comment.
This is more of a question for me -- Before an object (sitting on a table for example) is grasped, a natural orientation vector would be +Z going "up". But when re-parenting the object to a gripper (where positive Z is "down"), that would flip it's orientation vector? That can't be right?
It seems that re-parenting for complex object where that "child" orientation vector matters isn't as simple as just changing the parent.
There was a problem hiding this comment.
I am thinking if the object we picked up had built in frames, it would be relative to some parent. that transform to parent would need to change on pickup. for something like a drill, it could have a grip frame and a drill bit frame, we would need to define a transform from the TCP to the grip frame on pickup so we don't loose the drill bit, and if it wasn't using DH the orientation would probably change axis.
|
|
||
| ## WorldState versus the world state store service | ||
|
|
||
| The names are similar, but `WorldState` and the world state store service are |
There was a problem hiding this comment.
I think the goal is to populate motion service requests with items defined in the world state store service. Not sure if that task without a completion date warrants changing the narrative here. But just wanted to be transparent that the two ought to be more similar than they currently are.
The documentation though is accurate w.r.t how things behave today.
There was a problem hiding this comment.
Once that goes through I will need to update a bunch then, have similar distinctions in the new Visualization Section
| weight: 60 | ||
| layout: "docs" | ||
| type: "docs" | ||
| description: "Use armplanning.PlanMotion to compute and inspect a trajectory before the arm moves, and learn how to get the same plan over the motion service API." |
There was a problem hiding this comment.
I'm not sure if there needs to be a documentation change here, just being transparent about the intention of armplanning.PlanMotion.
Calling PlanMotion directly is regarded as accessing a "private" API. It's (long term) goal is to only be consumed by the motion service. That said, there are enough limitations (e.g: passing around large meshes may not be feasible) with using the motion service such that using this more directly is helpful/neccessary.
Being considered "private", we do break this API. So there's some risk in adopting this heavily into application code.
The remote section here about using the motion service with the "plan" command is the recommended path. Hopefully we can make it more ergonomic in the future and allow users to make that call without having to proto serialize the MoveReq by hand. Which motivated me to file a ticket for that: https://viam.atlassian.net/browse/RSDK-14155
There was a problem hiding this comment.
Making plan easier to use from the Motion Service's perspective would be amazing. I can switch this to only show the DoCommand verb if that feels more correct. I ended up making a bunch of helpers to make marshalling a bit easier: https://github.com/viam-labs/viamkit/blob/main/verify/plan.go. The plan verb was extremely important in moving the pallet around
There was a problem hiding this comment.
Thanks for sharing that code link -- I've added it to the ticket to give more concrete motivation of what users shouldn't need to write.
I can switch this to only show the DoCommand verb if that feels more correct.
Again, not sure if I'm the right decision maker here. But given the plan verb can do everything (in the context of verifying -- not in the context of multiple waypoints), opting to get rid of the direct armplanning.PlanMotion example makes sense to me.
| @@ -0,0 +1,155 @@ | |||
| --- | |||
There was a problem hiding this comment.
I know you asked to especially look at this, so leaving a note.
This all looks good to me! I think this does a much better job explaining the "follow the tilt" motivation/ease than my code comment did.
The code example at the bottom re: not spilling is definitely what we're striving for what a user should write. I'm skeptical that system reliably achieves that! But see nothing that needs to change there.
If there's anything worth detailing, it's about the sharp edge regarding orientation vector normalization. I'm not sure if the wine pouring example/documentation is the most straightforward example. But there's definitely a game where setting a goal pose with OZ: 0 (and leaving OX/OY untouched because of an unconstrained pose cloud) is a bit undefined. Because the goal orientation of OX: 0, OY: 0, OZ: 0 would get normalized back to OX: 0, OY: 0, OZ: 1. And from there having a pose cloud of OX: 1, OY: 1, OZ: no longer does the right thing.
Maybe this goes into the "what is a pose" documentation Shannon was referring to above. Or we just wait on this more esoteric documentation in case we come up with a better idea for resolving that ambiguity most likely preserves user intent.
Dan Gottlieb (dgottlieb)
left a comment
There was a problem hiding this comment.
lgtm % updated svgs
| weight: 60 | ||
| layout: "docs" | ||
| type: "docs" | ||
| description: "Use armplanning.PlanMotion to compute and inspect a trajectory before the arm moves, and learn how to get the same plan over the motion service API." |
There was a problem hiding this comment.
Thanks for sharing that code link -- I've added it to the ticket to give more concrete motivation of what users shouldn't need to write.
I can switch this to only show the DoCommand verb if that feels more correct.
Again, not sure if I'm the right decision maker here. But given the plan verb can do everything (in the context of verifying -- not in the context of multiple waypoints), opting to get rid of the direct armplanning.PlanMotion example makes sense to me.
- Flip arm/tool/object frames to Z-down (DH convention) while keeping the world frame Z-up, per Dan's orientation-axis comment. - Use a right-handed Z-down triad with green Y on the world frame's lower-left side (X-left, Y-down-left), so all green axes sit on one side; give Y a longer line so it reads clearly. - Label one triad per image (the rest are color-coded), draw red X over green Y, and remove the per-axis labels that collided. - Trim the end-effector-types caption to drop the ambiguous "world frame at the base" clause; widen the canvas so "drill-tip frame" is not clipped. - Delete the orphaned drill-bit-frame.svg (superseded by arm-vs-gripper-frame). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdVfSBN5zBzSHStG1HoPDK
Per Dan's review: a pose cloud's OX/OY/OZ leeways are checked against a normalized orientation vector, so the three share one unit-sphere budget and do not move independently. Explain that you widen all three together to let the pointing direction vary, and that a wide OX/OY with a tight OZ holds the tool aligned because OZ pins the direction and the unit-sphere constraint then holds OX and OY at 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdVfSBN5zBzSHStG1HoPDK
Shannon Bradshaw (shannonbradshaw)
left a comment
There was a problem hiding this comment.
Thanks for this PR. It fills a massive gap. Many changes requested in comments throughout.
Co-authored-by: Shannon Bradshaw <shannon.bradshaw@gmail.com>
Co-authored-by: Shannon Bradshaw <shannon.bradshaw@gmail.com>
Co-authored-by: Shannon Bradshaw <shannon.bradshaw@gmail.com>
Restructure end-effector-frames.md into the arm frame, end effector frames, component-frame definition, moving with the motion service, and code-defined frame sections. Add the arm/joint-frames figure and fix the frame-system diagram triads (right-handed axes, DH joint orientation). Link the world state store service and WorldState references.
Rework pose-clouds.md: when-to-use guidance, the cup running example, the pose-cloud-as-box model, tolerances measured in the target frame, and the orientation-vector tolerance coupling plus the normalization sharp edge. Update the pose-cloud-cup and pose-cloud-target-frame diagrams (right-handed triads, label fixes).
Add brief frame and pose definitions to the frame-system overview so they are referenceable (per review), and repoint the end-effector-frames link to the new anchor.

What
Adds four new pages under Motion Planning and wires them into the section navigation.
New pages
Movetargets a named frame, not a component: howcomponent_nameselects the end effector frame, how theframeattribute defines a static frame, howWorldStatetransforms extend the frame system for a single request, and howWorldStatediffers from the world state store service.armplanning.PlanMotion: howPlanRequest.GoalschainsPlanStates into a single continuous trajectory, mixing poses / joint configurations / pose clouds per waypoint, and usingreturn_partial_planto isolate an infeasible waypoint.NewPoseInFrameWithGoalCloud: the translational/rotational leeways, why tolerances are measured in the target frame, and when a goal region beats an exact pose. Briefly noted and linked from the Configure constraints page.armplanning.PlanMotionvsmotionService.Move, assembling aPlanRequest, reading the returnedPlan/Trajectory, and reproducing the same plan over the motion service with theplanDoCommandverb (and its trade-offs).Navigation / edits
Notes for reviewers
make build-prod.🤖 Generated with Claude Code