Tag Archives: clojure

rosclj – ROS node in Clojure

Playing with robots, and learning ROS (robot operating system), I was happy to find out about rosclj, Clojure bindings for ROS.  I would be able to control robots from the REPL; how nice!

However, I quickly discovered that the only thing remaining from rosclj is its documentation: the code (originally in a SVN repo of Berkeley) has disappeared.  But never mind.  Clojure can do Java interoperop, right?  So I gave it a shot, and it turned out pretty well, so I thought I’d publish my findings because there is not much up-to-date information out there.

I started by familiarising myself with rosjava and create a pub-sub sample project following the nice tutorial here.  But don’t worry, you don’t really need to fiddle out with catkin to get Clojure talk to a ROS node.  This is actually simpler.

 

Your first ROS node in Clojure

Here are the steps:

1. Create a lein project (I called mine roscljtest), and add rosjava repository and dependencies to your project.clj.  Here is mine:

(defproject roscljtest "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [org.ros.rosjava_core/rosjava "0.2.1"]
                 [org.ros.rosjava_messages/geometry_msgs "1.11.7"]]
  :repositories [["rosjava" "https://raw.githubusercontent.com/rosjava/rosjava_mvn_repo/master"]]
  :aot :all)

2. Write a ROS node in Clojure.  I simply translated the Listener from the rosjava tutorial to clojure:

(ns roscljtest.core
  (:import [org.apache.commons.logging Log]
           [org.ros.message MessageListener]
           [org.ros.namespace GraphName]
           [org.ros.node AbstractNodeMain ConnectedNode NodeMain]
           [org.ros.node.topic Subscriber]))

(gen-class
  :name "roscljtest.core.CljListener"
  :extends org.ros.node.AbstractNodeMain
  :prefix "clist-")

(defn clist-getDefaultNodeName [this]
  (GraphName/of "rosjava/listener"))

(defn clist-onStart [this connectedNode]
  (let [log (.getLog connectedNode)]
    (doto (.newSubscriber connectedNode "chatter" std_msgs.String/_TYPE)
      (.addMessageListener
        (proxy [MessageListener] []
          (onNewMessage [msg]
            (.info log (str "I heard: \"" (.getData msg) "\""))))))))

3. Build the Clojure code, and create a uberjar, which will be useful to avoid messing up with the classpath:

> lein uberjar

If everything goes well, the following jar file should be generated, and (notice the :aot :all in our project.clj) contain all .class files: roscljtest-0.1.0-SNAPSHOT-standalone.jar

4. Start ROS core and the Talker from the Java tutorial (don’t start the Listener, since we will start the one we just wrote in Clojure)

> roscore &
> cd src/rosjava_catkin_package_a/my_pub_sub_tutorial
> cd build/install/my_pub_sub_tutorial/bin
> ./my_pub_sub_tutorial com.github.rosjava.rosjava_catkin_package_a.my_pub_sub_tutorial.Talker &

5. Finally, start the Clojure node, as follows:

> java -cp target/roscljtest-0.1.0-SNAPSHOT-standalone.jar org.ros.RosRun roscljtest.core.CljListener

Once the connection is established, you should see the following output flow, at a rate of about 1 message per second:

Oct 17, 2015 8:28:18 PM org.ros.internal.node.RosoutLogger info
INFO: I heard: "Hello world! 26"
Oct 17, 2015 8:28:19 PM org.ros.internal.node.RosoutLogger info
INFO: I heard: "Hello world! 27"

Next Steps

OK, this is great.  And the thing I like the most, is that we don’t even need our project to be “catkinized”: we can just use Leiningen as usual (provided we specify the correct repo in our project.clj).

I was actually even able to run the CljListener on a separate machine (provided I set ROS_MASTER_URI and ROS_IP correctly on both machines): I did not even have to install ROS on the machine running the CljListener!

Next step will be to make this a little more idiomatic Clojure, because extending Java classes and overriding methods is no fun.  And I want to be able to run commands from the REPL, which I haven’t tried yet.

But all in all, this looks very promising.

(best? ide-for-clojure)

Hello, Clojureverse!

Since I started learning Clojure, I tried different development environments, including Eclipse and LightTable, but today, I am back to the simplest-thing-that-could-possibly-work: VIM.

Eclipse with CCWI started with Eclipse with counterclockwise. It has syntax highlighting and a REPL and it was OK when I worked on my first Clojure project: clogo, a LOGO turtle interpreter. (I’ll surely come back on this one). It certainly does the job, but I would not really recommend Eclipse for Clojure… too heavyweight.

After installing Leinigen and using VIM for a short period of time, I stumbled onto LightTable, which is clean and nice, with a minimalistic design. It seemed promising as it includes a REPL with real-time evaluation of the Clojure code you type. But I found it not very practical, because unlike an autocompletion feature, I like my REPL to wait until I’m done typing. So I ended up copying and pasting code from LT to my REPL, which I thought was probably not the best way. (The other thing that I didn’t like about LT is that the screen could only be split vertically; maybe it’s improved today).

In quest of a more integrated environment, I went back to VIM and tried the NailGun server for REPL integration. It is OK, and although the execution of Clojure code in a separate window seemed a good idea, it looks like NG is sometimes getting lost when I inadvertently close it’s buffer. That’s really a pain.

MacVim and vim-fireplaceAt this point, I found vim-fireplace (earlier called foreplay.vim) which is simple and really nice. It will find your REPL and automatically connect to it, and it can not only execute a block of code in a single keystroke, but also run your tests, or let you see the documentation for any function.

So to summarise: my environment today is Leiningen, and MacVim with vim-fireplace (+ vim-clojure-static and rainbow_parentheses.vim plugins). I am using clojure.test for testing, and cloverage to measure my test coverage. And I use criterium library together with VisualVM when I have to look at performance.

Voilà. Enough talking. Let’s start coding…