Difference between revisions of "Calico ROS"

From IPRE Wiki
Jump to: navigation, search
(ROS)
(Issues)
Line 149: Line 149:
 
= Issues =
 
= Issues =
  
# does it shutdown correctly?
+
# Does it shutdown correctly? I think so, as long as you call UnSubscribe. How to do that automatically?
# can we package this up so that it callable from other languages?
+
# If you run the code twice, how to unsubscribe from the first, if there is an error?
 +
## finally?
 +
## with...?
 +
# Can we package this up so that it callable from other languages?
 +
## Add functions to C# code.

Revision as of 10:25, 15 October 2012

This page describes creating a ROS/Calico connection.

ROS

ROS is the Robot Operating System. Here we assume a standard ROS install. Also, we assume that Mono has been installed. The example below uses Ubuntu.

RosCS

RosCS is a ROS package which creates a connection between Mono and ROS. It takes a C# file and dynamically builds all of the needed links into a set of dynamic link libraries (DLL).

First, we need a local copy of ROS. We are using the current version of ROS (called "fuerte"):

  1. source /opt/ros/fuerte/setup.bash
  2. mkdir ~/ros
  3. rosws init ~/ros /opt/ros/fuerte
  4. source ~/ros/setup.bash
  5. roscd

Next, we need to install the package RosCS:

  1. rosws set cn-roscs-ros-pkg --git https://code.google.com/p/cn-roscs-ros-pkg/
  2. source ~/ros/setup.sh
  3. rosws update cn-roscs-ros-pkg
  4. [remove <rosdep name="mono"> from ~/ros/cn-roscs-ros-pkg/roscs/manifest.xml]
  5. rosdep install roscs

Finally, we create a C# file and build the DLLs:

  1. mkdir sandbox
  2. rosws set ~/ros/sandbox
  3. source ~/ros/setup.sh
  4. cd sandbox
  5. roscreate-pkg ROS std_msgs rospy roscpp roscs
  6. Create a C# file in ROS/src/hello.cs (see below)
  7. Edit ROS/CMakeLists.txt to add text (see below)
  8. roscd ROS
  9. rosmake

If it compiles without errors, then you can copy the .dll and .so files from lib to Calico/modules/

  1. cd lib
  2. cp *.dll *.so ~/Calico/trunk/modules/

The next section explores using these libraries.

hello.cs:

using System;
using System.Threading;
using RosCS;

public class RosCsExample
{
    Node node;
    Publisher pub;

    public RosCsExample()
    {
	this.node = Node.MainNode;
	this.pub = new Publisher(this.node,"DummyTopic",RosCS.std_msgs.String.TypeId,1);
	this.node.Subscribe("DummyTopic",OnMessage,6);
        
    }

    public void OnMessage(RosCS.std_msgs.String msg) {
	Console.WriteLine("Got message: "+msg.Data);
    }

    public void Run() {
	int i = 0;
	while(RosSharp.Ok()) {
	    RosCS.std_msgs.String msg = new RosCS.std_msgs.String();
	    msg.Data ="Hello "+i;
	    this.pub.Send(msg);
	    i++;
	    Thread.Sleep(1000);
	}                       
    }               

    public static void Main(string[] args) {                        
	RosSharp.Init("NodeName",args);                 
	RosCsExample rce = new RosCsExample();
	rce.Run();
    }
}

Add to bottom of CMakeLists.txt:

rosbuild_include(roscs cncs)
rosbuild_gen_cs_msg()
rosbuild_gensrv()
CSHARP_ADD_TARGET_DEPENDENCY(hello Mono.C5) 
CSHARP_ADD_EXE(hello src/hello.cs)

Calico

  1. In a terminal, run roscore:
    1. source ~/ros/setup.bash
    2. roscore
  2. In another terminal, start Calico:
    1. StartCalico
    2. Run sample Python code (below)
  3. In another terminal, run rostopic
    1. rostopic echo DummyTopic
import System
import RosCS

# First we initialize the root (NodeName) and get the node:
RosCS.RosSharp.Init("NodeName", System.Array[str]([]))
node = RosCS.Node.MainNode

# Next, we create a publisher to post on a topic, here DummyTopic:
publisher = RosCS.Publisher(node, "DummyTopic", RosCS.std_msgs.String.TypeId, 1)
# It is setup to receive string messages

# Next, we setup a String Message receiver callback:
def OnMessage(msg):
    ## msg is RosCS.std_msgs.String
    print("Got message: " + msg.Data);

# Directly calling the Subscribe doesn't work because signature is based on type:
# node.Subscribe("DummyTopic", OnMessage, 6)
# So, we get the overload by type:
Subscribe = node.Subscribe.Overloads[str, RosCS.OnString, int]
# and call it:
Subscribe("DummyTopic", OnMessage, 6)

# And now we start sending and receiving messages:
i = 0
while RosCS.RosSharp.Ok() and i < 10:
    # Create a string message:
    msg = RosCS.std_msgs.String()
    msg.Data = "Hello " + str(i)
    # Send it:
    publisher.Send(msg)
    # Wait for a second, and continue:
    i += 1
    System.Threading.Thread.Sleep(1000)

# and unsubscribe:
UnSubscribe = node.UnSubscribe.Overloads[str, RosCS.OnString]
UnSubscribe("DummyTopic", OnMessage)

Issues

  1. Does it shutdown correctly? I think so, as long as you call UnSubscribe. How to do that automatically?
  2. If you run the code twice, how to unsubscribe from the first, if there is an error?
    1. finally?
    2. with...?
  3. Can we package this up so that it callable from other languages?
    1. Add functions to C# code.