Skip to content

Add SetGoal action and make the SetGoal service blocking - #20

Open
VitezGabriela wants to merge 4 commits into
ros-controls:masterfrom
b-robotized-forks:feat/set-goal-action
Open

Add SetGoal action and make the SetGoal service blocking#20
VitezGabriela wants to merge 4 commits into
ros-controls:masterfrom
b-robotized-forks:feat/set-goal-action

Conversation

@VitezGabriela

@VitezGabriela VitezGabriela commented Aug 11, 2026

Copy link
Copy Markdown

Summary

  • Add the SetGoal ROS 2 action interface and RosSetGoalActionServer.
  • Add ForemanErrorState message for action feedback/result error reporting.
  • Make the SetGoal service blocking by waiting on Foreman's engine snapshot until the requested goal is reached, fails, or is preempted.
  • Add a shared set_goal execution lock so action and service requests cannot overwrite each other while one goal is active.
  • Use a reentrant callback group for the blocking service so concurrent service callers can reach the lock and get rejected instead of silently waiting in the callback queue.
  • Add unit tests

Behavior Change

Previously, SetGoal service returned success when the goal request was accepted.

With this change, both interfaces now report completion only once Foreman reaches the requested goal:

  • The action result succeeds once Foreman reports at_goal = true.
  • The service response succeeds once Foreman reports at_goal = true.

If another set_goal request is already active through either the service or the action, the new request is rejected with:

Another set_goal request is already active.

Motivation

The old SetGoal service could only report whether Foreman accepted a requested goal. It returned before Foreman's transition loop had finished switching controllers and components, so clients had no Foreman-level ROS signal for when the requested state was actually reached.

This could create a race for clients that need the target controller to be active immediately after requesting a goal. For example, MoveIt could send a trajectory after SetGoal returned success while the joint trajectory controller was still inactive, causing the trajectory goal to be rejected.

The action solves this for action clients, while the blocking service keeps compatibility for existing service clients.

Testing

colcon build --packages-up-to foreman
colcon test --packages-up-to foreman
colcon test-result --verbose

Result: 59 tests, 0 errors, 0 failures, 0 skipped

@VitezGabriela
VitezGabriela marked this pull request as draft August 11, 2026 20:18
@VitezGabriela VitezGabriela changed the title Convert SetGoal service to ROS action Add SetGoal action and make the SetGoal service blocking Aug 12, 2026
@VitezGabriela
VitezGabriela marked this pull request as ready for review August 12, 2026 10:06
from foreman_msgs.msg import ForemanErrorState


def _to_error_msg(snapshot: ErrorSnapshot) -> ForemanErrorState:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is duplicating with the status library. So we have to see what we merge first to reuse as much as possible.

@VitezGabriela VitezGabriela Aug 13, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, what would you propose to do since there we have this function inlined but here we reuse it multiple times. Do you think best would be to make a conversion py file and import it in both?

Comment thread foreman/foreman/adapters/ros_set_goal_action_server.py Outdated
Comment thread foreman/foreman/adapters/ros_set_goal_action_server.py Outdated
Comment thread foreman/foreman/adapters/ros_set_goal_action_server.py Outdated
Comment thread foreman/foreman/adapters/ros_set_goal_action_server.py Outdated
while True:
if not goal_handle.is_active:
result.success = False
result.message = f"Goal '{goal_name}' was preempted."

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can this actually happen?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

On shutdown. Do you prefer it removed?

self._node.get_logger().info(f"{engine_response.message}")

feedback = SetGoal.Feedback()
while True:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are there no mechanisms in python where we wait for a variable to be set, in this case would be at_goal and ˙is_error`?

Maybe better to check those variable in the while loop, instead of while true. A bit more clarity, possibly.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

threading.Condition would work, but cancel and shutdown come from the goal handle, nothing notifies you about those, so you'd still need the 50 ms loop. And it changes also the engine, so that would maybe be another PR

We can check the variables in the while loop, but the loop if it exits you would not know why- So you have to ask again. That would be 8 checks instead of current 4 checks.

Comment thread foreman/foreman/adapters/ros_set_goal_action_server.py Outdated
@@ -7,17 +10,20 @@
class RosSetGoalServer:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When I see this. Maybe would actually make sense to make only one file with ROS interfaces. In that way, we might reduce some of the duplication. What do you think? If so, we should then make this in a follow-up PR.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I agree, we can have one file with the SetGoal service and action. We can do it in another PR

Comment thread foreman/foreman/adapters/ros_set_goal_action_server.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants