I want to write a finite state machine (FSM) like planner that has several different modes. I implement it as a system derived from the LeafSystem and want to use the witness function like in the rimless_wheel and the spring-loaded inverted pendulum example to define the transition between modes. (Follow the suggestion in the answer to my another question). To do so, I define a witness function inside my class:
self.touch_witness = self.MakeWitnessFunction('touch', WitnessFunctionDirection.kNegativeThenNonNegative, self.offset_vertical_force, UnrestrictedUpdateEvent(self.touch_event))
With the guard function self.offset_vertical_force defined as:
def offset_vertical_force(self, context):
F_ext = self.get_input_port(1).Eval(context)
return F_ext[1] - 1.0
Here the F_ext is the external force sensed and F_ext[1] is the force on the vertical direction. In my considered scenario, at first there is no external force so offset_vertical_force should return -1, then after collision happens, the offset_vertical_force would return a NonNegative Value. Then self.touch_event will be trigered. (The witness function is added with the DoGetWitnessFunctions method.)
However, when I run the code, I find that the self.touch_event is never triggered, despite the fact that self.offset_vertical_force returns negative value first and then returns positive value. Then when I change the guard function self.offset_vertical_force to use some continuous state of the FSM planner itself, I do see that the event can be triggered. So my first question is that is it true that the witness function (to be more precise, the guard function) can only be defined by the system's own internal state?
However, for my purpose I need the FSM planner's mode transition be triggered by the external information. My second question is that if the witness function can only be defined by the system's own internal state, are there some workaround ways?
Apart from above, I have also tried to change the state in the self.touch_event
def touch_event(self, context, event, state):
At first I tried to change the state using
context.get_mutable_continuous_state_vector().SetFromVector(value)
However, when I run the code I see no change in the state. Then I use
state.get_mutable_continuous_state().get_mutable_vector().SetFromVector(Value)
and when I run the code I can see the state changes. My understanding is that the context in the event function is const but the state in the event function is not. Am I right?
Thank you very much for your answer!