-*- coding: utf-8 -*- 2012-0525 ODEに本格参入を決定 すでにMy PCにCygwin、ODEをインストール Ubuntu にもインストール Let's note CF-B10 にもインストールを試みる cygwin + codeblocks  出村氏のサイトから Codeblocks 10.05をダウンロードし、インストールする いきなりミス mingw つきのをダウンロード、インストールすべきだった ODEをダウンロード ode-0.12を選択 展開してcドライブに置く。build フォルダに移り premake4 (codeblocks指定)で作成 ODEのビルド codeblocksを起動、c;\ode-0.12のbuildの下にある ode.workspaceを開いて workspaceをビルド -> 成功 RoboSimuのビルド ode-0.12の下に置く 展開したフォルダの名前をroboSimuに変更する。そして premake、codeblocksでビルド 清水先生のシステム make を使っている --- cygwin  INSTALL.txtにしたがい、sh autogen.sh; configure --enable-double-precision だとmakeで失敗する。 そこで http://d.hatena.ne.jp/maski/20111014/1318612107 の記述に従う。 begin quote-------------------------------------------------- cd ~/src/ode-0.11.1 sh ./autogen.sh ここで、./configureを編集します。 テキストエディタを使用し、DEFS=を検索します。 DEFS=-DHAVE_CONFIG_H これを DEFS="-DHAVE_CONFIG_H -D_WIN32 -DUSE_OPENGL32" に書き換えて保存します。 あとは ./configure --enable-double-precision make make install end quote-------------------------------------------------- これでMyPCはうまくいった。。。はず。しかし、BF10ではmakeでエラーになる (OPENGLのライブラリの関係のように見えるが、cygcheckではOK) 諦めて、 http://yak3.myhome.cx:8080/junks/ にあるcygwin版ODEをインストール(ダウンロードして展開するだけ) 動いた。 (/home/sirai/のcygwin-*bz2がそれ) ただし、清水先生のシステムは動かない(resources.oが/usr/local/libにない、という) これもMyPCで通ってきた道。 結局、makefileを編集。RESOURCE_FILE: /usr/local/lib/resources.o で対処 (resources.oはODEのdrawstuffで作られている) makeはできたが、/usr/local/lib/dstexturesがないというメッセージ これもODEからもってくる。drawstuffのtexturesをコピー 終了 ------------------------------------------------------------ こんなページを発見 http://www.crystal-creation.com/robot/technical-information/physics-engine/ode/error/message.htm 発展: socket通信により、ODEのロボットをコントロールする 疑問: RangeSensorは何を返す? ============================================================ socket通信による表示 show.pde try { C = S.available(); if (C != nul) { input = C.readString(); if (input.length() <= 3) ... } else { // 正常読み込み lines = split(input,"\n"); for (i=0; i try - catch で対応 2. 同じメッセージを何回も読む --> finally { return; } を書いて解決  3. 「角度と距離」データを受け取る --> "角度: 距離\n"という文字列を受け取り(line)、split(":")で分ける 受け取るのは実際にはこの文字列の塊なので、その前にsplit("\n")で切り分ける 4. メッセージの中に"B"という文字が入り込む --> substring(2)を使って、先頭にある"B"を読み飛ばす 0. Processingの言葉を知るには、ホームページのreferenceが一番! -------------------------------------------------- collabo-test12.cpp ソケット通信するために struct sockaddr_in S_IN; #define PortNO 50590 int Sockfd; static void socketInit() { /* ソケットを生成する */ if ((Sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("client: socket"); exit(1); } /* サーバの情報を与える */ S_IN.sin_family = AF_INET; S_IN.sin_port = htons(PortNo); S_IN.sin_addr.s_addr = inet_addr("127.0.0.1"); /* サーバに接続する (クライアント) */ if ((connect(Sockfd, (struct sockaddr *)&S_IN, sizeof(S_IN))) < 0) { perror("client: connect"); } } を用意。実際にメッセージを送るのは次の関数: static void reportStatus(OmniRobot& OR, ODE_ENVIRONMENTS& OE) { int i; char buf[18]; for (i=0; i< 360; i+=15) { sprintf(buf,"%4d:%10.3f\n",i,Check_RangeSensor(OE, OR.Sensor, i)); send(Sockfd,buf,18,0); // MSG_OOB works bad printf("%s", buf); } } この時点では15度ごとの情報を、"角度: 距離\n"という形式で送る *sendの第4パラメタに何を書くか迷った---0と書けば良い(ためしたのはMSG_OOB) send(Sockfd,buf,strlen(buf)+1,0) の方がすっきりしている ====================================================================== 2012-0622 清水先生宛のメール 以下のようなRayを使ったバージョンのレンジセンサーを作りました。これは Check_RangeSensor と互換です。 傾き(Rayの方向の計算)の考慮は Check_RangeSensor に完全に依存しています (この吟味、検討はしておりません)。 もう少し Check_RangeSensorおよび Check_DistanceSensro_Subの動きを検討してみたところ、 こちらのほうが無駄な計算が少ないということがわかりました (Check_DistanceSensor_Subでは二分探索のために再帰を使っています。 その呼び出しごとに全部のオブジェクトに対する衝突判定を行っています。 それに対して以下は、全部のオブジェクトをサーチしますが1回で済ませています) なお、前に書いたと思いますが、Robotの構造体のメンバー変数を増やし、 メンバー変数としてセンサーを取るようにし、MakeRangeSensorはそこに作ったセンサーを セットするように直すと、 すべてのオブジェクトを探索せずに済むようにProcess_RangeSensor を書き直せる ので効率性があがります。 ご参考までに。 白井 /* range sensor test */ static double MeasureDistance(ODE_ENVIRONMENTS& OE, GC_OBJ_PARAM p, int r) { const dReal maxLen = 5.0; const dReal *R1, *pos1; dReal p1[3], minDist; minDist = maxLen; dContactGeom contact; dGeomID ray = dCreateRay (0, maxLen ); /* 5m length */ pos1 = dBodyGetPosition(p.body); R1 = dBodyGetRotation(p.body); //始点設定 p1[0]=pos1[0]+(R1[1]*(p.rad)*cos(M_PI*r/180))-(R1[0]*(p.rad)*sin(M_PI*r/180)); p1[1]=pos1[1]+(R1[5]*(p.rad)*cos(M_PI*r/180))-(R1[4]*(p.rad)*sin(M_PI*r/180)); p1[2]=pos1[2]+(R1[9]*(p.rad)*cos(M_PI*r/180))-(R1[8]*(p.rad)*sin(M_PI*r/180)); dGeomRaySet (ray,p1[0],p1[1],p1[2], R1[1]*cos(M_PI*r/180)-R1[0]*sin(M_PI*r/180), R1[5]*cos(M_PI*r/180)-R1[4]*sin(M_PI*r/180), R1[9]*cos(M_PI*r/180)-R1[8]*sin(M_PI*r/180)); for(int i=0;i contact.depth) minDist=contact.depth; } } if (dCollide (ray,OE.Ground,1,&contact,sizeof(dContactGeom)) != 0) { if (minDist > contact.depth) minDist=contact.depth; } return minDist; /* dCollide If the geoms intersect, this function returns the number of contact points generated (and updates the contact array), otherwise it returns 0 (and the contact array is not touched). */ } -------------------------------------------------- 2012-0626 BumperSensorの作成、RangeSensorの変更 //(CheckRangeSensor)-------------------------------------------- ///レンジセンサ計測 //--------------------------------------------------------------------------------------- static double CheckRangeSensor_Sub(ODE_ENVIRONMENTS& OE, GC_OBJ_PARAM p, int r, dReal maxLen) { const dReal *R1, *pos1; dReal p1[3], minDist; minDist = maxLen; dContactGeom contact; dGeomID ray = dCreateRay (0, maxLen ); /* 5m length */ pos1 = dBodyGetPosition(p.body); R1 = dBodyGetRotation(p.body); //始点設定 p1[0]=pos1[0]+(R1[1]*(p.rad)*cos(M_PI*r/180))-(R1[0]*(p.rad)*sin(M_PI*r/180)); p1[1]=pos1[1]+(R1[5]*(p.rad)*cos(M_PI*r/180))-(R1[4]*(p.rad)*sin(M_PI*r/180)); p1[2]=pos1[2]+(R1[9]*(p.rad)*cos(M_PI*r/180))-(R1[8]*(p.rad)*sin(M_PI*r/180)); dGeomRaySet (ray,p1[0],p1[1],p1[2], R1[1]*cos(M_PI*r/180)-R1[0]*sin(M_PI*r/180), R1[5]*cos(M_PI*r/180)-R1[4]*sin(M_PI*r/180), R1[9]*cos(M_PI*r/180)-R1[8]*sin(M_PI*r/180)); for(int i=0;i contact.depth) minDist=contact.depth; } } if (dCollide (ray,OE.Ground,1,&contact,sizeof(dContactGeom)) != 0) { if (minDist > contact.depth) minDist=contact.depth; } return minDist; } static double CheckRangeSensor(ODE_ENVIRONMENTS& OE, GC_OBJ_PARAM p, int r) { return CheckRangeSensor_Sub(OE, p,r,5.0); } static bool ShortRangeSensor(ODE_ENVIRONMENTS& OE, GC_OBJ_PARAM p, int r) { dReal maxLen = 0.470; // check objects within 0.50m from the robot const dReal *R1, *pos1; dReal p1[3], minDist; minDist = maxLen; dContactGeom contact; dGeomID ray = dCreateRay (0, maxLen ); /* 5m length */ pos1 = dBodyGetPosition(p.body); R1 = dBodyGetRotation(p.body); //始点設定 p1[0]=pos1[0]+(R1[1]*(p.rad)*cos(M_PI*r/180))-(R1[0]*(p.rad)*sin(M_PI*r/180)); p1[1]=pos1[1]+(R1[5]*(p.rad)*cos(M_PI*r/180))-(R1[4]*(p.rad)*sin(M_PI*r/180)); p1[2]=pos1[2]+(R1[9]*(p.rad)*cos(M_PI*r/180))-(R1[8]*(p.rad)*sin(M_PI*r/180)); dGeomRaySet (ray,p1[0],p1[1],p1[2], R1[1]*cos(M_PI*r/180)-R1[0]*sin(M_PI*r/180), R1[5]*cos(M_PI*r/180)-R1[4]*sin(M_PI*r/180), R1[9]*cos(M_PI*r/180)-R1[8]*sin(M_PI*r/180)); for(int i=0;i project.config["DebugLib"].libdir = "/usr/local/lib" 2) roboSimu.lua の修正 64,65c64,65 < package.config.DebugDLL.links = {"oded", "drawstuffd"} < package.config.DebugLib.links = {"oded", "drawstuffd"} --- > package.config.DebugDLL.links = {"ode", "drawstuff"} > package.config.DebugLib.links = {"ode", "drawstuff"} 71c71 < package.links = { "oded", "drawstuffd" } --- > package.links = { "ode", "drawstuff" } ------------------------------------------------------------ この修正後、 ./premake.exe --target gnu cd src make すると、roboSimu/DebugLib の下にサンプルプログラムができる (amotor.exe, arm1.exe など) ====================================================================== 2013-0125 現時点のcygwin (cygcheck 1.7.11)では libopengl32も libglu32もないようである。 そのため、drawstuff のmakeで失敗する。 その対処方法:drawstuff および drawstuff/dstest の Makefile において、 GL_LIBS = -lglu32 -lopengl32 となっているところを GL_LIBS = -lGL -lGLU に書き換える (そしてmakeする) ------------------------------------------------------------ 2013-0226 resources.o の必要性 drawstuffのaccelerator として使われている。 これを削除すると、accelerator not found というエラーになるので注意