KotlinでROSを書いてみたくなったので頑張ってみた
ROSもkotlinもgradleもよくわからないので間違っている可能性もあるので、分かる方指摘ください。
手順
- RosJavaを入れる
- RosJavaでプロジェクトを作る
- build.gradleにkotlin関係のコードを追記する
- kotlinでコードを書く
- ビルド
手順2までは 前の記事 を参考に
build.gradleのkotlin関係のコードを追記する
kotlinのgithubを参考に以下の様にプロジェクトのbuild.gradleを書き換える。気をつけないといけないのが、gradlewと同じディレクトリにも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が大文字始まりになったり、コンストラクタが無いと言われたり、型推論が出来ないと怒られた。
色々試行錯誤してみた結果以下のコードで動いた
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を使ってビルドする
./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を起動しておくと、以下の感じにトピックが購読されてるのが見れる