Skip to content

Commit 3328f12

Browse files
taylorkfTaylorTaylor Kessler Faulkner
authored
Finalize learning capabilities (not including posthoc) (#195)
* Enabled calling all different policy types, added policy flag to start script * Fixed spacing error in dummy launch * Fixed linalg mispelling bug * Commit local changes on lovelace * Added full acquisition library, switched to SPANet context * Cleaned up code, added angled extraction, removed unwanted actions --------- Co-authored-by: Taylor <taylorkf@tiktok.personalrobotics.cs.washington.edu> Co-authored-by: Taylor Kessler Faulkner <taylorkf@cs.washington.edu>
1 parent 3afa890 commit 3328f12

File tree

14 files changed

+996
-573
lines changed

14 files changed

+996
-573
lines changed

ada_feeding/ada_feeding/behaviors/acquisition/compute_action_constraints.py

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ def blackboard_inputs(
6363
move_above_dist_m: Union[BlackboardKey, float] = 0.05,
6464
food_frame_id: Union[BlackboardKey, str] = "food",
6565
approach_frame_id: Union[BlackboardKey, str] = "approach",
66+
action: Union[BlackboardKey, Optional[AcquisitionSchema]] = None,
6667
) -> None:
6768
"""
6869
Blackboard Inputs
@@ -73,6 +74,7 @@ def blackboard_inputs(
7374
move_above_dist_m: how far from the food to start
7475
food_frame_id: food frame defined in AcquisitionSchema.msg
7576
approach_frame_id: approach frame defined in AcquisitionSchema.msg
77+
action: which action has been chosen in the initial pi-symmetry break
7678
"""
7779
# pylint: disable=unused-argument, duplicate-code
7880
# Arguments are handled generically in base class.
@@ -141,64 +143,67 @@ def update(self) -> py_trees.common.Status:
141143
self.logger.error(f"Malformed action select response: {response}")
142144
return py_trees.common.Status.FAILURE
143145

144-
# Sample Action
145-
index = np.random.choice(np.arange(prob.size), p=prob)
146-
action = response.actions[index]
147-
148-
### Construct Constraints
149-
150-
# Re-scale pre-transform to move_above_dist_m
151-
position = ros2_numpy.numpify(action.pre_transform.position)
152-
if np.isclose(np.linalg.norm(position), 0.0):
153-
self.logger.error(
154-
f"Malformed action pre_transform: {action.pre_transform.position}"
146+
action_set = self.blackboard_get("action")
147+
if action_set is None:
148+
# Sample Action
149+
index = np.random.choice(np.arange(prob.size), p=prob)
150+
action = response.actions[index]
151+
self.logger.info(f"Chosen action index: {index}")
152+
153+
### Construct Constraints
154+
155+
# Re-scale pre-transform to move_above_dist_m
156+
position = ros2_numpy.numpify(action.pre_transform.position)
157+
if np.isclose(np.linalg.norm(position), 0.0):
158+
self.logger.error(
159+
f"Malformed action pre_transform: {action.pre_transform.position}"
160+
)
161+
return py_trees.common.Status.FAILURE
162+
position = (
163+
position
164+
* self.blackboard_get("move_above_dist_m")
165+
/ np.linalg.norm(position)
166+
)
167+
action.pre_transform.position = ros2_numpy.msgify(Point, position)
168+
self.blackboard_set("move_above_pose", action.pre_transform)
169+
170+
# Calculate Approach Target (in food frame)
171+
move_into_pose = Pose()
172+
move_into_pose.orientation = deepcopy(action.pre_transform.orientation)
173+
offset = ros2_numpy.numpify(action.pre_offset)
174+
move_into_pose.position = ros2_numpy.msgify(Point, offset)
175+
self.blackboard_set("move_into_pose", move_into_pose)
176+
177+
### Calculate Approach Frame
178+
approach_vec = offset - position
179+
approach_frame = TransformStamped()
180+
approach_mat = np.eye(4)
181+
if not np.all(np.isclose(approach_vec[:2], np.zeros(2))):
182+
approach_mat[:3, :3] = R.from_rotvec(
183+
np.arctan2(approach_vec[1], approach_vec[0]) * np.array([0, 0, 1])
184+
).as_matrix()
185+
approach_frame.transform = ros2_numpy.msgify(Transform, approach_mat)
186+
approach_frame.header.stamp = self.node.get_clock().now().to_msg()
187+
approach_frame.header.frame_id = "food"
188+
approach_frame.child_frame_id = "approach"
189+
set_static_tf(approach_frame, self.blackboard, self.node)
190+
191+
### Calculate F/T Thresholds
192+
self.blackboard_set(
193+
"approach_thresh",
194+
create_ft_thresh_request(action.pre_force, action.pre_torque),
195+
)
196+
self.blackboard_set(
197+
"grasp_thresh",
198+
create_ft_thresh_request(action.grasp_force, action.grasp_torque),
199+
)
200+
self.blackboard_set(
201+
"ext_thresh",
202+
create_ft_thresh_request(action.ext_force, action.ext_torque),
155203
)
156-
return py_trees.common.Status.FAILURE
157-
position = (
158-
position
159-
* self.blackboard_get("move_above_dist_m")
160-
/ np.linalg.norm(position)
161-
)
162-
action.pre_transform.position = ros2_numpy.msgify(Point, position)
163-
self.blackboard_set("move_above_pose", action.pre_transform)
164-
165-
# Calculate Approach Target (in food frame)
166-
move_into_pose = Pose()
167-
move_into_pose.orientation = deepcopy(action.pre_transform.orientation)
168-
offset = ros2_numpy.numpify(action.pre_offset)
169-
move_into_pose.position = ros2_numpy.msgify(Point, offset)
170-
self.blackboard_set("move_into_pose", move_into_pose)
171-
172-
### Calculate Approach Frame
173-
approach_vec = offset - position
174-
approach_frame = TransformStamped()
175-
approach_mat = np.eye(4)
176-
if not np.all(np.isclose(approach_vec[:2], np.zeros(2))):
177-
approach_mat[:3, :3] = R.from_rotvec(
178-
np.arctan2(approach_vec[1], approach_vec[0]) * np.array([0, 0, 1])
179-
).as_matrix()
180-
approach_frame.transform = ros2_numpy.msgify(Transform, approach_mat)
181-
approach_frame.header.stamp = self.node.get_clock().now().to_msg()
182-
approach_frame.header.frame_id = "food"
183-
approach_frame.child_frame_id = "approach"
184-
set_static_tf(approach_frame, self.blackboard, self.node)
185-
186-
### Calculate F/T Thresholds
187-
self.blackboard_set(
188-
"approach_thresh",
189-
create_ft_thresh_request(action.pre_force, action.pre_torque),
190-
)
191-
self.blackboard_set(
192-
"grasp_thresh",
193-
create_ft_thresh_request(action.grasp_force, action.grasp_torque),
194-
)
195-
self.blackboard_set(
196-
"ext_thresh",
197-
create_ft_thresh_request(action.ext_force, action.ext_torque),
198-
)
199204

200-
### Final write to Blackboard
201-
self.blackboard_set("action", action)
205+
### Final write to Blackboard
206+
self.blackboard_set("action", action)
202207
return py_trees.common.Status.SUCCESS
203208

204209

ada_feeding/ada_feeding/trees/acquire_food_tree.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ def create_tree(
323323
) # End RecoverySequence
324324

325325
def move_above_plan(
326-
flip_food_frame: bool = False,
326+
flip_food_frame: bool = False, action: Optional[BlackboardKey] = None,
327327
) -> py_trees.behaviour.Behaviour:
328328
return py_trees.composites.Sequence(
329329
name="MoveAbovePlanningSeq",
@@ -380,7 +380,7 @@ def move_above_plan(
380380
inputs={
381381
"action_select_response": BlackboardKey(
382382
"action_response"
383-
),
383+
), "action": action,
384384
# Default move_above_dist_m = 0.05
385385
# Default food_frame_id = "food"
386386
# Default approach_frame_id = "approach"
@@ -523,7 +523,7 @@ def move_above_plan(
523523
memory=True,
524524
children=[
525525
move_above_plan(False),
526-
move_above_plan(True),
526+
move_above_plan(True, BlackboardKey("action")),
527527
],
528528
),
529529
MoveIt2Execute(

ada_feeding/launch/ada_feeding_launch.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
</node>
1919

2020
<!-- Launch the action servers necessary to move the robot -->
21-
<node pkg="ada_feeding" exec="create_action_servers.py" name="ada_feeding_action_servers" respawn="true" args="--ros-args --log-level $(var log_level) --log-level rcl:=INFO --log-level rmw_fastrtps_cpp:=INFO">
21+
<node pkg="ada_feeding" exec="create_action_servers.py" name="ada_feeding_action_servers" respawn="true" args="--ros-args --log-level $(var log_level) --log-level rcl:=INFO --log-level rmw_cyclonedds_cpp:=INFO">
2222
<param from="$(find-pkg-share ada_feeding)/config/ada_feeding_action_servers_default.yaml"/>
2323
<param from="$(find-pkg-share ada_feeding)/config/ada_feeding_action_servers_custom.yaml"/>
2424
<remap from="~/watchdog" to="/ada_watchdog/watchdog" />

ada_feeding_action_select/ada_feeding_action_select/policies/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
# Linear Policies
1313
from .linear_policies import RandomLinearPolicy
14+
from .linear_policies import GreedyLinearPolicy
15+
from .linear_policies import EpsilonGreedyLinearPolicy
16+
from .linear_policies import LinUCBPolicy
1417

1518
# Color Policy
1619
from .color_policy import ColorPolicy

ada_feeding_action_select/ada_feeding_action_select/policies/linear_policies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def _solve(self, arm=None):
207207
solve_out = self.checkpoint.linear_model[arm, :]
208208

209209
# Solve for linear policy vector
210-
solve_out[:] = np.linalge.solve(solve_a, solve_b)
210+
solve_out[:] = np.linalg.solve(solve_a, solve_b)
211211

212212
@override
213213
def get_checkpoint(self) -> Any:

ada_feeding_action_select/ada_feeding_action_select/policy_service.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ def select_callback(
349349
self.get_logger().info(
350350
f"AcquisitionSelect Success! Sending Response with ID: '{response.id}'"
351351
)
352+
352353
return response
353354

354355
def report_callback(
@@ -382,6 +383,8 @@ def report_callback(
382383
select.actions[request.action_index],
383384
)
384385

386+
self.get_logger().info(f"Executed Action: '{request.action_index}'")
387+
385388
# Run the posthoc adapter
386389
posthoc = self.posthoc_adapter.get_posthoc(np.array(request.posthoc))
387390
if posthoc.size != self.posthoc_adapter.dim:

0 commit comments

Comments
 (0)