Skip to content
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

RSDK-8835 motionplan should support planning both from and to either a pose or a list of possible configurations #4623

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

biotinker
Copy link
Member

This PR is not quite complete; there are not yet tests for the new behavior. Tests will be added before merge, and bugs turned up by the tests may merit minor changes to the body of code presented here.

This PR is a breaking change to motionplan. It introduces a new struct, PlanState, which may be a PathStep, a configuration, or both. PlanRequest undergoes the breaking change, removing several public fields and replacing them with new fields which must be PlanStates.

The changes here enable an arbitrary number of waypoints to be specified, and the planner will plan to each one in turn. It will do so faster than it would if each one were an individual Plan call.

Additionally, it permits two new interesting pieces of behavior:

  • The starting state of the robot may be specified as a set of poses, rather than a configuration (current or otherwise). If so, IK will be used to find a starting configuration.
  • The goal state of the robot may be specified as a configuration, rather than a set of poses. This allows to plan to a known-good state, such as from a prior executed plan, or to connect to a plan created by specifying a start pose as mentioned above.

@viambot viambot added the safe to test This pull request is marked safe to test from a trusted zone label Dec 12, 2024
}

// TODO: This should replace Frame and Goal
req.allGoals = map[string]*referenceframe.PoseInFrame{req.Frame.Name(): req.Goal}
for i, goalState := range req.Goals {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: comment this better

"go.viam.com/rdk/referenceframe"
)

// fixedStepInterpolation returns inputs at qstep distance along the path from start to target
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions are not new, they are merely moved over from rrt.go.

maps *rrtMaps,
) (map[string][]referenceframe.Input, *resultPromise, error) {
if parPlan, ok := pathPlanner.(rrtParallelPlanner); ok {
// ~ pm.logger.Debug("start planning for ", goal.ToProto())
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-enable

if err != nil {
return nil, err
}
// ~ wpOpt.setGoal(to)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete

@@ -124,7 +123,6 @@ type plannerOptions struct {
ConstraintHandler
motionChains []*motionChain
goalMetricConstructor func(spatialmath.Pose) ik.StateMetric
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment use of this

@@ -984,7 +984,7 @@ func TestClientStreamDisconnectHandler(t *testing.T) {
t.Helper()

client.connected.Store(false)
//nolint:staticcheck // the status API is deprecated
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These shouldn't have changed I think...darn linter

Copy link
Member

@raybjork raybjork left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I like the shape of it. I think we should think a little more about how we want to call these structs which will become the building blocks of this package. If we come up with something coherent I think it will make the mental load of understanding this package lighter to new developers

motionplan/node.go Show resolved Hide resolved

// PlanState is a struct which holds both a PathStep and a configuration. This is intended to be used as start or goal states for plans.
// Either field may be nil.
type PlanState struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the way the names for these objects slightly confusing. Maybe rename to PlanStep? Or if not rename PathStep to PathState? I think I like the latter better. That way we have a Plan & PlanState, Path & PathState, in the future Trajectory & TrajectoryState. I'm open to other ideas on what to actually call them but I think we should try to draw parallels here in our nomenclature, otherwise some of these names are a bit confusing.

utils.PanicCapturingGo(func() {
mp.rrtBackgroundRunner(ctx, seed, &rrtParallelPlannerShared{nil, nil, solutionChan})
mp.rrtBackgroundRunner(ctx, &rrtParallelPlannerShared{
initMaps.maps,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[style] this doesnt have to be broken up to multiple lines. Or if you want to do this can you add the field names to the struct instantiation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point; I think I was originally prototyping this with a much longer line, and had to split to read it, then shrunk it later

// Pick a random (first in map) seed node to create the first interp node
for sNode, parent := range rrt.maps.startMap {
if parent == nil {
seed = sNode.Q()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pretty sure you want to be breaking out of this loop here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

executionState.CurrentPoses(),
poses[len(poses)-1],
&PlanState{poses: executionState.CurrentPoses(), configuration: startingInputs},
&PlanState{poses: poses[len(poses)-1]},
startingInputs,
worldState,
nil,
nil, // no pb.Constraints
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as long as youre fixing these comments this should read Constraints now

}

// DeserializePlanState turns a serialized PlanState back into a PlanState.
func DeserializePlanState(iface map[string]interface{}) (*PlanState, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have round trip tests for this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WIP

referenceframe.PoseInFrameToProtobuf(startPose.(*referenceframe.PoseInFrame)),
request.WorldState.String(),
)
}
opt, err := pm.plannerSetupFromMoveRequest(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The arguments of this function can be cleaned up a little I think. We're passing redundant arguments

return nil, err

// Log each requested motion
for frame, goal := range goalPoses {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be worth it to make a String function on PlanRequest

@@ -758,6 +670,122 @@ func (pm *planManager) plannerSetupFromMoveRequest(
return opt, nil
}

// generateWaypoints will return the list of atomic waypoints that correspond to a specific goal in a plan request.
func (pm *planManager) generateWaypoints(request *PlanRequest, seedPlan Plan, wpi int) ([]atomicWaypoint, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like a lot of this was moved from above should I do a deeper read of this?

motionplan/planManager.go Show resolved Hide resolved
…, more to do on creating motion chains when goal is in frame of itself.
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
safe to test This pull request is marked safe to test from a trusted zone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants