人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

ODEをMacにインストール

Mac OS X Mountain Lion に物理シミュレーションエンジンの Open Dynamics Engine (ODE) を入れようとしてすごく苦労したのでまとめておきます。macportsにもodeはありますが、これだとdrawstuffというライブラリが入っていなかったのでソースコードからコンパイルしています。

コンパイルに使ったg++は、macportsではなく、Xcode4.4のものです。Xcode4.4のコマンドラインツールのインストールは、こちらを参考にしてください。

> which g++
/usr/bin/g++
> ls -l /usr/bin/g++
lrwxr-xr-x  1 root  wheel  12  7 28 21:19 /usr/bin/g++@ -> llvm-g++-4.2

Open Dynamics Engine のサイトから ode-0.12.tar.bz2 をダウンロードし、倍精度でコンパイルしました。

tar xvzf ode-0.12.tar.bz2
cd ode-0.12
./configure --enable-double-precision
make
sudo make install

ここまでで、/usr/local/lib/usr/local/includeにODEがインストールされますが、実はこれだけではダメでデフォルトだとなぜかdrawstuffがインストールされなかったです。なので、drawstuffのライブラリファイルとヘッダファイルを手動でコピーします。

sudo cp drawstuff/src/.libs/libdrawstuff.* /usr/local/lib/
sudo mkdir /usr/local/include/drawstuff
sudo cp include/drawstuff/*.h /usr/local/include/drawstuff/

また、デフォルトのテクスチャファイルはあとで使うので作業ディレクトリにコピーしておくとよいです。

cp -R drawstuff/textures ~/work

最後にODEチュートリアルソースコードをコンパイルして動作確認。fn.path_to_texturesのtexturesは先ほどテクスチャをコピーした場所を設定します。

/* sample.cpp */
#include <ode/ode.h>
#include <drawstuff/drawstuff.h>

#ifdef dDOUBLE
#define dsDrawSphere dsDrawSphereD
#endif

static dWorldID world;
dBodyID ball;
const dReal radius = 0.2, mass = 1.0;

static void simLoop(int pause) {
    const dReal *pos, *R;
    dWorldStep(world, 0.05);
    dsSetColor(1.0, 0.0, 0.0);
    pos = dBodyGetPosition(ball);
    R = dBodyGetRotation(ball);
    dsDrawSphere(pos, R, radius);
}

void start() {
    static float xyz[3] = {0.0, -3.0, 1.0};
    static float hpr[3] = {90.0, 0.0, 0.0};
    dsSetViewpoint(xyz, hpr);
}

int main(int argc, char **argv) {
    dReal x0 = 0.0, y0 = 0.0, z0 = 1.0;
    dMass m1;

    dsFunctions fn;
    fn.version = DS_VERSION;
    fn.start = &start;
    fn.step = &simLoop;
    fn.command = NULL;
    fn.stop = NULL;
    fn.path_to_textures = "./textures";

    dInitODE();
    world = dWorldCreate();
    dWorldSetGravity(world, 0, 0, -0.01);

    ball = dBodyCreate(world);
    dMassSetZero(&m1);
    dMassSetSphereTotal(&m1, mass, radius);
    dBodySetMass(ball, &m1);
    dBodySetPosition(ball, x0, y0, z0);

    dsSimulationLoop(argc, argv, 352, 288, &fn);

    dWorldDestroy(world);
    dCloseODE();

    return 0;
}

で、最後にコンパイルですが、ここではまりにはまった。まず、

g++ sample.cpp -lode -ldrawstuff -DdDOUBLE

とやってみた。libodeとlibdrawstuffは、標準の/usr/local/libにあるので-Lでパスを指定する必要はないはず。それなのに、下のようなよくわからないコンパイルエラー。

Undefined symbols for architecture x86_64:
  "_glBegin", referenced from:
      drawConvexD(double*, unsigned int, double*, unsigned int, unsigned int*)in libdrawstuff.a(drawstuff.o)
      drawCapsule(float, float)in libdrawstuff.a(drawstuff.o)
      drawCylinder(float, float, float)in libdrawstuff.a(drawstuff.o)
      drawConvex(float*, unsigned int, float*, unsigned int, unsigned int*)in libdrawstuff.a(drawstuff.o)
      drawBox(float const*)in libdrawstuff.a(drawstuff.o)
      _dsDrawTriangleD in libdrawstuff.a(drawstuff.o)
      _dsDrawLine in libdrawstuff.a(drawstuff.o)
      ...
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

このエラーは Mac OS X Lion 以降頻発するらしくWeb上にいろいろ情報があったのですが、なかなか解決しなかった・・・

で、数時間格闘したあと、最終的に下のように-frameworkでGLUTOpenGLを指定することでコンパイルできることが判明。ここのサイトが決め手になりました。64bitとか関係あったの???

g++ sample.cpp -lode -ldrawstuff -DdDOUBLE -framework GLUT -framework OpenGL

もしくは、ODEのコマンドode-configを使って下のようにも書けます。

g++ sample.cpp `ode-config --cflags --libs` -ldrawstuff -framework GLUT -framework OpenGL

ode-configは、ライブラリ、ヘッダファイルのパスとインストールしたときの精度を返してくれるようです。

> ode-config --cflags --libs
-I/usr/local/include -DdDOUBLE
-L/usr/local/lib -lode

よーし、これで動作確認もできたし、本格的に物理シミュで遊ぶぞ!

f:id:aidiary:20120807094656p:plain