KotlinでROSのノードを書く


KotlinでROSを書いてみたくなったので頑張ってみた
ROSもkotlinもgradleもよくわからないので間違っている可能性もあるので、分かる方指摘ください。

[github](https://github.com/iwata-n/roskotlin)

## 手順

1. RosJavaを入れる
2. RosJavaでプロジェクトを作る
3. build.gradleにkotlin関係のコードを追記する
4. kotlinでコードを書く
5. ビルド

手順2までは [前の記事](http://qiita.com/iwata-n@github/items/989bed3acc21ffb28521) を参考に

## build.gradleのkotlin関係のコードを追記する

[kotlinのgithub](https://github.com/JetBrains/kotlin-examples/blob/master/gradle/hello-world/build.gradle)を参考に以下の様にプロジェクトのbuild.gradleを書き換える。気をつけないといけないのが、gradlewと同じディレクトリにもbuild.gradleがあること。そっちはいじらない。

``` roskotlin/src/iwatan/sample/build.gradle
/* This plugin is necessary for creating installApp tasks (i.e. executables) */
apply plugin: 'application'
mainClassName = 'org.ros.RosRun'

/* 
 Dependencies can be on external maven artifacts (such as rosjava_core
 here) or on sibling subprojects. Fpr external maven artifact dependencies
 it's convenient to use an open ranged dependency, but restrict it to
 cover the patch version only to avoid breakages due to api changes
 which usually occur on minor and major version numbers.
*/

dependencies {
  /* An external maven artifact dependency */
  compile 'org.ros.rosjava_core:rosjava:[0.2,0.3)'
  /* Example of a local subproject dependency */ 
  /* compile project(':sibling_gradle_project') */
}

/* ここから追記 */
buildscript {
    repositories {
        mavenCentral()
        maven {
            url 'http://oss.sonatype.org/content/repositories/snapshots'
        }
    }
    dependencies {
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT'
    }
}

apply plugin: "kotlin"

sourceSets {
    deploy
}

repositories {
    mavenCentral()
    maven {
        url 'http://oss.sonatype.org/content/repositories/snapshots'
    }
}

dependencies {
    compile 'com.google.guava:guava:12.0'
    compile 'org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT'
    deployCompile 'com.google.guava:guava:12.0'
    testCompile  'org.testng:testng:6.8'
}

test.testClassesDir = project.tasks.compileTestKotlin.destinationDir
```

## kotlinでコードを書く

IntelliJのKotlinプラグインを使ってrosjavaのサンプルコードをコンバートしてみたら、そのままでは動かなかった。
overrideが大文字始まりになったり、コンストラクタが無いと言われたり、型推論が出来ないと怒られた。
色々試行錯誤してみた結果以下のコードで動いた

```roskotlin/src/iwatan/sample/src/main/kotlin/main.kt
package iwatan.kotlin.sample

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

public class Listener() : AbstractNodeMain() {

    override
    public fun getDefaultNodeName(): GraphName {
        return GraphName.of("roskotlin/listener")
    }

    override
    public fun onStart(connectedNode: ConnectedNode) {
        val log = connectedNode.getLog()
        val subscriber = connectedNode.newSubscriber<std_msgs.String>("chatter", std_msgs.String._TYPE)
        subscriber.addMessageListener { message ->
            log.info("Kotlin heard: \"" + message.getData() + "\"")
        }
    }
}
```

javaよりもsubscriber.addMessageListenerの部分が関数リテラルでもうチョット簡単にかけるかと思ったらなんか上手くいかなかったので、この形に落ち着いた。なんでかよく分からん。

## ビルド

rosjavaと同じく、gradlewを使ってビルドする


```bash
./gradlew installApp
```

そうすると、メッセージが出てくる。多分初めは依存関係の解決で時間がかかると思う。

```
:sample:compileKotlin
:sample:compileJava UP-TO-DATE
:sample:processResources UP-TO-DATE
:sample:classes UP-TO-DATE
:sample:jar
:sample:startScripts
:sample:installApp

BUILD SUCCESSFUL

Total time: 11.639 secs
```

こんな感じでcompileKotlinが出て来てる！

## 実行

実行はrosjavaと同じく、src/build/install/binにバイナリがあるので、以下で実行する。

```
cd src/iwatan/sample/build/install/sample/bin
./sample iwatan.kotlin.sample.Listener
```

別のコンソールでrosjavaのサンプルのTalkerを起動しておくと、以下の感じにトピックが購読されてるのが見れる

![スクリーンショット 2015-08-09 20.34.12.png](https://qiita-image-store.s3.amazonaws.com/0/16612/fa688930-de3b-3485-20f4-2e5ea977c927.png "スクリーンショット 2015-08-09 20.34.12.png")