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

Pause and resume an action state #18

Open
WZHwerk5 opened this issue May 14, 2024 · 16 comments
Open

Pause and resume an action state #18

WZHwerk5 opened this issue May 14, 2024 · 16 comments

Comments

@WZHwerk5
Copy link

Hi, I just wonder how to pause/resume an action state with a ROS2 service. Thanks!

@mgonzs13
Copy link
Collaborator

Hey @WZHwerk5, the action state involves using ROS 2 actions which, as far as I know, cannot be paused/resumed. However, pausing/resuming a state could be a good feature. Do you have any suggestions?

@WZHwerk5
Copy link
Author

Ok I see, thanks for quick reply! Let's step back a bit, how to cancel a running action state by a service (e.g. a Trigger)? Could you give me an example? Thanks in advance

@mgonzs13
Copy link
Collaborator

In YASMIN, all states can be implemented to be canceled. In the case of the action states, canceling a state means canceling the action server. An example of action state is shown here. Thus, to cancel the FSM sm, you can use the following code:

sm.cancel_state()

@mgonzs13
Copy link
Collaborator

mgonzs13 commented Jun 3, 2024

Hey @WZHwerk5, how is this going?

@WZHwerk5
Copy link
Author

WZHwerk5 commented Jun 3, 2024

Hi, it worked, thanks.

@mgonzs13 mgonzs13 closed this as completed Jun 3, 2024
@jonyktan
Copy link

Hi, can I get some advice on how to cancel actions please? Given that the ActionState outcomes are (SUCCEED, ABORT, CANCEL), how can I trigger ABORT or CANCEL?

@mgonzs13
Copy link
Collaborator

Hi @jonyktan, you have how to cancel an action in the previous comments.

In YASMIN, all states can be implemented to be canceled. In the case of the action states, canceling a state means canceling the action server. An example of action state is shown here. Thus, to cancel the FSM sm, you can use the following code:

sm.cancel_state()

@mgonzs13 mgonzs13 reopened this Oct 10, 2024
@jonyktan
Copy link

jonyktan commented Oct 10, 2024 via email

@mgonzs13
Copy link
Collaborator

Let us consider the action_client_demo.py. In this example, a FSM is created with an ActionState. Then, the FSM is executed inside the main thread of the program.

To overview an example of canceling a FSM we can execute the FSM of the demo in a new thread as follows:

    import threading
    t = threading.Thread(target=sm, args=(blackboard,))
    t.start()
    t.join()

This way, we can attempt to cancel the FSM while executing. Here you have the code modified canceling the FSM, for instance after 2 seconds of starting the execution:

    import time
    import threading
    t = threading.Thread(target=sm, args=(blackboard,))
    t.start()
    time.sleep(2)
    sm.cancel_state()
    t.join()

I hope this is helpful to you. I'll add an example to the demo pkg.

Copy link

This issue is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale label Dec 14, 2024
Copy link

This issue was closed because it has been inactive for 14 days since being marked as stale.

@jonyktan
Copy link

jonyktan commented Jan 3, 2025

Hi again and happy new year! Sorry life happened and I only got back to this recently.

I tested the latest action_client_demo.py with the sm.cancel_state() implemented but noticed that the KeyboardInterrupt that triggers the cancel_state() kills the SM as well.

Instead, I was hoping that the SM could accept a cancel state event while in ActionState that when triggered, would send a cancel_goal to the Fib action server and then transit back to its previous state, staying alive and ready for a new event to trigger the ActionState.

So ideally:

    sm.add_state(
        "CALLING_FIBONACCI",
        FibonacciState(),
        transitions={
            SUCCEED: "PRINTING_RESULT",
            CANCEL: "<previous state>", # Event triggered cancellation of the action goal
            ABORT: "<another state>", # Action server triggered abort of the action
        },
    )

Do you have any suggestions on how I could do this in my state machine using YASMIN? Thanks for the help!

@mgonzs13 mgonzs13 reopened this Jan 6, 2025
@mgonzs13
Copy link
Collaborator

mgonzs13 commented Jan 6, 2025

Hi @jonyktan, KeyboardInterrupt cancels the state machine since I want to stop all the demos. However, as mentioned before, you can create a service that cancels a state. What if you create a state, like the Fibonacci state, that inherits from ActionState and creates a service to cancel it?

@github-actions github-actions bot removed the stale label Jan 7, 2025
@jonyktan
Copy link

jonyktan commented Jan 8, 2025

Hi @mgonzs13, thanks for your reply! I am not sure I understand what you mean - do you mean creating another ActionState (e.g. "CancelFibonacciState) within the same SM? While in FibonacciState, I wouldn't be able to transit to CancelFibonacciState until the Fibonacci action is complete though?

In YASMIN, all states can be implemented to be canceled. In the case of the action states, canceling a state means canceling the action server. An example of action state is shown here. Thus, to cancel the FSM sm, you can use the following code:

sm.cancel_state()

Also, I don't think cancelling the action should cancel the action server, as the action server should be independent of the action client (the ActionState).

@jonyktan
Copy link

jonyktan commented Jan 8, 2025

Hi, it worked, thanks.

@WZHwerk5, would you be able to share a little on how you got it to work please? Thanks!

@mgonzs13
Copy link
Collaborator

mgonzs13 commented Jan 8, 2025

Also, I don't think cancelling the action should cancel the action server, as the action server should be independent of the action client (the ActionState).

@jonyktan Cancling an action state will cancel the action client which means trying to cancel to action server.

One option is to cancel the state machine which will cancel the current state. You can use the following code inside a ROS 2 service:

sm.cancel_state()

Another option could be creating a service that cancels a specific state. For example, you can create this service inside the Fibonacci state as follow. However, take into account that having multiple instance of this state will create multiple service to cancel Fibonacci.

from yasmin_ros.yasmin_node import YasminNode
from std_srvs.srv import Trigger


class FibonacciState(ActionState):
    """
    Class representing the state of the Fibonacci action.

    Inherits from ActionState and implements methods to handle the
    Fibonacci action in a finite state machine.

    Attributes:
        None
    """

    def __init__(self) -> None:
        """
        Initializes the FibonacciState.

        Sets up the action type and the action name for the Fibonacci
        action. Initializes goal, response handler, and feedback
        processing callbacks.

        Parameters:
            None

        Returns:
            None
        """

        node = YasminNode.get_instance()
        self._cancel_srv = node.create_service(
            Trigger, "/cancel_fibonacci", self.cancel_fibonacci_cb
        )

        super().__init__(
            Fibonacci,  # action type
            "/fibonacci",  # action name
            self.create_goal_handler,  # callback to create the goal
            None,  # outcomes. Includes (SUCCEED, ABORT, CANCEL)
            self.response_handler,  # callback to process the response
            self.print_feedback,  # callback to process the feedback
        )

    def cancel_fibonacci_cb(
        self, req: Trigger.Request, res: Trigger.Response
    ) -> Trigger.Response:
        self.cancel_state()
        return res

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

No branches or pull requests

3 participants