Ask Your Question
3

Communication between ROS and wxWidgets

asked 2011-11-14 19:06:51 -0500

updated 2014-01-28 17:10:47 -0500

ngrennan gravatar image

What's the best way of sending and receiving ROS messages to and from a wxWidgets GUI in C++? I have a GUI that should be updated with status of some ROS nodes and I want to be able to send some ROS messages to ROS nodes when a button is clicked i the GUI (or similar).

I have tried to make wxApp as a ROS node and update the GUI when a ROS message is received, but it does not work (some problems with threads).

There must be a 'default' way of communicating with other C++ programs in a wxWidgets GUI?

edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
3

answered 2011-11-15 20:05:40 -0500

I got it to work now. It turned out that I forgot to change the call to wxFrame, so the Frame that was supposed to be a class variable was actually a local variable. :-( I'm so mad at myself that I didn't see that sooner...

Anyway, if someone else wants to connect ROS and wxWidgets, this is how I did it:

In wxApp:

  • In OnInit(): call ros::init() (convert wxString in argv to char**)
  • In Onrun(): create a nodehandle and call subscribe with a reference to the wxFrame object. End OnRun with return wxApp::OnRun();

In wxFrame:

  • Create a timer event that calls ros::spinonce() in its callback method.
  • Create a callback method for the ROS message and do some exciting stuff in it :-)
edit flag offensive delete link more

Comments

Hi Ola, I am trying to building a GUI with wxWidgets (using Code::Block). Can you point me where I can find the wxApp::OnRun()? Or where can I read more about it, please.

LivingMachine gravatar imageLivingMachine ( 2013-07-05 17:00:41 -0500 )edit

I don't think it is there by default, but you should place it in the App-class, so something like this: int MyCoolApp::OnRun() { // subscribers and stuf goes here return wxApp::OnRun(); }

Ola Ringdahl gravatar imageOla Ringdahl ( 2013-08-13 21:41:02 -0500 )edit

Hello, Ola. I have some questions for you, I hope you can answer me.

When you said "Create a timer event that calls ros::spinonce() in its callback method.", did you mean that we have to create a wxTimerEvent? http://docs.wxwidgets.org/trunk/class...

Adri gravatar imageAdri ( 2016-02-16 05:21:06 -0500 )edit

And the other question is: When you said "In OnInit(): call ros::init() (convert wxString in argv to char**)", which argv do you mean?

Thank you in advance.

Adri gravatar imageAdri ( 2016-02-16 05:27:09 -0500 )edit

Yes you should create a wxTimerEvent. In onInit, I do the following: char* argvForRos = new char[argc]; for (int i = 0; i < argc; ++i) { argvForRos[i] = strdup(wxString(argv[i]).mb_str()); } ros::init(argc, _argvForRos, "my

Gui");

Ola Ringdahl gravatar imageOla Ringdahl ( 2016-02-16 07:04:02 -0500 )edit

Thank you for your answer. In onInit I tried directly with a casting and it worked too: ros::init(argc, (char **) argv, "my_other_GUI");

Again, thank you so much, Ola. You helped me a lot, :)

Adri gravatar imageAdri ( 2016-02-17 04:53:35 -0500 )edit
4

answered 2011-11-15 12:30:27 -0500

Patrick Mihelich gravatar image

I have little experience with wxWidgets, but I can give a general answer for using ROS subscribers/publishers within a GUI framework.

First read http://answers.ros.org/question/2853/significance-of-rosspinonce#4581 and the roscpp overview of callbacks and spinning. This is an example of "Integrating ROS with framework X."

Using ROS requires two things:

  • Initialization: Call ros::init(...), create a ros::NodeHandle, and create any ros::Publisher's or ros::Subscriber's you need.
  • Event handling: Periodically (on the order of 10ms) call ros::spinOnce() to handle callbacks for any just-arrived messages.

In a simple ROS node, you'd do all that in your main(). Set up your ROS communication, and then call ros::spin() to handle events until the node shuts down.

Some GUI frameworks (like wxWidgets) claim main() entirely for themselves, so you have to slot these tasks into whatever hooks the framework gives you. In the framework's "On Init" hook, do your ROS initialization, and then set up a timer event (using whatever mechanism the framework provides) that calls ros::spinOnce().

edit flag offensive delete link more
0

answered 2011-11-15 18:21:20 -0500

Thank you for your answer! I have done as you suggest, but it still does not work. If I create a subscriber in OnInit(), the node does not subscribe to any messages. If I call subscribe in OnRun(), the callback function works (i.e gets called when a message arrive). However, when I try to update the icon of a button in the callback, I get a segmentation fault because this point to null.

I have tried to have the callback function in the wxApp class and in the wxFrame class (the one that starts the GUI and the GUI itself respectively). The result is the same; all references are gone (points to null) in the callback method.

It feels like it has something to do with threads, but I can't figure out why this should be a problem in this case...

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2011-11-14 19:06:51 -0500

Seen: 1,006 times

Last updated: Nov 15 '11