\\\\ ٩( 'ω' )و ////

いろんな形がなかったりするものをこねてこねてこねまくります

LEGO Mindstorms NXTをMacでEclipseを使わずごにょる

授業で LEGO Mindstorms EV3 ではなく NXT をいじることになりました。
授業的には Mac はできるかもしれないけどサポートはしないので Windows 使っとけって感じなんですが、仮想環境使いたくないマンなので Mac でゴリ押しました。

おおまかな構成としてはGitHub - j-selby/Rescue-2016: LejOS NXT implementation of the AU Junior Rescue challenge.を元に leJOS NXJ のツール郡を Gradle を使ってごにょるだけです。

ダウンロードしなきゃいけないもの

  • Java 6
  • NXT Fantom Driver
  • leJOS NXJ
  • Gradle

Java6

LEGO Mindstorms NXT64bit Java には対応していません。なので Apple のホームページから Java6 という名の遺産をダウンロードしてください

(あなたと Java 今すぐダウンロード)
ダウンロード - Java for OS X 2017-001

インストールが完了したら、32bit に対応した Java がインストールされているか確認するためターミナルで以下のコマンドを実行してみてください。

/usr/libexec/java_home -d32

実行すると以下のような感じになると思います。

$ /usr/libexec/java_home -d32
/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

実行しても何も出ない場合はインストールできてない可能性が高いのでもう一回インストールし直すかしましょう。

NXT Fantom Driver

NXT Fantom Driver はレゴ公式からダウンロードしてインストールしてください。

leJOS NXJ

LeJOS, Java for Lego Mindstorms / NXJ Downloads

leJOS NXJ は Souce Forge を見ても Beta 版しかありませんが、問題ないので最新(2 年前)のものをダウンロードしてもらって大丈夫です。

Mac 版だと Zip で実行バイナリや Jar ライブラリ、ツール郡が固められてるので適当な場所に解凍してください。

Gradle

システム側の Gradle は公式を見て頑張ってインストールしてください。HomeBrew とか使うといいです。

Gradle | Installation

Gradle は 2 系を最後に Java6 をサポートしなくなりました。なので、Wrapper を使ってプロジェクトディレクトリに 2 系の最後のバージョンである 2.14.1 をダウンロードします。

環境の設定

NXT のバイナリやライブラリを Gradle で使うためにNXJ_HOMEを設定します

export NXJ_HOME=path/to/leJOS_NXJ

ついでに PATH も通します

export PATH="$NXJ_HOME/bin:$PATH"

これで NXJ コンパイラファームウェアアップデートをする実行ファイルが使えると思うので、ファームウェアアップデート用のコマンドをためしてみましょう。

nxjflashg

実行すると Flash leJOS firmware と書かれたボタンのある GUI が開けば OK です

Gradle の設定

Intellij IDEA で適当に Gradle のプロジェクトを作ってください。

作ったら、Gradle2.14.1 の Wrapper を作成します

gradle wrapper --gradle-version=2.14.1

実行すると gradle フォルダと gradlew というものが Moshi ので次からはこれを実行していきます。

Wrapper を作っても今のままではデフォルトの 64bit Java を使ってしまうので別で設定が必要です。

gradle.propertiesに以下の設定を追加すると gradlew 側で Java6 を使ってくれるようになります。

org.gradle.java.home=/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

つぎはbuild.gradleの設定です。

とりあえず Java6 しか使いたくないので sourceCompatibility と targetCompatibility を 1.6 にしましょう

jar も assemble も必要ないので disable しましょう

tasks.jar.enabled = false
tasks.assemble.enabled = false

使う NXJ ツール

Gradle から呼び出してコンパイルやアップロードなどを行うライブラリは$NXJ_HOME/lob/pc内にあるpctools.jarという Jar を用います。

pctools.jarには nxj ファイルを生成するNXJLinkと NXT にファイルをアップロードするNXJUploadがありますが、他にもいろいろあります。1

実際にコマンドで使うためにはbuild.gradleに task を追記しなければいけないので書いていきます。

まず、ボタンやモーターを動かすためのライブラリがある/lib/nxtとツールの jar がいっぱい入っている/lib/pcがありますが、それぞれの classpath を list にぶち込みます。

def nxjHome = System.getenv('NXJ_HOME')

def nxtClasspath = []
def nxtDir = new File(nxjHome + "/lib/nxt")
nxtDir.eachFileRecurse { file ->
    if (file.path.endsWith(".jar")) {
        nxtClasspath << file
    }
}

def pcClasspath = []
def pcDir = new File(nxjHome + "/lib/pc")
pcDir.eachFileRecurse { file ->
    if (file.path.endsWith(".jar")) {
        pcClasspath << file
    }
}

ビルドするための依存の記述はnxtClasspathをそのまま dependencies に入れればいいです。

dependencies {
    compile files(nxtClasspath)
}

link

lejos.pc.tools.NXJLinkクラスを使います。

artifactName は出力するファイル名を指定してください。

task('link', type: JavaExec, group: 'lejos',
        description: ‘javaコードからnxjバイナリを生成’,
        dependsOn: 'compileJava')
    classpath = files(pcClasspath)
    main = "lejos.pc.tools.NXJLink"

    // Build classpath
    def classpathString = ""

    nxtClasspath.each {
        if (classpathString != "") {
            classpathString += File.pathSeparator
        }
        classpathString += it.path
    }

    args += "--bootclasspath"
    args += classpathString

    args += "--classpath"
    args += sourceSets.main.output.classesDir

    args += "--writeorder"
    args += "LE"

    args += "-o"
    args += "build${File.separator}${artifactName}.nxj"

    args += "-od"
    args += "build${File.separator}${artifactName}.nxd"

    args += mainClass
}
  • --bootclasspath

      `--bootclasspath`はnxtのライブラリである`$NXJ_HOME/lib/nxt/classes.jar`が指定されます。
    
  • --classpath

      実際にビルドしたclassファイルのアウトプットされたディレクトリです。
    
  • --writeorder

      プロセッサのバイトオーダを指定するオプション。
      NXTはリトルインディアンでの設計なので`LE`を指定してください。
    
  • -o

      nxjファイルを出力するディレクトリを指定します。
    
  • -od

      リモートデバッグなどに使用するデバッグファイルを出力するディレクトリを指定します。
    

upload

NXT への nxj ファイルのアップロードはlejos.pc.tools.NXJUploadを使います。

task('upload', type: JavaExec, group: 'lejos',
        description: 'Upload the code to the robot.',
        dependsOn: 'link') {
    classpath = files(pcClasspath)
    main = "lejos.pc.tools.NXJUpload"

    // Use 32bit JVM
    jvmArgs += "-d32"

    args += "build${File.separator}${artifactName}.nxj"
}

64bit JVM を使うと 32bit の JVM を使えと怒られるので jvmArgs に 32bit JVM を使うように指定します。

アップロードと同時に実行もさせたい場合。args 変数に-rもしくは--runオプションを追加で指定するだけで可能になります。

USB のみを使用してアップロードをする場合、args 変数に-uもしくは--usbを追加してください。

同様に Bluetooth 経由でのアップロードを指定する場合は args 変数に-bもしくは--bluetoothを追加するだけです。

まとめ的なあれ

以上で設定は完了したので適当に Hello World のプログラムなり何なりを書いて以下のコマンドを実行すればビルド先のディレクトリにほげほげ.nxjというファイルが出力されているはずです。

./gradlew link

USB もしくは Bluetooth で NXT と接続している場合は./gradlew uploadもしくは./gradlew uploadAndRunとすれば NXT に.nxjふぁいるがアップロードされます。

これで快適に intellj IDEA でじゃばじゃばできますね。

以下本音垂れ流し

Java6 なんて遺産は使いたくなさすぎて嫌になるし、もう売ってない NXT じゃなくて EV3 使いたい……


  1. 気が向いたら追記します