-
Notifications
You must be signed in to change notification settings - Fork 0
Add direct navigation commands (move, turn, strafe, stop, stand/sit) #41
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
24df2dd
b2404e5
4b52c93
aafdc03
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 |
|---|---|---|
|
|
@@ -11,8 +11,13 @@ | |
| ActionSequence, | ||
| Follow, | ||
| Gaze, | ||
| MoveRelative, | ||
| Pick, | ||
| Place, | ||
| StandSit, | ||
| Stop, | ||
| Strafe, | ||
| TurnRelative, | ||
| ) | ||
| from spot_tools_ros.utils import path_to_waypoints, waypoints_to_path | ||
|
|
||
|
|
@@ -64,6 +69,16 @@ def from_msg(msg): | |
| actions.append(place_from_msg(a)) | ||
| case a.GAZE: | ||
| actions.append(gaze_from_msg(a)) | ||
| case a.MOVE_RELATIVE: | ||
| actions.append(MoveRelative(distance_m=a.scalar_value)) | ||
| case a.TURN_RELATIVE: | ||
| actions.append(TurnRelative(angle_deg=a.scalar_value)) | ||
| case a.STRAFE: | ||
| actions.append(Strafe(distance_m=a.scalar_value)) | ||
| case a.STOP: | ||
| actions.append(Stop()) | ||
| case a.STAND_SIT: | ||
| actions.append(StandSit(action=a.stand_sit_action)) | ||
| case _: | ||
| raise Exception(f"Received invalid action type {a.action_type}") | ||
| return ActionSequence( | ||
|
|
@@ -339,3 +354,169 @@ def _(action: Place, marker_ns): | |
| m.points = [pt1, pt2] | ||
|
|
||
| return [m] | ||
|
|
||
|
|
||
| # --- Direct navigation commands --- | ||
|
|
||
|
|
||
| @to_msg.register | ||
| def _(action: MoveRelative): | ||
| msg = ActionMsg() | ||
| msg.action_type = msg.MOVE_RELATIVE | ||
| msg.scalar_value = action.distance_m | ||
| return msg | ||
|
|
||
|
|
||
| @to_viz_msg.register | ||
| def _(action: MoveRelative, marker_ns): | ||
| m = Marker() | ||
| m.header.frame_id = "body" | ||
|
Collaborator
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. I don't think this is the right way to visualize the relative commands. I think we want to be able to visualize a series of these commands in a way that represents the overall robot motion. Representing all of the commands with respect to the current body frame does not match the semantics of what is being commanded of the robot (not to mention that hard-coding the frame here is very bad...). I think the most reasonable way of visualizing the trajectory is to transform the relative commands into the same fixed frame as the other actions, based on what the state of the robot should be when it executes the relative commands. This will require a little extra logic in the function that visualize the sequence of actions, as we have to roll forward the state from the previous actions. I think you can use an instance of SpotExecutor and fake spot to use the existing interpretation of these commands, although it might be slightly more straightforward to add the logic directly here. |
||
| m.header.stamp = gtm() | ||
| m.ns = marker_ns | ||
| m.id = 0 | ||
| m.type = m.ARROW | ||
| m.action = m.ADD | ||
| m.pose.orientation.w = 1.0 | ||
| m.scale.x = 0.1 # shaft diameter | ||
| m.scale.y = 0.15 # head diameter | ||
| m.color.a = 1.0 | ||
| m.color.r = 0.0 | ||
| m.color.g = 1.0 | ||
| m.color.b = 1.0 | ||
| pt1 = Point() | ||
| pt1.x = 0.0 | ||
| pt1.y = 0.0 | ||
| pt1.z = 0.0 | ||
| pt2 = Point() | ||
| pt2.x = action.distance_m | ||
| pt2.y = 0.0 | ||
| pt2.z = 0.0 | ||
| m.points = [pt1, pt2] | ||
| return [m] | ||
|
|
||
|
|
||
| @to_msg.register | ||
| def _(action: TurnRelative): | ||
| msg = ActionMsg() | ||
| msg.action_type = msg.TURN_RELATIVE | ||
| msg.scalar_value = action.angle_deg | ||
| return msg | ||
|
|
||
|
|
||
| @to_viz_msg.register | ||
| def _(action: TurnRelative, marker_ns): | ||
| # Create a cone to visualize rotation | ||
| m = Marker() | ||
| m.header.frame_id = "body" | ||
| m.header.stamp = gtm() | ||
| m.ns = marker_ns | ||
| m.id = 0 | ||
| m.type = m.CYLINDER | ||
| m.action = m.ADD | ||
| m.pose.orientation.w = 1.0 | ||
| m.scale.x = 0.5 # radius | ||
| m.scale.y = 0.5 | ||
| m.scale.z = 0.1 # height | ||
| m.color.a = 0.3 | ||
| m.color.r = 1.0 | ||
| m.color.g = 0.5 | ||
| m.color.b = 0.0 | ||
| return [m] | ||
|
|
||
|
|
||
| @to_msg.register | ||
| def _(action: Strafe): | ||
| msg = ActionMsg() | ||
| msg.action_type = msg.STRAFE | ||
| msg.scalar_value = action.distance_m | ||
| return msg | ||
|
|
||
|
|
||
| @to_viz_msg.register | ||
| def _(action: Strafe, marker_ns): | ||
| m = Marker() | ||
| m.header.frame_id = "body" | ||
| m.header.stamp = gtm() | ||
| m.ns = marker_ns | ||
| m.id = 0 | ||
| m.type = m.ARROW | ||
| m.action = m.ADD | ||
| m.pose.orientation.w = 1.0 | ||
| m.scale.x = 0.1 # shaft diameter | ||
| m.scale.y = 0.15 # head diameter | ||
| m.color.a = 1.0 | ||
| m.color.r = 1.0 | ||
| m.color.g = 1.0 | ||
| m.color.b = 0.0 | ||
| pt1 = Point() | ||
| pt1.x = 0.0 | ||
| pt1.y = 0.0 | ||
| pt1.z = 0.0 | ||
| pt2 = Point() | ||
| pt2.x = 0.0 | ||
| pt2.y = action.distance_m | ||
| pt2.z = 0.0 | ||
| m.points = [pt1, pt2] | ||
| return [m] | ||
|
|
||
|
|
||
| @to_msg.register | ||
| def _(action: Stop): | ||
| msg = ActionMsg() | ||
| msg.action_type = msg.STOP | ||
| return msg | ||
|
|
||
|
|
||
| @to_viz_msg.register | ||
| def _(action: Stop, marker_ns): | ||
| # Red X marker to indicate stop | ||
| m = Marker() | ||
| m.header.frame_id = "body" | ||
| m.header.stamp = gtm() | ||
| m.ns = marker_ns | ||
| m.id = 0 | ||
| m.type = m.CUBE | ||
| m.action = m.ADD | ||
| m.pose.orientation.w = 1.0 | ||
| m.scale.x = 0.3 | ||
| m.scale.y = 0.3 | ||
| m.scale.z = 0.3 | ||
| m.color.a = 0.8 | ||
| m.color.r = 1.0 | ||
| m.color.g = 0.0 | ||
| m.color.b = 0.0 | ||
| return [m] | ||
|
|
||
|
|
||
| @to_msg.register | ||
| def _(action: StandSit): | ||
| msg = ActionMsg() | ||
| msg.action_type = msg.STAND_SIT | ||
| msg.stand_sit_action = action.action | ||
| return msg | ||
|
|
||
|
|
||
| @to_viz_msg.register | ||
| def _(action: StandSit, marker_ns): | ||
| # Green sphere for stand, blue sphere for sit | ||
| m = Marker() | ||
| m.header.frame_id = "body" | ||
| m.header.stamp = gtm() | ||
| m.ns = marker_ns | ||
| m.id = 0 | ||
| m.type = m.SPHERE | ||
| m.action = m.ADD | ||
| m.pose.orientation.w = 1.0 | ||
| m.scale.x = 0.2 | ||
| m.scale.y = 0.2 | ||
| m.scale.z = 0.2 | ||
| m.color.a = 0.8 | ||
| if action.action == "stand": | ||
| m.color.r = 0.0 | ||
| m.color.g = 1.0 | ||
| m.color.b = 0.0 | ||
| else: # sit | ||
| m.color.r = 0.0 | ||
| m.color.g = 0.0 | ||
| m.color.b = 1.0 | ||
| return [m] | ||
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.
We should definitely add visualization conversion functions here. I know it's a little tricky to figure out where to actually call them from, but I think having that capability is pretty important for understanding what the robot's trying to do. I think we would want to add an extra lightweight node that just listens on the appropriate topic, and publishes the markers associated with these new actions.