-
Notifications
You must be signed in to change notification settings - Fork 129
dual arm teleop & smoothing #5898
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
9d7cc30
a2d5dab
92bb429
011c1da
18ca3c5
08d5210
068ad56
455f941
b4f9b6e
117244a
136339b
92feec9
ea25e58
e04d14f
de2c2e7
d30b808
29de7a4
5894186
7c7fbb7
242301f
79c05de
e31afdd
c4e88c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,6 +97,17 @@ type Config struct { | |
|
|
||
| // example { "arm" : { "3" : { "min" : 0, "max" : 2 } } } | ||
| InputRangeOverride map[string]map[string]referenceframe.Limit `json:"input_range_override"` | ||
|
|
||
| // TeleopSmallMoveRad is the max joint displacement (radians) below which | ||
| // the arm's built-in interpolation is enabled for smooth motion. Default 0.005. | ||
| TeleopSmallMoveRad float64 `json:"teleop_small_move_rad"` | ||
| // TeleopInterpolateOverride when true forces interpolation ON for all teleop | ||
| // movements regardless of size. Useful for testing. | ||
| TeleopInterpolateOverride bool `json:"teleop_interpolate_override"` | ||
| // TeleopSmoothAlpha is the EMA smoothing factor for joint positions (0-1). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's EMA? |
||
| // Lower = smoother but more latency, higher = more responsive but less smooth. | ||
| // 0 = frozen, 1 = no smoothing. Default 0.5. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this really about how many points to batch up before sending to planning/smooth? I think we can afford to be more transparent with how the tradeoff works in the documentation. Even if the 0->1 slider will always be opaque. |
||
| TeleopSmoothAlpha float64 `json:"teleop_smooth_alpha"` | ||
| } | ||
|
|
||
| func (c *Config) shouldWritePlan(start time.Time, err error) bool { | ||
|
|
@@ -532,67 +543,43 @@ func (ms *builtIn) plan(ctx context.Context, req motion.MoveReq, logger logging. | |
| return plan, err | ||
| } | ||
|
|
||
| // planTeleop is a low-latency variant of plan() for the teleop pipeline. | ||
| // It uses a pre-built frame system and caller-provided fsInputs (merged from | ||
| // live CurrentInputs + planning head) to avoid per-call overhead. | ||
| func (ms *builtIn) planTeleop( | ||
| // planTeleopMulti plans a trajectory for multiple components simultaneously. | ||
| // It builds a multi-frame goal from the given poses map, allowing the planner | ||
| // to find collision-free paths for all arms jointly. | ||
| func (ms *builtIn) planTeleopMulti( | ||
| ctx context.Context, | ||
| req motion.MoveReq, | ||
| goals referenceframe.FrameSystemPoses, | ||
| extra map[string]interface{}, | ||
| frameSys *referenceframe.FrameSystem, | ||
| fsInputs referenceframe.FrameSystemInputs, | ||
| logger logging.Logger, | ||
| ) (motionplan.Plan, error) { | ||
| ctx, span := trace.StartSpan(ctx, "motion::builtin::planTeleop") | ||
| ctx, span := trace.StartSpan(ctx, "motion::builtin::planTeleopMulti") | ||
| defer span.End() | ||
|
|
||
| movingFrame := frameSys.Frame(req.ComponentName) | ||
| if movingFrame == nil { | ||
| return nil, fmt.Errorf("component named %s not found in robot frame system", req.ComponentName) | ||
| } | ||
|
|
||
| startState, waypoints, err := waypointsFromRequest(req, fsInputs) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if len(waypoints) == 0 { | ||
| return nil, errors.New("could not find any waypoints to plan for in MoveRequest. Fill in Destination or goal_state") | ||
| } | ||
|
|
||
| if req.Extra != nil { | ||
| req.Extra["waypoints"] = nil | ||
| } | ||
|
|
||
| // Re-evaluate goal poses to be in the frame of World. | ||
| worldWaypoints := []*armplanning.PlanState{} | ||
| solvingFrame := referenceframe.World | ||
| for _, wp := range waypoints { | ||
| if wp.Poses() != nil { | ||
| step := referenceframe.FrameSystemPoses{} | ||
| for fName, destination := range wp.Poses() { | ||
| tf, err := frameSys.Transform(fsInputs.ToLinearInputs(), destination, solvingFrame) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| goalPose, _ := tf.(*referenceframe.PoseInFrame) | ||
| step[fName] = goalPose | ||
| } | ||
| worldWaypoints = append(worldWaypoints, armplanning.NewPlanState(step, wp.Configuration())) | ||
| } else { | ||
| worldWaypoints = append(worldWaypoints, wp) | ||
| // Transform all goal poses to world frame. | ||
| worldGoals := make(referenceframe.FrameSystemPoses, len(goals)) | ||
| for fName, destination := range goals { | ||
| tf, err := frameSys.Transform(fsInputs.ToLinearInputs(), destination, referenceframe.World) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| goalPose, _ := tf.(*referenceframe.PoseInFrame) | ||
| worldGoals[fName] = goalPose | ||
| } | ||
|
|
||
| planOpts, err := armplanning.NewPlannerOptionsFromExtra(req.Extra) | ||
| startState := armplanning.NewPlanState(nil, fsInputs) | ||
| goalState := armplanning.NewPlanState(worldGoals, nil) | ||
|
|
||
| planOpts, err := armplanning.NewPlannerOptionsFromExtra(extra) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| planRequest := &armplanning.PlanRequest{ | ||
| FrameSystem: frameSys, | ||
| Goals: worldWaypoints, | ||
| Goals: []*armplanning.PlanState{goalState}, | ||
| StartState: startState, | ||
| WorldState: req.WorldState, | ||
| Constraints: req.Constraints, | ||
| PlannerOptions: planOpts, | ||
| } | ||
|
|
||
|
|
@@ -688,6 +675,7 @@ func (ms *builtIn) execute(ctx context.Context, trajectory motionplan.Trajectory | |
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| if err := ie.GoToInputs(ctx, inputs...); err != nil { | ||
| // If there is an error on GoToInputs, stop the component if possible before returning the error | ||
| if actuator, ok := r.(inputEnabledActuator); ok { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does testing mean here? Doesn't seem to be for unit testing.
Why is "testing" in the office different than a real demo?