(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

Groovy rosjava project setup

Description: This explains how to use the Groovy language to interact with ROS via rosjava

Tutorial Level:

WARNING: This documentation refers to an outdated version of rosjava and is probably incorrect. Use at your own risk. Follow updates on site: https://github.com/rosjava/rosjava_core and https://github.com/tkruse/rosjava_wiki_tutorials

Introduction

Groovy is a script language that is based on the Java Virtual Machine. As such we can use the rosjava libraries to interact with ROS.

Setup

Create a project just like in rosjava_tutorial_pubsub

Copy the build.gradle file from there, but make these modifications:

apply plugin: 'groovy'

dependencies {
  compile 'ros.rosjava_core:rosjava:0.0.0-SNAPSHOT'
  compile 'ros.rosjava_core:rosjava_messages:0.0.0-SNAPSHOT'
  compile 'ros.rosjava_core:rosjava_bootstrap:0.0.0-SNAPSHOT'
  // Libraries required for groovy
  groovy group: 'org.codehaus.groovy', name: 'groovy', version: '2.0.0'
}

The groovy version may be outdated by the time you read this tutorial.

Creating a Listener

We will create a simple Listener as in the Publisher / Subscriber rosjava Tutorial:

Copy / Create the file src/main/java/org/ros/rosjava_tutorial_pubsub/Talker.java, we will reuse the same Talker. You can also use the tutorial talker from c++ or python tutorials, of course.

Create this file as src/main/groovy/org/ros/rosgroovy_tutorial_pubsub/Listener.groovy:

package org.ros.rosgroovy_tutorial_pubsub

import org.apache.commons.logging.Log;

import org.ros.message.MessageListener;
import org.ros.namespace.GraphName;
import org.ros.node.AbstractNodeMain;
import org.ros.node.ConnectedNode;
import org.ros.node.NodeMain;
import org.ros.node.topic.Subscriber;

class Listener extends AbstractNodeMain {

  GraphName getDefaultNodeName() {
    new GraphName("rosjava_tutorial_pubsub/listener");
  }

  void onStart(ConnectedNode connectedNode) {
    final log = connectedNode.getLog();
    Subscriber<std_msgs.String> subscriber = connectedNode.newSubscriber("chatter", std_msgs.String._TYPE);
    subscriber.addMessageListener(new MessageListener<std_msgs.String>() {
      @Override
      void onNewMessage(std_msgs.String message) {
        log.info("I heard: \"${message.getData()}\"");
      }
    });
  }
}

The file must go there because that's where gradle picks up groovy files.

Note I am not an experienced Groovy programmer, so the code above might be ugly and too verbose for Groovy, it is a rather literal translation from the rosjava tutorial with just a bit of groovy syntax added.

build and run

To build, use gradle:

$ gradle installApp

To run, we use the same procedure as for rosjava:

$ roscore
$ ./build/install/rosjava_wiki_tutorial_pubsub/bin/rosjava_wiki_tutorial_pubsub org.ros.rosjava_tutorial_pubsub.Talker
$ ./build/install/rosjava_wiki_tutorial_pubsub/bin/rosjava_wiki_tutorial_pubsub org.ros.rosgroovy_tutorial_pubsub.Listener

Interactive usage

This section is for advanced users.

Groovy has two tools to code interactively, GroovyConsole and groovysh. The general problem is to set up the classpath for either.

GroovyConsole

GroovyConsole is relatively easy to start with gradle. In my case, what was required was this change to build.gradle:

dependencies {
  ...
  compile 'org.codehaus.groovy:groovy-all:2.0.0'
}

task(console, dependsOn: 'classes', type: JavaExec) {
  main = 'groovy.ui.Console'
  classpath = sourceSets.main.runtimeClasspath
}

Then the following should work:

$ gradle console

groovysh

To run groovysh, I found it a bit more difficult to get the classpath right. First I extended the dependencies in build.gradle to:

dependencies {
  ...
  compile 'xerces:xercesImpl:2.9.1'
  compile 'org.apache.commons:commons-cli:1.3-SNAPSHOT'
}

However I had to remove org.codehaus.groovy:groovy-all:2.0.0, due to some later conflicts.

Then, I ran

$ gradle installApp

This generates a shell script, in ./build/install/<project>/bin/<project>. The idea now is to copy the classpath section into a file. I created startgroovysh.sh

APP_HOME="`pwd -P`/build/install/rosgroovy_tutorials"

CLASSPATH=$APP_HOME/lib/rosgroovy_tutorials-0.0.0-SNAPSHOT.jar:\
$APP_HOME/lib/xercesImpl-2.9.1.jar:\
$APP_HOME/lib/rosjava-0.0.0-SNAPSHOT.jar:\
$APP_HOME/lib/rosjava_messages-0.0.0-SNAPSHOT.jar:\
$APP_HOME/lib/rosjava_bootstrap-0.0.0-SNAPSHOT.jar:\
$APP_HOME/lib/commons-pool-1.6.jar:\
$APP_HOME/lib/jsr305-1.3.9.jar:\
$APP_HOME/lib/guava-12.0.jar:\
$APP_HOME/lib/com.springsource.org.apache.commons.lang-2.4.0.jar:\
$APP_HOME/lib/com.springsource.org.apache.commons.codec-1.3.0.jar:\
$APP_HOME/lib/com.springsource.org.apache.commons.io-1.4.0.jar:\
$APP_HOME/lib/netty-3.5.1.Final.jar:\
$APP_HOME/lib/com.springsource.org.apache.commons.logging-1.1.1.jar:\
$APP_HOME/lib/junit-3.8.2.jar:\
$APP_HOME/lib/xml-apis-1.0.b2.jar:\
$APP_HOME/lib/ws-commons-util-1.0.1.jar:\
$APP_HOME/lib/com.springsource.org.apache.commons.httpclient-3.1.0.jar:\
$APP_HOME/lib/apache_xmlrpc_common-0.0.0-SNAPSHOT.jar:\
$APP_HOME/lib/apache_xmlrpc_server-0.0.0-SNAPSHOT.jar:\
$APP_HOME/lib/apache_xmlrpc_client-0.0.0-SNAPSHOT.jar:\
$APP_HOME/lib/com.springsource.org.apache.commons.net-2.0.0.jar:\
$APP_HOME/lib/dnsjava-2.1.1.jar:\
$APP_HOME/lib/antlr-2.7.7.jar:\
$APP_HOME/lib/asm-4.0.jar:\
$APP_HOME/lib/asm-tree-4.0.jar:\
$APP_HOME/lib/asm-commons-4.0.jar:\
$APP_HOME/lib/asm-util-4.0.jar:\
$APP_HOME/lib/asm-analysis-4.0.jar:\
$APP_HOME/lib/commons-cli-1.3-SNAPSHOT.jar

groovysh -cp $CLASSPATH

An alternative approach is to use the jar's for xercesImpl and commons-cli that gradle or maven download into your M2_REPO.

If you install the program mop, you can locate automate jar location like this:

$ mop classpath commons-cli:commons-cli:1.2

Either way, whenever you have run gradle installApp, the following session should work:

$ sh startgroovysh.sh
groovy:000> import org.ros.rosgroovy_tutorial_pubsub.Listener
groovy:000> import org.ros.node.DefaultNodeMainExecutor;
groovy:000> import org.ros.node.NodeConfiguration;
groovy:000> import org.ros.node.NodeMainExecutor;
groovy:000> l = new Listener()
groovy:000> nodeConfiguration = NodeConfiguration.newPrivate()
groovy:000> nodeMainExecutor = DefaultNodeMainExecutor.newDefault()
groovy:000> nodeMainExecutor.execute(l, nodeConfiguration)

This will spam the repl with the outputs of the listener, but you get the idea.

Wiki: rosjava_core/graveyard/rosgroovy_project_setup (last edited 2013-10-19 12:05:50 by ThibaultKruse)