yasmin icon indicating copy to clipboard operation
yasmin copied to clipboard

Pause and resume an action state

Open WZHwerk5 opened this issue 1 year ago • 3 comments

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

WZHwerk5 avatar May 14 '24 10:05 WZHwerk5

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?

mgonzs13 avatar May 14 '24 14:05 mgonzs13

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

WZHwerk5 avatar May 15 '24 08:05 WZHwerk5

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 avatar May 15 '24 14:05 mgonzs13

Hey @WZHwerk5, how is this going?

mgonzs13 avatar Jun 03 '24 09:06 mgonzs13

Hi, it worked, thanks.

WZHwerk5 avatar Jun 03 '24 10:06 WZHwerk5

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?

jonyktan avatar Oct 10 '24 10:10 jonyktan

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 avatar Oct 10 '24 14:10 mgonzs13

Could you give an example of where to insert sm.cancel_state() for an event to trigger the state cancellation while in that state please? I'm not too sure where to put it inside the ActionState

On Thu, Oct 10, 2024, 22:54 Miguel Ángel González Santamarta < @.***> wrote:

Hi @jonyktan https://github.com/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 https://github.com/uleroboticsgroup/yasmin/blob/main/yasmin_demo/yasmin_demo/action_client_demo.py. Thus, to cancel the FSM sm, you can use the following code:

sm.cancel_state()

— Reply to this email directly, view it on GitHub https://github.com/uleroboticsgroup/yasmin/issues/18#issuecomment-2405351455, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJYCWNNXRYHFEJI36HBQUOLZ22IJ3AVCNFSM6AAAAABHV5ZGW6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMBVGM2TCNBVGU . You are receiving this because you were mentioned.Message ID: @.***>

jonyktan avatar Oct 10 '24 15:10 jonyktan

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.

mgonzs13 avatar Oct 10 '24 17:10 mgonzs13

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

github-actions[bot] avatar Dec 14 '24 02:12 github-actions[bot]

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

github-actions[bot] avatar Dec 29 '24 02:12 github-actions[bot]

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!

jonyktan avatar Jan 03 '25 07:01 jonyktan

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?

mgonzs13 avatar Jan 06 '25 10:01 mgonzs13

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 avatar Jan 08 '25 07:01 jonyktan

Hi, it worked, thanks.

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

jonyktan avatar Jan 08 '25 07:01 jonyktan

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

mgonzs13 avatar Jan 08 '25 09:01 mgonzs13

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

github-actions[bot] avatar Feb 08 '25 01:02 github-actions[bot]

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

github-actions[bot] avatar Feb 22 '25 01:02 github-actions[bot]