How to subscribe and process a joystick
Hello,
I'm trying to implement a FSM where the transitions are activated depending on the buttons of a joystick.
Following the tutorial, I'm implementing this instruction:
self._sub = ProxySubscriberCached({'/a_topic': MsgType})
self._sub = ProxySubscriberCached({'/joy': Joy})
At this moment, I can only "subscribe" to the /joy topic. But I don't know how to continue, also I'm newbie with python.
Can I create a joy_cb where processing the information of the message like in a normal node? Or the method in flexbe is different?
In the definition I have found something about the callback,
if topic not in ProxySubscriberCached._topics:
sub = rospy.Subscriber(topic, msg_type, self._callback, callback_args=topic)
ProxySubscriberCached._topics[topic] = {'subscriber': sub,
'last_msg': None,
'buffered': buffered,
'msg_queue': []}
if callback is not None:
ProxySubscriberCached._topics[topic]['subscriber'].impl.add_callback(callback, None)
But if I declare like this:
self._joy_sub = ProxySubscriberCached({'/joy': Joy}, self._joy_cb)
[...]
def _joy_cb(self, msg, topic):
It says: 'ContactoState' object has no attribute '_joy_cb' See onboard terminal for more information.
Thank you.
Because FlexBE runs it's states at a certain rate, the way you access ROS messages you received is a bit different.
There is no need to define a callback for the topic's subscriber, but just check the last received message in the State's execute method:
def __init__(self, topic='/joy'):
self._topic = topic
self._sub = ProxySubscriberCached({self._topic: Joy})
def execute(se,f userdata)
if self._sub.has_msg(self._topic):
msg = self._sub.get_last_msg(self._topic)
if matches_some_condition(msg):
return 'some_condition_matched'
# else:
# not returning anything means:
# do not exit the state, so that `execute` is called in the next 'tick' and hopefully we have received a message by then
Hi @LoyVanBeek, thank you for your help.
I have try to implement your code, but adapting it to my FSM.
def __init__(self, topic='/joy'):
super(ContactoState, self).__init__(outcomes = ['turn_on'])
self._topic = topic
self._joy_sub = ProxySubscriberCached({self._topic: Joy})
def execute(self, userdata):
if self._sub.has_msg(self._topic):
msg = self._sub.get_last_msg(self._topic)
if(msg.button[9] == 1):
return 'turn_on'
But I have the next error:
line 28, in ContactoState
self._topic = topic
NameError: name 'topic' is not defined"
And I know why the topic is not accepted in the declaration.
Kinds regards, Jorge
I really don't see why topic would not be defined. But there is no great need to have this as parameter, you can use
self._topic = '/joy'
in the constructor just as well, but makes the state less configurable if you ever have a different topic. Not required at all.
Note that if you use FlexBE for this application, be aware that is loops at a certain rate (configurable I think). And think about how that afferts interop with your joystick and looking at the last message. If you press the button for a shorter time than the loop rate AND only look at the last message, you could potentially miss a message where the button is pressed that is simply not the last message. Looking at all messages since the last 'tick' can solve that maybe
I don't know anything about your application, but there are other joystick-interpreters in ROS IIRC. FlexBE might not be the optimal choice for what you are doing.
Hi again Loy,
the application is just for controlling a vehicle with a logitech pad, but not only for the command_vel topic. It also require some commands for the ignition, turn off, ... that's why I would like to use a FSM. But maybe is not the best option.
Also, I try to search for ROS IIRC, but without results, could you give more information about IIRC?
Thank you
:-) IIRC means "If I Recall Correctly" but maybe that's just old internet slang.
But answering your question: I don't know which repo or package that would be. I made https://github.com/RobotRose/rose_joystick a loooong time ago and might be usable or provide some inspiration. Or not... You might use the ROS wiki or github to search for packages depending on these joystick messages and maybe that turns up something useful too.
A state machine is the way to go after you have a bunch of inputs to process, but you indeed really want to process those directly when they are received and not at a fixed rate. This is possible with FSMs of course, but as far as I understand, FlexBE is not really meant for this kind of FSM, more intended for high-level robot behavior. For your type of application, it might be faster, easier to write your own event processing state machine thing in plain Python.