Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/sdk_protos_map.csv
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ arm,GetEndPosition,,get_end_position,EndPosition,endPosition,getEndPosition
arm,MoveToPosition,,move_to_position,MoveToPosition,moveToPosition,moveToPosition
arm,MoveToJointPositions,,move_to_joint_positions,MoveToJointPositions,moveToJointPositions,moveToJointPositions
arm,MoveThroughJointPositions,,,MoveThroughJointPositions,,
arm,MoveThroughJointPositionsStreamed,,move_through_joint_positions_streamed,MoveThroughJointPositionsStreamed,,
arm,GetJointPositions,,get_joint_positions,JointPositions,jointPositions,getJointPositions
arm,Get3DModels,,,Get3DModels,get3DModels,get3DModels
## Flutter-only client-side helper, sums link lengths from getKinematics() locally; no proto/RPC and no analog in other SDKs:
Expand Down
36 changes: 31 additions & 5 deletions .github/workflows/update_sdk_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,11 +538,29 @@ def parse_method_usage(usage_string):
param_type_link = "https://pkg.go.dev/builtin#error"
else:
param_raw = regex.sub(r'<.*?>', '', param).removesuffix(')').split()
## Handle channel data types (only used for Board > StreamTicks):
if len(param_raw) == 3 and param_raw[0] == 'ch':
type_name = 'ch chan'
param_type = 'Tick'
type_link = '#Tick'

## pkg.go.dev HTML-escapes the arrows in channel types, so put them back
## before we match on the tokens:
param_raw = [token.replace('&lt;', '<').replace('&gt;', '>') for token in param_raw]

## Clear the per-parameter state. Python scopes these to the whole function,
## so a parameter shape matching none of the cases below would otherwise
## inherit the previous parameter's values and document itself as a copy of
## its neighbor:
type_name = None
param_type = None
type_link = None

## Handle channel parameters, whose type spans two tokens: a direction
## marker and the element type. All three directions occur in the SDK,
## and the element type can itself be a slice:
if len(param_raw) == 3 and param_raw[1] in ('chan', '<-chan', 'chan<-'):
type_name = param_raw[0]
param_type = param_raw[1] + ' ' + param_raw[2]
try:
type_link = regex.findall(r'href="([^"]+)">', param)[-1]
except:
print("DEBUG: No type link found: {}, {}".format(usage_string, param))
## Handle named parameters:
elif len(param_raw) == 2:
type_name = param_raw[0]
Expand Down Expand Up @@ -589,6 +607,14 @@ def parse_method_usage(usage_string):
except:
print("DEBUG: No type link found: {}, {}, {}".format(usage_string, param, param_raw))

## Nothing above claimed this parameter. Fall back to the stripped source
## text so the shape that got missed is visible in the output and in the
## log, rather than quietly taking on its neighbor's identity:
if type_name is None and param_type is None:
print("DEBUG: Unhandled parameter shape: {}, {}".format(param, param_raw))
type_name = ''
param_type = ' '.join(param_raw)

if type_link:
param_type_link = type_link
else:
Expand Down
20 changes: 13 additions & 7 deletions docs/motion-planning/move-an-arm/move-by-joint-positions.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ are different tools. You reach for joint-space when:
causes a wrist flip or elbow reconfiguration.
- You want predictable motion between two configurations you both
control.
- You are building a control loop that computes its own joint targets.

Both methods on this page need every waypoint before the arm starts moving. If
you are computing the trajectory as the arm runs, see
[Stream joint positions to an arm](/motion-planning/move-an-arm/stream-joint-positions/).

**A caveat before you dive in.** Joint-space moves bypass the motion planner.
No obstacle avoidance, no constraint satisfaction, no path smoothing. If the
Expand Down Expand Up @@ -226,12 +229,13 @@ programmatically.

## Joint-space moves compared to motion.Move

| Motion path | Use when |
| ------------------------------------ | --------------------------------------------------------------------------------------------------- |
| `arm.MoveToJointPositions` | You know the joint angles you want. |
| `arm.MoveThroughJointPositions` (Go) | You have a sequence of joint targets and want per-call velocity or acceleration caps. |
| `arm.MoveToPosition` | You have a Cartesian target pose but don't need obstacle avoidance. |
| `motion.Move` | You have a Cartesian target and want obstacle avoidance, constraints, and IK picked by the planner. |
| Motion path | Use when |
| ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `arm.MoveToJointPositions` | You know the joint angles you want. |
| `arm.MoveThroughJointPositions` (Go) | You have a sequence of joint targets and want per-call velocity or acceleration caps. |
| [`arm.MoveThroughJointPositionsStreamed`](/motion-planning/move-an-arm/stream-joint-positions/) (Python, Go, C++) | You are producing the trajectory as the arm moves and cannot supply it all up front. |
| `arm.MoveToPosition` | You have a Cartesian target pose but don't need obstacle avoidance. |
| `motion.Move` | You have a Cartesian target and want obstacle avoidance, constraints, and IK picked by the planner. |

Joint-space moves are the right call when you need to control the
posture of the arm precisely. They do not protect against collisions
Expand Down Expand Up @@ -271,6 +275,8 @@ module's documentation or the kinematics file.

## What's next

- [Stream joint positions to an arm](/motion-planning/move-an-arm/stream-joint-positions/):
push waypoints while the arm is already moving.
- [Move an arm to a pose](/motion-planning/move-an-arm/move-to-pose/):
Cartesian motion with obstacle avoidance through `motion.Move`.
- [Move with constraints](/motion-planning/move-an-arm/move-with-constraints/):
Expand Down
23 changes: 14 additions & 9 deletions docs/motion-planning/move-an-arm/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,28 @@ aliases:
- /motion-planning/pick-and-place/
---

Viam exposes three ways to command an arm. Three questions sort them:
Viam exposes multiple ways to command an arm. Three questions sort them:

1. **What do you know about the destination?** A Cartesian target (a pose
in space) calls for the motion service. A specific joint configuration
calls for direct joint commands.
in space), a region of acceptable poses, an ordered list of goals, or a
specific joint configuration each point to a different call.
2. **Does the path matter, or only the endpoint?** If you
need a straight line, a fixed orientation, or any other rule about
the path itself, you need constraints.
3. **Do you want obstacle avoidance and IK picked for you, or fine
3. **Do you want obstacle avoidance and inverse kinematics (IK) picked for you, or fine
manual control?** The motion service picks the IK solution and plans
around obstacles for you; direct joint commands execute exactly the
angles you send.

| Pattern | Input | Obstacle avoidance | Path-shape control | When to pick |
| -------------------------------------------------------------------------------- | ------------------------ | ------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| [Move to a pose](/motion-planning/move-an-arm/move-to-pose/) | Cartesian target | Yes | No | You know where the end effector needs to go and want the planner to choose the path. |
| [Move with constraints](/motion-planning/move-an-arm/move-with-constraints/) | Cartesian target + rules | Yes | Yes | The shape of the motion matters (straight-line tool path, level end effector). |
| [Move by joint positions](/motion-planning/move-an-arm/move-by-joint-positions/) | Joint angles | No | Direct | You know the joint angles, need predictable motion between known configurations, or want to avoid the planner picking an unexpected IK solution. |
| Pattern | Input | Obstacle avoidance | Path-shape control | When to pick |
| -------------------------------------------------------------------------------- | ---------------------------------------------------- | ------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| [Move to a pose](/motion-planning/move-an-arm/move-to-pose/) | Cartesian target | Yes | No | You know where the end effector needs to go and want the planner to choose the path. |
| [Move with constraints](/motion-planning/move-an-arm/move-with-constraints/) | Cartesian target + rules | Yes | Yes | The shape of the motion matters (straight-line tool path, level end effector). |
| [Relax a goal with a pose cloud](/motion-planning/move-an-arm/pose-clouds/) | Cartesian target + tolerances | Yes | No | Any pose in a region will do, or an exact goal plans slowly or keeps failing. |
| [Move through waypoints](/motion-planning/move-an-arm/multiple-waypoints/) | Ordered list of Cartesian and/or joint goals | Yes | Partial | The arm must pass through specific intermediate goals in one continuous trajectory. |
| [Move by joint positions](/motion-planning/move-an-arm/move-by-joint-positions/) | Joint angles | No | Direct | You know the joint angles, need predictable motion between known configurations, or want to avoid the planner picking an unexpected IK solution. |
| [Stream joint positions](/motion-planning/move-an-arm/stream-joint-positions/) | Joint waypoints with times, sent while the arm moves | No | Direct | You are computing the trajectory as the motion runs, from a teleoperation feed or a control loop. |
| [Arm-level Cartesian move](/reference/apis/components/arm/#movetoposition) | Cartesian target | No | No | You have a pose and deliberately want the arm's own IK, with no planner, frame system, or obstacle checking. |

For the four constraint types the planner enforces, see
[Configure motion constraints](/motion-planning/move-an-arm/constraints/).
Expand Down Expand Up @@ -59,6 +63,7 @@ from the table above.
{{% card link="/motion-planning/move-an-arm/move-with-constraints/" noimage="true" %}}
{{% card link="/motion-planning/move-an-arm/constraints/" noimage="true" %}}
{{% card link="/motion-planning/move-an-arm/move-by-joint-positions/" noimage="true" %}}
{{% card link="/motion-planning/move-an-arm/stream-joint-positions/" noimage="true" %}}
{{% card link="/motion-planning/move-an-arm/multiple-waypoints/" noimage="true" %}}
{{% card link="/motion-planning/move-an-arm/pose-clouds/" noimage="true" %}}
{{% card link="/motion-planning/move-an-arm/pick-an-object/" noimage="true" %}}
Expand Down
Loading
Loading