uml-robotics / ROS.NET

ROS.NET: ROS Client Library for Windows Development in C#
BSD 2-Clause "Simplified" License
93 stars 52 forks source link

Which version of ROS does this ROS.NET implementation support? #11

Closed nickkazepis closed 9 years ago

nickkazepis commented 9 years ago

Hello from Greece! I was poking around on the internet and landed on this repo. I want to develop C# applications on windows (8.1) that are able to communicate with ROS Indigo Igloo running on some other Ubuntu 14.04 machine. So I am wondering whether this .NET repo will do the trick and which version of ROS it supports. Thank you in advance!

nuclearmistake commented 9 years ago

It should be fine communicating with versions from diamondback through indigo. As far as version-compatibility, if you don't see message md5sum mismatches in rosout, then it'll work, and the messages that have changed since diamondback are on a very short list and relatively obscure.

With windows 8.1, be careful with the XmlRpcWin32... I have only compiled it with VS2008 (previously) and VS2010... with VS2012, I've only had success by not upgrading that project... but I wasn't exhaustive.

As it is implemented now, you won't be able to make windows store or windows RT apps, but any traditional desktop program will work on windows 7-10

nickkazepis commented 9 years ago

Nice! I'm going to give it a try and come back with the results. As I understood from the readme this will allow me to build custom message types. I already have an Ubuntu with indigo up and running so I'm going to give this repo a spin and report back to you. I'm new to ROS but a quick learner. I don't intend to build store apps or RT. I'm planning on building traditional desktop programs so this going to be ok. As far as XmlRpcWin32 is concerned I'll try not to upgrade and see how this will go. I am planning on using VS2013 but if anything f(l)ails there is no problem going back to VS2010 I suppose. Let me try VS2013 first and then see how things turn out. Anyway, you've done a great job!!!

nuclearmistake commented 9 years ago

hehe thanks. Everything but TF is generally solid... used it for a few funded projects and competitions (with fuerte, hydro, and indigo robots)... usually with WPF UIs.

For custom messages, a recent (maybe not yet documented) advancement is that you can treat projects' folders like ros package folders... so if you made a project called "my_node" and put my_msg.msg in the msg folder inside it, it would generate the Messages.my_node.my_msg class... then on the linux side, you would just need a ros package called my_node with the same my_msg.msg in its msg folder for linux nodes to import/include to communicate with your .NET node

nickkazepis commented 9 years ago

Hello, I'm back with my preliminary results as promised. Compilation succeeded without any problem at all. I upgraded the XmpRpcWin32 project and it compiled successfully (VS2013, Win8.1) I run a roscore, a sample talker, a sample listener and a rqt_graph on my Ubuntu 14.04 (ROS Indigo). I run a SimpleSubscriber on my windows machine ta talk to the linux. The Subscriber WPF window loaded successfully but there are no messages received. I have set ROS_MASTER_URI, ROS_HOSTNAME and ROS_IP to point to the Ubuntu machine. I have changed the SimpleSubscriber to listen to my topic (a simple String chatter):

    Subscriber<Messages.std_msgs.String> sub;
    NodeHandle nh;
    DateTime before;
    public MainWindow()
    {
        before = DateTime.Now;
        InitializeComponent();

        ROS.ROS_MASTER_URI = "http://192.168.56.101:11311";
        ROS.ROS_HOSTNAME = "192.168.56.101";

        ROS.Init(Environment.GetCommandLineArgs(), "chatter");

        nh = new NodeHandle();

        sub = nh.subscribe<Messages.std_msgs.String>("/chatter", 10, subCallback);
    }

    public void subCallback(Messages.std_msgs.String msg)
    {
        Dispatcher.Invoke(new Action(() =>
        {
            TimeSpan dif = DateTime.Now.Subtract(before);
            l.Content = "Received: " + msg.data + "\n" + Math.Round(dif.TotalMilliseconds, 2) + " ms"; ;
        }));

        before = DateTime.Now;
    }

Finally after shutting down my simple subscriber and tried to re-run the rqt_graph on the Ubuntu I got an exception which resolved only AFTER I restarted my roscore. :(

PluginHandlerDirect._restore_settings() plugin "rqt_graph/RosGraph#0" raised an exception: Traceback (most recent call last): File "/opt/ros/indigo/lib/python2.7/dist-packages/qt_gui/plugin_handler_direct.py", line 116, in _restore_settings self._plugin.restore_settings(plugin_settings_plugin, instance_settings_plugin) File "/opt/ros/indigo/lib/python2.7/dist-packages/rqt_graph/ros_graph.py", line 202, in restore_settings self._refresh_rosgraph() File "/opt/ros/indigo/lib/python2.7/dist-packages/rqt_graph/ros_graph.py", line 226, in _refresh_rosgraph self._update_graph_view(self._generate_dotcode()) File "/opt/ros/indigo/lib/python2.7/dist-packages/rqt_graph/ros_graph.py", line 259, in _update_graph_view self._redraw_graph_view() File "/opt/ros/indigo/lib/python2.7/dist-packages/rqt_graph/ros_graph.py", line 292, in _redraw_graph_view same_label_siblings=True) File "/opt/ros/indigo/lib/python2.7/dist-packages/qt_dotgraph/dot_to_qt.py", line 256, in dotcode_to_qt_items subgraph_nodeitem = self.getNodeItemForSubgraph(subgraph, highlight_level) File "/opt/ros/indigo/lib/python2.7/dist-packages/qt_dotgraph/dot_to_qt.py", line 83, in getNodeItemForSubgraph bb = subgraph.attr['bb'].strip('"').split(',') KeyError: 'bb'

Any ideas? Thank you in advance!

nuclearmistake commented 9 years ago

Try "rosnode list" after the UI os closed... Probably not ubregistering itself with master. Override OnClosed() in the window and try to call ROS.shutdown(); ROS.waitForShutdown() before super.OnClosed() in it.

Also, rather than just stopping the debugger, hitting X on the window usually increases the likelihood of the window "saying bye" to master in a way that doesn't leave a ghost node behind. On May 22, 2015 6:32 AM, "nickkazepis" notifications@github.com wrote:

Hello, I'm back with my preliminary results as promised. Compilation succeeded without any problem at all. I upgraded the XmpRpcWin32 project and it compiled successfully (VS2013, Win8.1) I run a roscore, a sample talker, a sample listener and a rqt_graph on my Ubuntu 14.04 (ROS Indigo). I run a SimpleSubscriber on my windows machine ta talk to the linux. The Subscriber WPF window loaded successfully but there are no messages received. I have set ROS_MASTER_URI, ROS_HOSTNAME and ROS_IP to point to the Ubuntu machine. I have changed the SimpleSubscriber to listen to my topic (a simple String chatter):

Subscriber<Messages.std_msgs.String> sub;
NodeHandle nh;
DateTime before;
public MainWindow()
{
    before = DateTime.Now;
    InitializeComponent();

    ROS.ROS_MASTER_URI = "http://192.168.56.101:11311";
    ROS.ROS_HOSTNAME = "192.168.56.101";

    ROS.Init(Environment.GetCommandLineArgs(), "chatter");

    nh = new NodeHandle();

    sub = nh.subscribe<Messages.std_msgs.String>("/chatter", 10, subCallback);
}

public void subCallback(Messages.std_msgs.String msg)
{
    Dispatcher.Invoke(new Action(() =>
    {
        TimeSpan dif = DateTime.Now.Subtract(before);
        l.Content = "Received: " + msg.data + "\n" + Math.Round(dif.TotalMilliseconds, 2) + " ms"; ;
    }));

    before = DateTime.Now;
}

Finally after shutting down my simple subscriber and tried to re-run the rqt_graph on the Ubuntu I got an exception which resolved only AFTER I restarted my roscore. :(

PluginHandlerDirect._restore_settings() plugin "rqt_graph/RosGraph#0" raised an exception: Traceback (most recent call last): File "/opt/ros/indigo/lib/python2.7/dist-packages/qt_gui/plugin_handler_direct.py", line 116, in _restore_settings self._plugin.restore_settings(plugin_settings_plugin, instance_settings_plugin) File "/opt/ros/indigo/lib/python2.7/dist-packages/rqt_graph/ros_graph.py", line 202, in restore_settings self._refresh_rosgraph() File "/opt/ros/indigo/lib/python2.7/dist-packages/rqt_graph/ros_graph.py", line 226, in _refresh_rosgraph self._update_graph_view(self._generate_dotcode()) File "/opt/ros/indigo/lib/python2.7/dist-packages/rqt_graph/ros_graph.py", line 259, in _update_graph_view self._redraw_graph_view() File "/opt/ros/indigo/lib/python2.7/dist-packages/rqt_graph/ros_graph.py", line 292, in _redraw_graph_view same_label_siblings=True) File "/opt/ros/indigo/lib/python2.7/dist-packages/qt_dotgraph/dot_to_qt.py", line 256, in dotcode_to_qt_items subgraph_nodeitem = self.getNodeItemForSubgraph(subgraph, highlight_level) File "/opt/ros/indigo/lib/python2.7/dist-packages/qt_dotgraph/dot_to_qt.py", line 83, in getNodeItemForSubgraph bb = subgraph.attr['bb'].strip('"').split(',') KeyError: 'bb'

Any ideas? Thank you in advance!

— Reply to this email directly or view it on GitHub https://github.com/uml-robotics/ROS.NET/issues/11#issuecomment-104612676 .

nickkazepis commented 9 years ago

OK! That solved the ghost node problem! I did what you said and the rosnode list no longer displays the ghost windows node because it now sends proper goodbye :)

However I am still unable to receive any messages on windows from the talker process on the ubuntu machine.

More insight: If I start the talker and listener on the ubuntu side they talk to each other. Then, when I start my listener on the windows side I get this on the output window:

Publisher update for [/chatter]: http://lemnos:54146/, already have these connections: Failed to contact publisher [lemnos:54146] for topic [/chatter]

lemnos is the name of my ubuntu (virtual machine 192.168.56.101) What port is this? Is it the right one?

If there is no "talker" running on my ubuntu then the output just mentions this:

Publisher update for [/chatter]: already have these connections:

and then nothing else (since there are no connections on the /chatter topic I guess..

Any help on why the messages aren't getting through?

nickkazepis commented 9 years ago

Solved it! Somehow the stupid windows translated the ros master uri ip to hostname and then it couldnt resolve back the name to connect to the master!

One other thing: While the windows node is running the rqt_graph give the same exception and doesnt display anything. As soon as the windows node closes, the rqt_graph shows the ubuntu nodes without any exception.

Any ideas on that?

THANK you once again for your invaluable support!

nuclearmistake commented 9 years ago

Iirc, rqt_graph should work if started after the node? I think there's some weirdness with how it handles nodes that are killed and restarted... But I'll take a look into it.

For master uri and stuff, you can set them in your windows environment variables on the windows side, so source doesn't need to be changed every time your IP does... And I usually set the ROS_HOSTNAME to be the IP in the environment all of my Linux nodes are running in, which prevents any DNS weirdness from causing issues w/ the ros.net node resolving the IP of the Linux nodes On May 22, 2015 7:08 AM, "nickkazepis" notifications@github.com wrote:

Solved it! Somehow the stupid windows translated the ros master uri ip to hostname and then it couldnt resolve back the name to connect to the master!

One other thing: While the windows node is running the rqt_graph give the same exception and doesnt display anything. As soon as the windows node closes, the rqt_graph shows the ubuntu nodes without any exception.

Any ideas on that?

THANK you once again for your invaluable support!

— Reply to this email directly or view it on GitHub https://github.com/uml-robotics/ROS.NET/issues/11#issuecomment-104622203 .

nickkazepis commented 9 years ago

The rqt_graph dies with the aforementioned exception only when I try to start it while the windows node is running. If I stop the windows node first, rqt_graph starts normally... This is weird... Furthermore if I start the windows listener node before starting the talker node on Ubuntu, the windows node never receives any messages whatsoever. Any ideas on this?

nickkazepis commented 9 years ago

From what I understand the core module checks only once for existing publishers at initialization time. So if a publisher starts on the Ubuntu side AFTER the subscriber has started on the C# side, the subscriber never learns about or "hears" from the new publisher.

Any suggestions how to change that? This is an important point of failure since ALL subscribers HAVE to be started before the C# initialization code runs to be able to see them.

nickkazepis commented 9 years ago

Also the SimplePublisher although visible (as a node - through rosnode list) from the Ubuntu side, doesn't seem to publish any messages (the "rostopic echo /chatter" command doest show anything on the screen). Am I missing something important here? I mean I am clearly doing something wrong but has to be a major mistake. What are the steps to run a WPF ROS app? I need to call ROS.Init and then I need a while (ROS.ok)? There is no need for "spin" once or something, right? Thank you in advance.

nuclearmistake commented 9 years ago

There is no need for a spin... there's internal threading.

For a WPF app, you just need to call ROS.Init, create a nodehandle (that is scoped somewhere which won't get garbage collected), create pubs and subs (scoped somewhere which won't get garbage collected), and that's all that's needed until the window closes and things need to be shutdown cleanly... WPF-wise, just make sure to go through dispatcher.(begin)invoke in the callback, or it'll error because the callback is on a different thread.

What does rosnode info show for your .NET node?

nuclearmistake commented 9 years ago

I haven't seen any issues with node ordering in the past year-ish... could it be that the linux node's predecessor is not exiting? after it dies, does "rosnode cleanup" find any zombies?

nickkazepis commented 9 years ago

For the simple subscriber:

kazepis@lemnos:~$ rosnode info /simplesubscriber

Node [/simplesubscriber] Publications: None

Subscriptions:

Services: None

contacting node http://192.168.56.101:61808/ ... ERROR: Communication with node[http://192.168.56.101:61808/] failed!

But the IP of the windows machine is 192.168.56.1 and the IP of Ubuntu is: 192.168.56.101

The simple subscriber is a windows node so it shouldnt try to contact it on the 101 IP. Right?

When the windows node dies (most of the times it dies gracefully) the rosnode cleanup doesnt show any output.

nickkazepis commented 9 years ago

OMG Eric, I'm so stupid... I guess this is my mistake:

//from the windows simplesubscriber ROS.ROS_MASTER_URI = "http://192.168.56.101:11311"; ROS.ROS_HOSTNAME = "192.168.56.101";

The ROS.ROS_HOSTNAME should be pointed at the windows IP (..56.1) instead of the ubuntu (..56.101) right? I thought that everything should point to the Linux IP. Can you confirm that please?

nuclearmistake commented 9 years ago

YES... that would definitely cause the weirdness you're seeing.

The hostname needs to be the ip of the machine running the node, and the master_uri is the central machine they all talk to.

I'm uploading fresh versions of the simple* wpf nodes with healthier WPF+ROS lifecycles and without the programmatically set ROS_MASTER_URI and ROS_HOSTNAME. You can use either the user or system windows environment variables to set those variables for EVERY node on the system, which is far more manageable IMO.

env

nickkazepis commented 9 years ago

Oh God, you are the best! I'm going to call it a day and add in my tomorrow's TODO list to try and play with custom messages and services. I'll keep you posted in here! Thanx a million!

nickkazepis commented 9 years ago

Hello Eric, My odyssey continues :) I tried running the ServiceServer and the ServiceClient projects. The ServiceServer seems to work (I can call the addition service from the ubuntu side). The ServiceClient however throws an argument null exception at line 66 of the MainWindow.xaml.cs where the responce (resp) seems to be null after the service call. I investigated a little and I found that in ROS.NET\ROS_Comm\ServiceServerLink.cs line 307 the resp.Serialized becomes null after the call to resp.Deserialize which is the reason why the call at ROS.NET\ROS_Comm\ServiceServerLink.cs line 345 makes the responce to be null.

Since I can't understand the internal mechanics could you please look into this? Am I doing something incorrect? Thank you in advance!

nickkazepis commented 9 years ago

Good morning! :) I found out that changing the line ROS.NET\ROS_Comm\ServiceServerLink.cs:345 into resp = (MRes) iresp;//.Deserialize(iresp.Serialized); seems to fix the error. Can you please confirm that this change is enough and the correct way to handle the error? Thank you a lot.

P.S. Since I am new to github, do you believe that I should create a new issue?

nuclearmistake commented 9 years ago

And a pull request