Monthly Archives: October 2015

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.

PyCon JP 2015

I had the pleasure to attend PyCon JP 2015, held in Heisei Plaza in Tokyo on October 9-10, featuring the “Possibilities of Python”.  Although I am not really into Python (busy with Clojure & robots!), I thought is would be a good way to meet programming enthusiasts in Tokyo.  And it was.

My first impression about the Python community is its diversity.  Beyond gender diversity, I felt Pythonistas (seems to be how to call someone who writes Python) were coming from so many different areas: I met people in the devops world (of course), but also researchers, roboticists, data scientists, linguists, game developers, startup owners, photographers and hackers of all sorts.  Great community!

Now let me pick up a few talks/sessions which resonated with me.

My first (and favourite) talk is by Hideyuki Takei (@HideyukiTakei) on how to make a 4-leg robot learn to move on its own using reinforcement learning in Python.  His idea is simple, but really great: let the robot “try out” different possible actuator settings, and based on a reward (basically, the total travelled distance), learn the “good” patterns (i.e. the ones that will make the robot move forward).  I thought this was wonderful.  He is using Gazebo robot simulator for learning (to avoid making his robot actually move so many times), and showed off his robot walking.  It was impressive to see a real motion pattern emerge after only 400 iterations!

My next pick is actually a poster session by Ugo-Nama (@movingsloth) who presented his attempt to create a toad robot, particularly focusing on modelling of the perception of the world by the toad.  He is using (again) Q-learning and CNN (convolutional neural networks) to analyse the visual input of the toad and deduce whether the toad sees a “prey” or a “predator”.  This information can then be transformed them into actionable goals, such as “jump”, “run”, etc.  His work is based on the research of J.P. Ewert who studied neurophysiological foundations of behavior.

Make a Toad

I also liked the talk of Tomoko Uchida (@moco_beta) on natural language processing, and in particular Morphological Analysis using Python.  This was appealing to me, because the problem of lexical parsing turns out to be more difficult in Japanese than in Western languages for example, where the separation between words is clear.  She explained how she built janome, a morphological analysis library written in Python.  I tried it out, and yes, it parses the following sentence correctly!

>>> from janome.tokenizer import Tokenizer
>>> t = Tokenizer()
>>> for token in t.tokenize(u'すもももももももものうち'):
...     print(token)
...
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
>>> ^D

I also attended many other talks / poster sessions, including “How to participate to programming contests and become a strong programmer” by Chica Matsueda, “Building a Scalable Python gRPC Service using Kubernetes” by Ian Lewis, “Finding related phrases on large amount of tweets in real time using Tornado/Elasticsearch” by Satoru Kadowaki, “Python and the Semantic Web: Building a Linked Data Fragment Server with Asynco and Redis” by Jeremy Nelson, “Let it crash: what Python can learn from Erlang” by Benoit Chesneau, a panel session on diversity, “How to develop an FPGA system easily using PyCoRAM” by Shinya Takamaeda, “Sekai no Kao” (the Face of the World) by Hideki Tanaka et al., and “Rise of the Static Generator” by Justin Mayer.

Lots of great content, but especially great people.  Many thanks to the organisers for such a great conference.  I’m hoping to attend PyCon 2016… and maybe submit a talk?