まず,ここにあるODEのFAQを読んでからコメントお願いします.
ODE質問・要望募集10!のコメントが100件を超えましたので,新規のご質問やご要望はこちらにお願いします! ご質問の内容を詳しく説明して頂けると的確に回答できますので,時間を節約できると思います.
また、私のコメントやご自分の努力により問題が解決された場合に、問題の原因がわかれば投稿して頂くと大変助かります。その情報はODEの初心者にとって重要なものです。ある程度たまりましたらFAQに掲 載したいと思いますのでご協力のほどよろしくお願いします。
でむ
コメント
はじめまして。ODE初級講座3のこんにちは物理世界のプログラムを自分でプロジェクトを作成し同じプログラムを作成しコンパイルを行ったら、error LNK2019: 未解決の外部シンボル _dWorldDestroy が関数 _main で参照されました。というようなエラーが何個も出たのですが原因がわかりません。ただダウンロードしたsample3は正常に動きました。どちらのプロジェクトもodeのインクルードファイルなどは読み込ませてると思います。一体何がまずかったのでしょうか?アドバイスをお願いします。
自己解決できました。原因はプロジェクトのプロパティの構成プロパティのリンカーの追加の依存ファイルの設定をode_doubled.lib;drawstuffd.lib;opengl32.lib;glu32.lib;winmm.lib;%(AdditionalDependencies)としていなかった事と、fn.path_to_texturesで渡すディレクトリの設定がサンプルプログラムの設定のままではディレクトリが1つずれてしまうことでした。。
私のvisual c++2010EEの環境ではサンプルプログラムと比べ、ディレクトリが1つだけ多く作成されてしまうため、”../../../drawstuff/textures”とする必要があったようです。これらの事は、私が初級講座で見た限り見つけられなかったので、もし本当にこれらの記載がないなら、補足した方が、私のようにつまずく人が減ると思います。ちなみに私は、visual C++2010EEとode-0.11.1の組み合わせでやりました。
xenoneさん、
コメントありがとうございます。返事が遅くなりすみません。
サンプルプログラムは相対パスでdrawstuffのテクスチャパスを見ているので、c:\ode-0.12\myprogの下で解凍する必要があります(myprogというフォルダ名に必要はありません)。また、ライブラリ名もode-0.11.1とode-0.12では変更がありました。
初級講座に明記していなかったので追記します。
今後とも不備な点があればご指摘頂ければ大変助かります。どうもありがとうございました。
でむ
こんばんわ
剛体とジョイントによって直立不動の仮人体モデルを作成しました。
この作成したモデルにトルクを与えてシミュレーションを考えています。
たとえば、直立不動のモデルではなく投球の構えのフォームを初期フォームとしてシミュレーションを行いたいのですが、ボディの角度をステップごとに変化させたり、移動したりすることはできるのでしょうか?
Kinematic Stateによって直立不動の構えから投球フォームにそれぞれボディを移動させていこうと考えていたのですが、なかなかうまくいきませんでした。
またステップを0~100までなどの指定する方法などはあるのでしょうか?
よろしくお願いします。
markさん,
コメントありがとうございます.
ボディの角度をステップごとに変化させるにはamotorを使えば可能です.amotor(angular motor)は理想的なモータで次のステップで必ず指定した角速度になります.角度を指定するためには何らかの制御が必要になります.amotorの使い方は拙著のロボットシミュレーションの91ページをご覧ください.
また,ステップを指定するためにはsimloop内でステップ数を数え,その回数に応じて処理を変更すれば良いと思います.
ご参考になれば幸いです.
でむ
こんにちわ.
前回の関節の角度の問題は,引数がおかしかったようです.
問題は無事に解決されました.
そして,また質問をさせていただきます.
縦0.1×横0.1×高さ0.31の直方体(ボーンののうなイメージの物)をユニバーサルジョイントで,地面と接触している箱型のオブジェクトと接続しました.
base.body = dBodyCreate(world);
dMassSetZero(&mass);
dMassSetBoxTotal(&mass,BASE_M,BASE_S[0],BASE_S[1],BASE_S[2]);
dBodySetMass(base.body,&mass);
base.geom = dCreateBox(space,BASE_S[0],BASE_S[1],BASE_S[2]);
dGeomSetBody(base.geom,base.body);
dBodySetPosition(base.body,START_X,START_Y,BASE_S[2]*0.5);
born[b].body = dBodyCreate(world);
dMassSetZero(&mass);
dMassSetBoxTotal(&mass,main_born_mass,main_born_X,main_born_Y,main_born_Z);
dBodySetMass(born[b].body,&mass);
born[b].geom = dCreateBox(space,main_born_X,main_born_Y,main_born_Z);
dGeomSetBody(born[b].geom,born[b].body);
dBodySetPosition(born[b].body,START_X,START_Y,BASE_S[2]+*0.5);
で両物体の定義と生成をしています.
born_joint[j] = dJointCreateUniversal (world,0);
dJointAttach (born_joint[j],base.body,born[0].body);
dJointSetUniversalAnchor (born_joint[j],0,0,buggy_tall_Z);
dJointSetUniversalAxis1 (born_joint[j],1,0,0);
dJointSetUniversalAxis2 (born_joint[j],0,1,0);
dJointSetUniversalParam (born_joint[j],dParamLoStop,-0.3);
dJointSetUniversalParam (born_joint[j],dParamHiStop,0.3);
dJointSetUniversalParam (born_joint[j],dParamLoStop2,-0.3);
dJointSetUniversalParam (born_joint[j],dParamHiStop2,0.3);
でユニバーサルジョイントで接続しています.
この接続の仕方で,ボーンが倒れてしまいます.
ユニバーサルジョイントの限界角度設定を0にする以外で,ボーンを倒れなくする方法はありますか?
よろしくお願いします.
KidAmさん
解決おめでとうございます.
差支えなければ,引数がどうおかしいか教えていただけないでしょうか?
多くの方の参考になると思います.
でむ
返事が遅くなりました.
API表の説明をちゃんと読んでなかった事が問題でしたが,radで引数を与えていなかったことが原因ですね.
「設定したい角度」/(180*3.14)
を引数に与えたら上手くいきました.
ボーンが倒れてしまう現象については何か解答は頂けないでしょうか?
ボーン(直方体)を倒れなくするためには,倒れないように制御すればよいのではないですか?
そもそも,倒れる理由も良くわかりません.標準の姿勢の場合は外力が働かなければ倒れないと思います.ジョイントを無効にして試して頂けますか?
でむ
こんばんわ.
前回の質問から,自力でモデルロボットを組むことができるようになりました.
組めるようになったと言っても,関節が脆く,上に乗ってるパーツの重みや,重心のズレなどですぐに崩れてしまいます.
どのようにすれば,このような事態はなくなりますか?
あと,シミュレーションが描画されるときにに,物体同士が離れて描画されたり,めり込んで表示されたりします.
なにか原因がわかりますか?
KidAmさん,
自力でロボットモデルを組むことができるようになったとのことおめでとうございます.
さて,関節がずれる理由はERPの値が小さいことが予想されます.ERPの値を0.8や0.9のように大きな値に設定してください.また,CFMの値は10E-10などと小さくしてください.
その他の原因は,リンクと関節の位置関係が間違っていることなどが考えられます.ERPやCFMの値を自分で変えていない場合は,後者の理由の可能性が高いと思います.
また,物体同士が離れたり,めりこんだりするのは,リンクと関節の位置や姿勢の設定が悪いからだと思います.
でむ
返信ありがとうございます.
自分ではその辺の設定は全くいじっていないので,demu先生のおっしゃる通り関節の位置関係が間違っている可能性が高いです.
あと,物体と関節の位置関係ですが,
//main born
dReal main_born_X=0.01;
dReal main_born_Y=0.01;
dReal main_born_Z=0.31;
dReal main_born_mass=1.6171;
dReal main_born[3]={0.01,0.01,0.31};
//shoulder born //y軸移動時
dReal shoulder_born_X = 0.26;
dReal shoulder_born_Y = 0.01;
dReal shoulder_born_Z = 0.01;
dReal shoulder_born[3]={0.26,0.01,0.01};
dReal shoulder_born_mass=0.3;
で,物体のサイズを先に決めて,
//0 main-born
born[b].body = dBodyCreate(world);
dMassSetZero(&mass);
dMassSetBoxTotal(&mass,main_born_mass,main_born_X,main_born_Y,main_born_Z);
dBodySetMass(born[b].body,&mass);
born[b].geom = dCreateBox(space,main_born_X,main_born_Y,main_born_Z);
dGeomSetBody(born[b].geom,born[b].body);
dBodySetPosition(born[b].body,START_X,START_Y,buggy_tall_Z);
b++;//1 shoulder born
born[b].body = dBodyCreate(world);
dMassSetZero(&mass);
dMassSetBoxTotal(&mass,shoulder_born_mass,shoulder_born_X,shoulder_born_Y,shoulder_born_Z);
dBodySetMass(born[b].body,&mass);
born[b].geom = dCreateBox(space,shoulder_born_X,shoulder_born_Y,shoulder_born_Z);
dGeomSetBody(born[b].geom,born[b].body);
dBodySetPosition(born[b].body,START_X,START_Y,buggy_tall_Z+main_born_Z-0.13);
で,ジオメトリと物体を定義してます.
その後に,
//main_born & shoulder_born
born_joint[j] = dJointCreateFixed (world,0);
dJointAttach (born_joint[j],born[0].body,born[1].body);
dJointSetFixed (born_joint[j]);
と,2つの物体の間の関節を定義しています.
位置関係としましては,物体と物体が衝突している中で関節を定義している感じです.
この定義の仕方で,描画されるロボットの関節が離れて描画されます.
このやり方で問題が発生しているので,どうか力をお貸しください.
よろしくお願いします.
連投になって申し訳ございません.
dBodySetPositionでの物体の定義する座標を誤認していたようで,「dBodySetPositionのx,y,zを中心に,dSetBoxなどで定義した物体の大きさ分の大きさを領域に作り出す」と,いう事がわかりました.(説明が分かりにくかったらごめんなさい)
なので,関節が外れて描画されるという問題に関しては解決できました.
ですが,関節の角度を設定したのに,その角度以上に関節が曲がってしまうという事態に陥ってしまいました.
ユニバーサルジョイントを使っています.
ERPもCFMの値も
void dWorldSetERP ( dWorldID, dReal erp );
void dWorldSetCFM ( dWorldID, dReal cfm );
で,先ほど教えていただいた値をセットしました.
何が原因なんでしょうか?
「関節の角度を設定したのに,その角度以上に関節が曲がってしまう」という意味が良くわかりません.
関節可動域の上限下限を設定したのに,制御をするとそれ以上に曲がるということでしょうか?
関節の初期角度はリンクの初期位置に依存するので,リンクの初期位置が正しければ,
ユニバーサルジョイントの回転中心,回転軸ベクトルの設定を疑ってみる必要があります.
dJointSetUniversalAnchor();
dJointSetUniversalAxis1();
dJointSetUniversalAxis2();
でむ
はじめまして,KidAmと申します.
卒研で,「ロボットの上半身を使ってバランス制御をする」と,いう研究をしています.
ODEを使って,ロボットの上半身モデルを生成したいのですが,Bad argument (s)というエラーに悩まされています.
Bad argument (s)と書かれたウィンドウが出てくるのですが,ここの過去ログの質問のようにどこがおかしいかは出てきません.
Bad argument (s)としか書かれていないウィンドウが出るだけです.
VC++2010を使っており,ビルドは問題なくできるのですが,デバッグをすると,上記のウィンドウが出てきます.
もし,よろしければ力を貸してください.
よろしくお願いします.
KidAmさん,
はじめまして.
Bad ArgumentsはODE APIに渡す引数が悪い,間違っている可能性があります.
ODEのソースコードの中でBad argumentを検索し,API等を確認してデバッグ
してみてください.
原因がわかったら教えて頂ければありがたいです.
でむ
こんにちわ.
Bad Argument(s)のエラーが一向に消える気配がありません.
関節の位置をしっかりと指定して実行したのですが,同じエラーがでてきてしまいます.
Bat Argument(s)のエラーが出る前までは,「join and bodies must be in same world」というエラーが出てました.
このエラーが出ているときは,まだ関節を設定していない状況でした.
関節を設定してからBat Argument(s)のエラーが出るようになったので,エラーの原因は,関節の部分と見てよろしいのでしょうか?
こんばんわ.
連投になってしまいますが,Bat Argument(s)のエラーは回避できました.
dSpaceAdd(space_ID,spere[i]);というところで,iの値が定義していないオブジェクト(?)の番号をさしていました.
そこを直したら実行ができるようになりました.
しかし,実行してみると,オブジェクトがあちこちに飛び跳ねている,と,いう状況になっていました.
もし,よろしければ,考えられる原因を教えていただけますか?
KidAmさん,
Bad Argumentsエラーの回避良かったですね.
現象をもう少し詳しく説明してください.
オブジェクトがあちこち飛び離れる現象は,シミュレーション開始直後は
バラバラになっていないが,直後に爆発するように飛び跳ねるということでしょうか?
もしそうなら,ジオメトリが重なっていると思います.
ジオメトリが重なると反発力が発生します.
衝突検出OFFにしても現象が発生するか確認して,発生しない場合は衝突検出が問題なので,
重なっているジオメトリの位置を変更し,重ならないようにしてください.
でむ
おはようございます
現象としましては,バラバラにはなっておらず,バギーの形を維持したままあちこち飛び跳ねている感じです.
この飛び跳ねる問題は,nearCallbackをいじったので,おそらく解決したかと思われます.
ですが,次にまた新たな問題がでてきました.
バギーの上に,ロボットの胴体となる直方体をボールジョイントで着けたいのですが,シミュレーション開始直後には直方体が,バギーをすり抜けて地面に落ちてしまっており,バギーとの衝突はないようです.
自分が作ったデモのソースを貼り付けますので,よろしければ,実行してみてください.
また,なにか気になる場所があれば指摘をお願いします.
#include
#include
#include “texturepath.h”
#ifdef _MSC_VER
#pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
#endif
// select correct drawing functions
#ifdef dDOUBLE
#define dsDrawBox dsDrawBoxD
#define dsDrawSphere dsDrawSphereD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCapsule dsDrawCapsuleD
#endif
// some constants
#define LENGTH 0.7 // chassis length
#define WIDTH 0.5 // chassis width
#define HEIGHT 0.2 // chassis height
#define RADIUS 0.18 // wheel radius
#define STARTZ 0.5 // starting height of chassis
#define CMASS 1 // chassis mass
#define WMASS 0.2 // wheel mass
/******************************nao param**************************/
//nao torso param
#define torso_X 0.1
#define torso_Y 0.1
#define torso_Z 0.18
#define torso_mass 1.2171
//head1 neck
#define head1_L 0.08 //length
#define head1_R 0.015 //半径のR
#define head1_mass 0.05
#define head1_rad_max 3.14/3 //最大限界角度
#define head1_rad_min -3.14/3
//head2 face
#define head2_R 0.065 //球体の半径
#define head2_mass 0.35
#define head2_rad_max 3.14/8
#define head2_rad_min 3.14/8
//shoulder
#define shoulder_R 0.01
#define shoulder_mass 0.07
#define arm1_max 3.14/3
#define arm1_min -3.14/3
#define arm2_rad_max 3.14/0.033 //rarm2のmaxは-95,larm2のmaxは95
#define arm2_rad_min 3.14/3.14 //rarm2のminは1,larm2のminは-1
//upper_arm
#define upper_arm_X 0.07
#define upper_arm_Y 0.08
#define upper_arm_Z 0.06
#define upper_arm_mass 0.15
#define arm3_rad_max 3.14/3
#define arm3_rad_min -3.14/3
//elbow
#define elbow_R 0.01
#define elbow_mass 0.035
#define arm4_rad_max 3.14/4
#define arm4_rad_min 3.14/3.14
//low_arm
#define low_arm_X 0.05
#define low_arm_Y 0.11
#define low_arm_Z 0.05
#define low_arm_mass 0.2
// dynamics and collision objects (chassis, 3 wheels, environment)
/********************************************************************/
static dWorldID world;
static dSpaceID space;
static dBodyID body[15];
static dJointID joint[16]; // joint[0] is the front wheel
static dJointGroupID contactgroup;
static dGeomID ground;
static dSpaceID car_space;
static dGeomID box[6];
static dGeomID sphere[9];
static dGeomID capsule[1];
static dGeomID ccylinder[1];
static dGeomID ground_box;
// things that the user controls
/*static*/ dReal speed=0,steer=0; // user commands
// this is called by dSpaceCollide when two objects in space are
// potentially colliding.
static void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
int i,n;
// only collide things with the ground
int g1 = (o1 == ground || o1 == ground_box);
int g2 = (o2 == ground || o2 == ground_box);
if (!(g1 ^ g2)) return;
const int N = 100;
dContact contact[N];
n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
if (n > 0) {
for (i=0; i 0.1) v = 0.1;
if (v < -0.1) v = -0.1;
v *= 10.0;
dJointSetHinge2Param (joint[0],dParamVel,v);
dJointSetHinge2Param (joint[0],dParamFMax,0.2);
dJointSetHinge2Param (joint[0],dParamLoStop,-0.75);
dJointSetHinge2Param (joint[0],dParamHiStop,0.75);
dJointSetHinge2Param (joint[0],dParamFudgeFactor,0.1);
dSpaceCollide (space,0,&nearCallback);
dWorldStep (world,0.05);
// remove all contact joints
dJointGroupEmpty (contactgroup);
}
//drawObjects
dsSetColor (0,1,1);
dsSetTexture (DS_WOOD);
dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
dReal torso[3] = {torso_X,torso_Y,torso_Z+STARTZ};
dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
dsSetColor (1,1,1);
for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]),
dBodyGetRotation(body[i]),0.02f,RADIUS);
dsDrawBox (dBodyGetPosition(body[6]),dBodyGetRotation(body[6]),torso);
dVector3 ss;
//dGeomBoxGetLengths (ground_box,ss);
// dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
/*
printf ("%.10f %.10f %.10f %.10f\n",
dJointGetHingeAngle (joint[1]),
dJointGetHingeAngle (joint[2]),
dJointGetHingeAngleRate (joint[1]),
dJointGetHingeAngleRate (joint[2]));
*/
}
int main (int argc, char **argv)
{
int i;
dMass m;
// setup pointers to drawstuff callback functions
dsFunctions fn;
fn.version = DS_VERSION;
fn.start = &start;
fn.step = &simLoop;
fn.command = &command;
fn.stop = 0;
fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
// create world
dInitODE2(0);
world = dWorldCreate();
space = dHashSpaceCreate (0);
contactgroup = dJointGroupCreate (0);
dWorldSetGravity (world,0,0,-0.98);
ground = dCreatePlane (space,0,0,1,0); //地面生成
// chassis body
body[0] = dBodyCreate (world);
dBodySetPosition (body[0],0,0,STARTZ);
dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
dMassAdjust (&m,CMASS);
dBodySetMass (body[0],&m);
box[0] = dCreateBox (0,LENGTH,WIDTH,HEIGHT);
dGeomSetBody (box[0],body[0]);
// wheel bodies
for (i=1; i<=3; i++) {
body[i] = dBodyCreate (world);
dQuaternion q;
dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
dBodySetQuaternion (body[i],q);
dMassSetSphere (&m,1,RADIUS);
dMassAdjust (&m,WMASS);
dBodySetMass (body[i],&m);
sphere[i-1] = dCreateSphere (0,RADIUS);
dGeomSetBody (sphere[i-1],body[i]);
}
/*
//head1 Cylinder
body[4] = dBodyCreate (world);
dBodySetPosition (body[4],0.5*torso_X,0.5*torso_Y,STARTZ+torso_Z);
dMassSetCapsule (&m,1,3,head1_R,head1_L);
dMassAdjust (&m,head1_mass);
dBodySetMass (body[4],&m);
ccylinder[0] = dCreateCCylinder (0,head1_R,head1_L);
dGeomSetBody (ccylinder[0],body[4]);
//head2 Sphere
body[5] = dBodyCreate (world);
dBodySetPosition (body[5],0.5*torso_X,0.5*torso_Y,STARTZ+torso_Z+0.2);
dMassSetSphere (&m,1,head2_R);
dMassAdjust (&m,head2_mass);
dBodySetMass (body[5],&m);
sphere[4] = dCreateSphere (0,head2_R);
dGeomSetBody (sphere[4],body[5]);
*/
//torso box
body[6] = dBodyCreate (world);
dBodySetPosition (body[6],0,0,STARTZ+torso_Z);
dMassSetBox (&m,1,torso_X,torso_Y,torso_Z);
dMassAdjust (&m,torso_mass);
dBodySetMass (body[6],&m);
box[1] = dCreateBox (0,torso_X,torso_Y,torso_Z);
dGeomSetBody (box[1],body[6]);
/*
//r_shoulder sphere
body[7] = dBodyCreate (world);
dBodySetPosition (body[7],0.5*torso_X,-shoulder_R,STARTZ+torso_Z-shoulder_R);
dMassSetSphere (&m,1,shoulder_R);
dMassAdjust (&m,shoulder_mass);
dBodySetMass (body[7],&m);
sphere[5] = dCreateSphere (0,shoulder_R);
dGeomSetBody (sphere[5],body[7]);
//l_shoulder sphere
body[8] = dBodyCreate (world);
dBodySetPosition (body[8],0.5*torso_X,torso_Y+shoulder_R,STARTZ+torso_Z-shoulder_R);
dMassSetSphere (&m,1,shoulder_R);
dMassAdjust (&m,shoulder_mass);
dBodySetMass (body[8],&m);
sphere[6] = dCreateSphere (0,shoulder_R);
dGeomSetBody (sphere[6],body[8]);
//r_upper-arm box
body[9] = dBodyCreate (world);
dBodySetPosition (body[9],0,-upper_arm_Y,STARTZ+torso_Z-shoulder_R*2);
dMassSetBox (&m,1,upper_arm_X,upper_arm_Y,upper_arm_Z);
dMassAdjust (&m,upper_arm_mass);
dBodySetMass (body[9],&m);
box[2] = dCreateBox (0,upper_arm_X,upper_arm_Y,upper_arm_Z);
dGeomSetBody (box[2],body[9]);
//l_upper-arm box
body[10] = dBodyCreate (world);
dBodySetPosition (body[10],0,torso_Y+upper_arm_Y,STARTZ+torso_Z-shoulder_R*2);
dMassSetBox (&m,1,upper_arm_X,upper_arm_Y,upper_arm_Z);
dMassAdjust (&m,upper_arm_mass);
dBodySetMass (body[10],&m);
box[3] = dCreateBox (0,upper_arm_X,upper_arm_Y,upper_arm_Z);
dGeomSetBody (box[3],body[10]);
//r_elbow sphere
body[11] = dBodyCreate (world);
dBodySetPosition (body[11],0,-elbow_R,STARTZ+torso_Z-shoulder_R*2-upper_arm_Z-elbow_R);
dMassSetSphere (&m,1,elbow_R);
dMassAdjust (&m,elbow_mass);
dBodySetMass (body[11],&m);
sphere[7] = dCreateSphere (0,elbow_R);
dGeomSetBody (sphere[7],body[11]);
//l_elbow sphere
body[12] = dBodyCreate (world);
dBodySetPosition (body[11],elbow_R,torso_Y+elbow_R,STARTZ+torso_Z-shoulder_R*2-upper_arm_Z-elbow_R);
dMassSetSphere (&m,1,elbow_R);
dMassAdjust (&m,elbow_mass);
dBodySetMass (body[12],&m);
sphere[8] = dCreateSphere (0,elbow_R);
dGeomSetBody (sphere[8],body[12]);
//r_low_arm box
body[13] = dBodyCreate (world);
dBodySetPosition (body[13],0,-low_arm_Y,STARTZ+torso_Z-shoulder_R*2-upper_arm_Z-elbow_R*2);
dMassSetBox (&m,1,low_arm_X,low_arm_Y,low_arm_Z);
dMassAdjust (&m,low_arm_mass);
dBodySetMass (body[13],&m);
box[4] = dCreateBox (0,low_arm_X,low_arm_Y,low_arm_Z);
dGeomSetBody (box[4],body[13]);
//r_low_arm box
body[14] = dBodyCreate (world);
dBodySetPosition (body[14],0,torso_Y+low_arm_Y,STARTZ+torso_Z-shoulder_R*2-upper_arm_Z-elbow_R*2);
dMassSetBox (&m,1,low_arm_X,low_arm_Y,low_arm_Z);
dMassAdjust (&m,low_arm_mass);
dBodySetMass (body[14],&m);
box[5] = dCreateBox (0,low_arm_X,low_arm_Y,low_arm_Z);
dGeomSetBody (box[5],body[14]);
*/
//最初の描画位置
//バギー
// dBodySetPosition (body[0],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);
dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);
dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);
dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);
//ロボットモデル
/*dBodySetPosition (body[4],torso_X*0.5,torso_Y,torso_Z*1.1);//head1 neck
dBodySetPosition (body[5],torso_X*0.5,torso_Y,torso_Z*1.1);//head2 face
dBodySetPosition (body[6],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT);//torso
dBodySetPosition (body[7],torso_X,-0.5*torso_Y,torso_Z*0.7);//r_shoulder
dBodySetPosition (body[8],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);//l_shoulder
dBodySetPosition (body[9],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);//r_upper_arm
dBodySetPosition (body[10],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);//l_upper_arm
dBodySetPosition (body[11],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);//r_elbow
dBodySetPosition (body[12],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);//l_elbow
dBodySetPosition (body[13],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);//r_low_arm
dBodySetPosition (body[14],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);//r_low_arm
*/
// front wheel hinge
/*
joint[0] = dJointCreateHinge2 (world,0);
dJointAttach (joint[0],body[0],body[1]);
const dReal *a = dBodyGetPosition (body[1]);
dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
dJointSetHinge2Axis1 (joint[0],0,0,1);
dJointSetHinge2Axis2 (joint[0],0,1,0);
*/
// front and back wheel hinges
for (i=0; i<3; i++) {
joint[i] = dJointCreateHinge2 (world,0);
dJointAttach (joint[i],body[0],body[i+1]);
const dReal *a = dBodyGetPosition (body[i+1]);
dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]);
dJointSetHinge2Axis1 (joint[i],0,0,1);
dJointSetHinge2Axis2 (joint[i],0,1,0);
}
//wheel hinges settings
// set joint suspension
for (i=0; i<3; i++) {
dJointSetHinge2Param (joint[i],dParamSuspensionERP,0.4);
dJointSetHinge2Param (joint[i],dParamSuspensionCFM,0.8);
}
// lock back wheels along the steering axis
for (i=1; i<3; i++) {
// set stops to make sure wheels always stay in alignment
dJointSetHinge2Param (joint[i],dParamLoStop,0);
dJointSetHinge2Param (joint[i],dParamHiStop,0);
// the following alternative method is no good as the wheels may get out
// of alignment:
// dJointSetHinge2Param (joint[i],dParamVel,0);
// dJointSetHinge2Param (joint[i],dParamFMax,dInfinity);
}
//**************robot model hinges setting*************
//torso & buggy's body
joint[4] = dJointCreateBall (world,contactgroup);
dJointAttach (joint[4],body[1],body[6]);
dJointSetBallAnchor (joint[4],0.5*LENGTH,0.5*WIDTH,STARTZ);
/*
//torso & neck
joint[5] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[5],body[6],body[4]);
dJointSetHingeAnchor (joint[5],0.5*torso_X,0.5*torso_Y,STARTZ+torso_Z);
dJointSetHingeAxis (joint[5],0,1,0);
dJointSetHingeParam (joint[5],dParamLoStop,head1_rad_min);//角度範囲下限
dJointSetHingeParam (joint[5],dParamHiStop,head1_rad_max);//角度範囲上限
// dJointSetHingeParam (joint[i],dParamStopCFM,1/(DT*kp+kd));
// dJointSetHingeParam (joint[i],dParamStopERP,(DT*kp)/(DT*kp+kd));
// dJointSetHingeParam (joint[i],dParamVel,速度);
// dJointSetHingeParam (joint[i],dParamFMax,力の最大値);
// dJointSetHingeParam (joint[i],dParamFudgeFactor,0.1);
//neck & face
joint[6] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[6],body[4],body[5]);
dJointSetHingeAnchor (joint[6],0.5*torso_X,0.5*torso_Y,STARTZ+torso_Z);
dJointSetHingeAxis (joint[6],0,0,1);
dJointSetHingeParam (joint[6],dParamLoStop,head2_rad_min);
dJointSetHingeParam (joint[6],dParamHiStop,head2_rad_min);
// dJointSetHingeParam (joint[i],dParamStopCFM,1/(DT*kp+kd));
// dJointSetHingeParam (joint[i],dParamStopERP,(DT*kp)/(DT*kp+kd));
// dJointSetHingeParam (joint[i],dParamVel,速度);
// dJointSetHingeParam (joint[i],dParamFMax,力の最大値);
// dJointSetHingeParam (joint[i],dParamFudgeFactor,0.1);
//r_shoulder & torso
joint[7] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[7],body[6],body[7]);
dJointSetHingeAnchor (joint[7],0.5*torso_X,-shoulder_R,STARTZ+torso_Z-shoulder_R);
dJointSetHingeAxis (joint[7],0,1,0);
dJointSetHingeParam (joint[7],dParamLoStop,arm1_min);
dJointSetHingeParam (joint[7],dParamHiStop,arm1_max);
//l_shoulder & torso
joint[8] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[8],body[6],body[8]);
dJointSetHingeAnchor (joint[8],0.5*torso_X,torso_Y+shoulder_R,STARTZ+torso_Z-shoulder_R);
dJointSetHingeAxis (joint[8],0,1,0);
dJointSetHingeParam (joint[8],dParamLoStop,arm1_min);
dJointSetHingeParam (joint[8],dParamHiStop,arm1_max);
//r_shoulder & r_upper_arm
joint[9] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[9],body[7],body[9]);
dJointSetHingeAnchor (joint[9],0,-upper_arm_Y,STARTZ+torso_Z-shoulder_R*2);
dJointSetHingeAxis (joint[9],1,0,0);
dJointSetHingeParam (joint[9],dParamLoStop,-arm2_rad_max);
dJointSetHingeParam (joint[9],dParamHiStop,arm2_rad_min);
//l_shoulder & l_upper_arm
joint[10] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[10],body[8],body[10]);
dJointSetHingeAnchor (joint[10],0,torso_Y+upper_arm_Y,STARTZ+torso_Z-shoulder_R*2);
dJointSetHingeAxis (joint[10],1,0,0);
dJointSetHingeParam (joint[10],dParamLoStop,-arm2_rad_min);
dJointSetHingeParam (joint[10],dParamHiStop,arm2_rad_max);
//r_upper_arm & r_elbow
joint[11] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[11],body[9],body[11]);
dJointSetHingeAnchor (joint[11],0,-elbow_R,STARTZ+torso_Z-shoulder_R*2-upper_arm_Z-elbow_R);
dJointSetHingeAxis (joint[11],1,0,0);
dJointSetHingeParam (joint[11],dParamLoStop,-0);
dJointSetHingeParam (joint[11],dParamHiStop,+0);
//l_upper_arm & l_elbow
joint[12] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[12],body[10],body[12]);
dJointSetHingeAnchor (joint[12],elbow_R,torso_Y+elbow_R,STARTZ+torso_Z-shoulder_R*2-upper_arm_Z-elbow_R);
dJointSetHingeAxis (joint[12],1,0,0);
dJointSetHingeParam (joint[12],dParamLoStop,-0);
dJointSetHingeParam (joint[12],dParamHiStop,+0);
//r_elbow & r_low_arm
joint[13] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[13],body[11],body[13]);
dJointSetHingeAnchor (joint[13],0,-low_arm_Y,STARTZ+torso_Z-shoulder_R*2-upper_arm_Z-elbow_R*2);
dJointSetHingeAxis (joint[13],1,0,0);
dJointSetHingeParam (joint[13],dParamLoStop,45);
dJointSetHingeParam (joint[13],dParamHiStop,45);
//r_elbow & r_low_arm
joint[14] = dJointCreateHinge (world,contactgroup);
dJointAttach (joint[14],body[12],body[14]);
dJointSetHingeAnchor (joint[14],0,torso_Y+low_arm_Y,STARTZ+torso_Z-shoulder_R*2-upper_arm_Z-elbow_R*2);
dJointSetHingeAxis (joint[14],1,0,0);
dJointSetHingeParam (joint[14],dParamLoStop,45);
dJointSetHingeParam (joint[14],dParamHiStop,45);
*/
// create car space and add it to the top level space
car_space = dSimpleSpaceCreate (space);
dSpaceSetCleanup (car_space,0);
/*
for(int f = 0;f <= 5;f++){
dSpaceAdd (car_space,box[f]);
}*/
dSpaceAdd (car_space,box[0]);
dSpaceAdd (car_space,box[1]);
/*for(int f = 0;f <= 8 ;f++){
dSpaceAdd (car_space,sphere[f]);
}*/
dSpaceAdd (car_space,sphere[0]);
dSpaceAdd (car_space,sphere[1]);
dSpaceAdd (car_space,sphere[2]);
// dSpaceAdd (car_space,sphere[3]); //定義されてない
// dSpaceAdd (car_space,sphere[4]);
// dSpaceAdd (car_space,sphere[5]);
// dSpaceAdd (car_space,sphere[6]);
// dSpaceAdd (car_space,sphere[7]);
// dSpaceAdd (car_space,sphere[8]);
// environment
//ground_box = dCreateBox (space,2,1.5,1);
dMatrix3 R;
dRFromAxisAndAngle (R,0,1,0,-0.15);
//dGeomSetPosition (ground_box,2,0,-0.34);
// dGeomSetRotation (ground_box,R);
// run simulation
dsSimulationLoop (argc,argv,352,288,&fn);
for(int f = 0;f <= 5;f++){
dGeomDestroy (box[f]);
}//BOXobject
for(int f = 0;f <= 8;f++){
dGeomDestroy (sphere[f]);
}//SpereObject
dGeomDestroy (ccylinder[0]);//CCylinderObject
dJointGroupDestroy (contactgroup);
dSpaceDestroy (space);
dWorldDestroy (world);
dCloseODE();
return 0;
}
かなり汚いソースかと思いますが,よろしくお願いします.
ある位置に設定した剛体同士をジョイントによって接続したものを時間ステップごとに、最初に設定した位置ではなくて、自ら設定したポジション(位置、角度)に設定(移動)させることは可能でしょうか?
よろしくお願いします。
abcさん,
はじめまして.
必要がないので使ったことはありませんが,ボディをKinematic Stateに指定すればお望みのことができるかもしれません.
以下のリンクをご覧ください.
http://ode-wiki.org/wiki/index.php?title=Manual:_Rigid_Body_Functions#Kinematic_State
でむ
物体同士が衝突した際の跳ね返る方向に任意のノイズを加えることは可能でしょうか.
Georgeさん,
返事がとても遅くなりごめんなさい.
以下の方法でいかがですか?
1.物体重心位置の変化から跳ね返った方向を計算し,その方向にランダムな力を物体に加える
2.他の物体に衝突する直前に,進行方向にランダムな力を物体に加える
でむ
demuさん,
提案して頂い方法を試してみます.
ありがとうございます.
はじめまして.
ODEでは剛体だけでなく
例えばバルーンのような弾性体も取り扱うことができますか?
取り扱うことができるのであればその方法を教えてください.
kuroiwaさん
コメントありがとうございます。
ODEは剛体の動力学計算エンジンなので弾性体、軟体のシミュレーションはできません。
剛体同士の衝突ならバネ・ダンパモデルを適用できますが..
でむ
はじめまして.
PS2のコントローラをUSBコンバータを介してPCに接続し,PS2コントローラからの入力でODE内のシミュレーションモデルを操作しようと考えているのですが,上手くいきません.
自分なりに調べて見た感じだと,ゲームコントローラからの入力を受け取るサンプルはだいたいint WINAPI WinMain~の形で書かれているのですが,ODEではint main~のためどのように組み合わせていいのかもわかりませんでした.
よろしければ,どのようにすれば解決できるのかを教えていただけないでしょうか.
よろしくお願いします.
Asidxxさん、
はじめまして。
ODEのサンプルプログラムではsimLoop関数が、シミュレーションの各ステップで呼び出されています。
必要なコードはsimLoop関数の中に書いてください。
よろしくお願いします。
でむ
Asidxxさん、
返事がとてもおそくなりすみません。
ご質問のないようが,Windowsプログラミングに関するものなので他で聞いて頂けますか。
お力になれず、すみません。
でむ
demura様、初めまして。
学校での自習テーマとしてODEを選び、こちらのサイトを参考にして勉強している者です。
今までは学校のPCだけで勉強していたのですが、自宅のPCにODEインストールしたところ問題が起き、
どうにも解決策が分からないので質問させて頂きました。
Code:BlocksとODEのインストールとODEのビルドは問題なく完了したのですが、生成されたデモプログラムを確認すると、
とても速い速度でシミュレーションが実行されてしまいます。
全部のデモが同じ様に高速で実行されます。
(こちらのサイトで見られる動画と比べると、空のテクスチャが倍ぐらいの速さで流れる)
学校のPCの開発環境(windows7Pro、VC++2008、ode-0.11.1)ではこの現象は起きておらず
自宅のPC(windows7pro、Code:Blocks10.05、ode-0.11.1)で初めて遭遇しました。
インストールの工程も確認しましたが、Code:Blocks10.05だとソフトの日本語化のみ省いた以外
特に違うことはしてない(と思う)ので、何が原因で起きるのか見当がつきません。
アドバイスよろしくお願いします。
(過去の質問もざっと見ましたが、重複する質問があったらすみません。)
motohashiさん、
コメントありがとうございます。
motohashiさんのコンピュータのグラフィクスチップが高速なことが原因です。
とくに問題はありません。気になる場合は、雲(空のテクスチャ)の移動量を小さくすると解決できます。
ご必要なら具体的な方法を回答します。
でむ
はじめまして。
今年の4月にODEをいじり始めた初心者です。
いま、全方向移動型のロボットを作成し、ロボットの動作に合わせてカメラも動作させたいと考えています。
カメラの位置を変数にして、キー入力でその変数が変化するように設定したのですがうまくいきません。
よろしければアドバイス等をいただけるとうれしいです。
ishikawaさん
返事が遅くなりすみません。
例えば、以下のようにするとx座標のカメラ位置が変わります。
参考になれば幸いです。
でむ
switch (cmd)
{
case ‘x’:
xyz[0] += 0.1f;
xyz[1] = 15.54f;
xyz[2] = 26.0f;
hpr[0] = 90.0f;
hpr[1] = -90.0f;
hpr[2] = 0.0f;
dsSetViewpoint(xyz,hpr);
break;
以下略
質問です。
コンパイルは通りましたが実行してみると
Bad argument(s) in dGeomGetPosition()と表示されてしまいます。
何が原因でしょうか?
tarouさん、
dGeomGetPosition()の引数が悪いという情報ですね。
引数の値を表示して確認してください。
でむ
楕円体の生成方法を教えていただけませんか?
基本形状ではないので,三角メッシュで作成するしかありません.
でむ
こんにちは。
質問なのですが、例えば、ヒンジジョイントでつながれた物体A(本体)とB(タイヤ)の車があるとします。
これら全体の初期の姿勢角度を変更しようとすれば、どうすればいいのでしょう?
試したのですが、本体の初期の姿勢角度を変更すると、タイヤは何故かdBodySetPositionで設定した位置からずれてしまうようです。
なにか良い方法はないでしょうか・・・?
slideさん,
こんにちは.
タイヤとヒンジジョイントの位置を変換してから,車を作り直せばよいと考えます.
でむ
簡単!実践!ロボットシュミレーションを購入させて頂きました。
プチプロジェクトとして様々な例題が記載されていますが、
これらの回答に当たるソースは公開されているのでしょうか?
ご購入ありがとうございます。プチプロジェクトのソースは公開していません。
でむ
SONYのVAIO Type Zを使っています。ODEをインストールしたところ、空が灰色でスピードも遅くて困っています。ちなみに、ディスプレイドライバはIntel HD Graphic 3000です。よろしくお願いします。
匿名さん
はじめまして。
これは、ODEというよりdrawstuffの問題です。drawstuffはOpenGLを使っていますが、VAIOのディスプレイドライバの問題です。以下のページを参考に変更してください。
http://forum.notebookreview.com/sony/625418-new-z2-gpu-driver-released.html
今のところVAIO Updateではアップデートできません。
でむ
はじめまして。
CodeBlocksにてOpenCVを使っています。ここの記事http://demura.net/misc/2884.htmlを参考にしてCodeblocksの設定をしてみました。(バージョンも同じく1.0です)
OpenCVのディレクトリにあるサンプルプログラムを実行することはできましたが、自分でプロジェクトを作成してビルドして実行したときに次のように聞いてくるウィンドウが開きます。
“It seems that this project has not been built yet.
Do you want to build it now?”
“はい”を選択すると何も起こりませんし、”いいえ”を選択するとコンソール画面だけしか開きません。
どうかよろしくお願いします。
はじめまして。先生のODE本を参考にODEの勉強をさせてもらっています。
プログラムについての質問なのですが、STEP8の4脚ロボットのソースの work() 関数の中にある
THETA[leg_no][joint_no] = gait[t%12][leg_no][joint_no];
という記述で、何故 t%12 で数値を回しているのかがどうしても理解できません。
お忙しいかとは思いますが、もし良ければご教授お願いします。
ndekaさん、
返信が遅くなってすみません。修士公聴会、卒研発表、ドメイン契約更新などですっかり回答が遅くなってしまいました。
12で回しているのは歩行を12ステップに分解しているからです。
詳しくは拙著ODE本のP209をご覧ください。
でむ
お返事ありがとう御座います。
読み返して何とか理解することが出来ました。
少し疑問に思ったのですが、このプログラムではworldstep毎に関節角度などを更新しています。
こういった場合もし計算などが膨大になった場合、ラグったり、更新が間に合わなくてロボットの挙動が不安定になったりするものでしょうか?
疑問の方は自己解決出来ました。
御教授いただきありがとう御座います。
初めまして。私は譜面データから動作を生成し、表示するシステムの研究しています。
ODEで動作の表示部分を作成しています。
そこで質問があります。
現在、ロボットを作成しまして、そこに衝突検出を組み込んでいるところです。
ロボットの足の部分を直方体と円柱をhingejointを用いて生成しています。
しかし、その足の部分を付け加えて衝突検出を行うと、argument not a spaceというエラーが出てしまいます。
足の部分を消してやったロボットで衝突検出を行うとこのエラーはでません。
『簡単!実践!ロボットシミュレーション』でもロボットを作成していたと思うのですが、このような
エラーは出なかったのでしょうか?
出なかったのであれば、何が問題なのでしょうか?
なにか御存じであれば教えて頂けると有難いです.
よろしくお願いします.
すいません。自己解決しました。
宣言のjointの数と実際使用しているjointの数が違うのが問題でした。
アスファルトの上を車いすが移動するとした場合、実世界と摩擦などを近づけるにはどのような値を入れれば良いのでしょうか。教えてください。
contact[i].surface.mu =
contact[i].surface.mu2 =
contact[i].surface.soft_cfm =
contact[i].surface.soft_erp =
コメントありがとうございます。
ODEは動摩擦係数、静止摩擦係数の違いがないので精度の高いシミュレーションには向きません。アスファルトのモデリングをしたことがないので詳しい数値はわかりません。
でむ
初めまして、ODEを使い移動型倒立振子を作成する卒業研究をしています。
前の人の引継ぎで研究をしているのですが、ソースファイルが無くVisual C++を使って製作していたみたいなのですが、動かず最初からODEをダウンロードしてやってみたのですがうまく作動してくれません。
しばらくCode::Blocksを使って製作していたのですが、前の人のプログラムを書き込んでみるとエラーになります。
教授に聞けば前の方はロボットシュミレーションの教材以外にも出村教授に使い方の資料をもらって参考にしていたみたいです。
差支えが無ければ私にも参考資料等がございましたら、譲っていただきたいのです。
それと現在わからないところなんですが、Code::Blocksではソースファイルを入れるところはありますか?
わがままを言って申し訳ありません。
どうぞよろしくお願いします。
uenoさん,
使い方の資料は,ODE本とこのブログにある資料以外にありません.
Code::Blocksの使いかたはこのブログにも少し解説しています.
検索窓から探してください.
でむ
お返事ありがとうございます。
私の勉強不足で、失礼な質問をしてすみません。
ODE本と前の方の論文から私なりに倒立振子を作ることはできたのですが、
移動型にするための車輪のつけ方がどうしてもわからないので教えていただけたらありがたいです。
ちなみに、Visual C++ 2008 をつかって製作していて、倒立振子は2次元で表示、
移動も2次元の左右移動にしたいです。
かなり行数が多いのですが、可能であれば製作したプログラムを見ていただきたいのですが。
よろしくお願いします。
uenoさん、
最近忙しくなってデバッグのサービスまでできません。
ごめんなさい。
でむ
はじめまして。
このサイトを元にODE,VisualC++2008をダウンロードししました。
サンプルは動くのですが、新しいプロジェクトから本に書いてあったプログラムを実行しようとすると
‘ode/ode.h’: No such file or directory
とでて実行できません。ヘッダファイルが開けていないのでしょうか?
初歩的なことで申し訳ありませんがよろしくお願いします。
初めまして、先生のHPと書籍をいつも利用させていただいています。
今回ODEの衝突検出に関して不明な点があるため質問をさせていただきます。
先生のサンプルプログラムの中でボールが床に衝突した際に色が変わるプログラムがあると思うのですが、
私はこれを利用して二足歩行ロボットがどちらの足で着地をしているかを判別したい考えています。
現在、左右どちらか一方の足の着地は判断できたのですが、両脚が着地している状態を判別することができません。
ODEでは複数個所を同時に衝突検出することは不可能なんでしょうか?
的外れな質問をしていたらすいません、先生の意見を聞かせていただけないでしょうか。
お忙しい所申し訳ありませんがよろしくお願いします。
こんにちは、
ODE本STEP7「関節角速度と先端速度の関係」を参考にして、
ヤコビ行列から6軸ロボットの動きをつくっています。
位置速度は問題ないのですが、角速度に問題がでて困っています。
R1*R2*R3*R4*R5*R6の回転行列からロールピッチヨーとして姿勢を取り出し、
それを微分した式をヤコビ行列に当てています。
(数値は、ODEのdBodyGetRotationから合っていることを確認しています)
これをシミュレーションしてみると、
ヨー角は 絶対座標で回転し、
ロール角は相対座標で回転し、
ピッチ角はわけのわからない動きになってしまいます。
どうすれば、相対座標で統一、もしくは絶対座標で統一させて動かせるのでしょうか。
よろしくお願いします。
すみません、ここを見て自己解決しました。
http://www5c.biglobe.ne.jp/~uso-ats/robbt/robo-no2/r-no2-2.html
ロボットの姿勢の考え方を勘違いしていたのが原因でした。
初めて質問します.
用語,文面等おかしく読みにくかったらすみません.
大学院の研究でピン挿入(ペグインホール)をしております.
その際のピン(ペグ)に作用する力・モーメントをODEを用いて算出しようと考えているのですが,
何か良いサンプル等ありませんか?
よろしくお願いします.
JOJOさん,
良いサンプルはありません.
すみません.
でむ
すみません.質問を変えます.
物体を地面に押し続けた際(Fx),
その反力として物体に作用する力(Nx)はODEの関数で表示できますか?
それとも計算式で自力で算出するしかありませんか?
Fx↓↓↓↓↓↓
/\
\Nx\
\↑/
=================
demuさんはじめまして.RozKenです.
大学院の研究でロボットの設計のため,物理シミュレーターを使おうと考えております.
demuさんのこのサイトを見つけて,Open Dynamics Engineに興味を持ちました.
「Big News for ODE:唯一の弱点が解決される!?」 ( http://demura.net/9ode/486.html )の記事を読んだのですが,現在のバージョンでは4次ルンゲクッタによる外力ソルバは実装されているのでしょうか?
また,LCPで用いているガウスザイデル法はOpenCLなどで並列化できると聞いたのですが,今後そのような予定はあるのでしょうか?これらがあれば,精度の点でもシミュレーション時間の点でも是非利用したいエンジンだと考えたのです.
もしよかったら,教えてくださいませ.
ルンゲクッタは実装されていません。数年前に誰かがルンゲクッタのパッチを投稿しましたが、実装が悪かったせいで組み込まれませんでした。ルンゲクッタを実装すると数倍から4倍遅くなるという報告ともあり、多くの開発者はODEを精度の高い用途では使っていないのであまり熱心ではありません。必要な人が実装すれば良いと思います。どうですか? Rozkenさん。
OpenCLの話も効きません。ただ、ODEは今まで衝突検出がBulletなどと差をつけられていましたが、最近、Continuous collision detectionが実装されたので、衝突検出はかなり改善されたと思います。
精度とスピードはトレードオフなので、高い精度が必要な場合はODEは向いてないと思います。精度は多少犠牲にしてもリアルタイム以上の速度が必要な場合はODEは候補になると思います。
でむ
demuさん。丁寧なコメントをありがとうございます。もう少し他の物理エンジンと比較してみたいと思います。
他の物理エンジンは何をお考えですか? OpenHRP, PhysX, Bullet あたりですか? OpenHRPとの定量的比較は見たことがないので、もし比較し結果が出たら教えてください。
でむ
でむさん,
HP,ODE本参考にさせて頂いてます.
描画に関して以下の質問があります.
①描画は遠近法(同じ大きさの物体でも,近くにある物は大きく,遠くにある物は小さい)ですが,
遠近法でない描画方法(図面を見るみたいに,距離に関係なく同じ大きさに見える)はありますでしょうか.
②物体を半透明にするため,以下APIを使用しているのですが,
alphaの値を変えても透明になりません.何が問題なのでしょうか.
dsSetColorAlpha(float red, float green, float blue, float alpha);
よろしくお願いします.
さがやまさん、
返事が遅れてすみません。
まず、ODEに付属のdrawstuffはデモのテスト用なので機能的には貧弱です。
① ありません。ご自分でソースコードを改変する必要があります。
② 私はそのような現象にあったことがないのでわかりません。drawstuffでは物体毎に色を設定することはできず、描画直前に呼ばれたAPIが反映されるので、そのためでしょうか?
でむ
はじめまして.
いつも参考にさせて頂いております.
早速質問なのですが, ODEを用いて, ボール(球体)をまっすぐ直線的に転がし,
転がした先にある円柱を倒す”ボーリング”のような環境を構築し遊んでいたのですが,
まったく同じ条件でボールをピンに衝突させているにも関わらず
ピンの倒れる本数にばらつきがうまれてきます.
僕の頭のなかでは, ボールの初期位置, 速度などすべてのパラメーターが同じであれば
同じ計算結果にならないとおかしいと思うのですが, なぜこのような違いがうまれるのでしょうか.
これはシミュレーションにおける安定性に起因するものなでしょうか?
基本的な質問で申し訳ありませんが教えて頂けませんでしょうか.
宜しくお願い致します.
takachanさん、
返事が遅れてすみません。やっと少し暇になりました。
さて、とても良い質問ですね(池上さん風)。
でも、本ブログの「ODEのよくある質問」のB23に回答済みです。そちらをご覧ください。
http://demura.net/ode_faq
でむ
現在,様々なシミュレータの性能や特徴を調べているのですが,
ODEでは閉リンク機構の動力学計算は行えるのでしょうか?
はじめまして。
現在、2足歩行ロボットシミュレータの制作をしています。
出村氏のテキスト『簡単!実践!ロボットシミュレーション』を参考にしながら進めているのですが、ちょっと壁に当たってしまったので質問させて頂こうと思った次第です。
上記テキストのstep9:ヒューマノイドロボット内の足の逆運動学(6自由度ロボットアーム)にて、有顔ベクトルaが使われていますが、これはどのように算出すればいいのでしょうか?
運動学で有顔ベクトルaを導出していますが、これを逆運動学用に使用することはできませんよね?
お忙しいかとは思いますが、ご教授いただけたら幸いです。
すみません、運動学の結果を利用してとありますので有顔ベクトルは求められますね。確認不足でした…。
ですが、別の問題があったので追記させて頂きます。
運動学の有顔ベクトルaの算出に使われる回転行列の角度θ1~6はdJointGetHingeAngleを使用して膝などの角度を取得すればいいんでしょうか?
分かりにくい質問でしたらごめんなさい。
すみません、自己解決しました。
追記が遅くなって済みませんでした
初めまして、まさしく同じことをやろうとして、同じところで悩んでいました。
逆運動学は、マニピュレータ先端の位置や姿勢から関節角度を算出することなので、
aについて運動学で出しても駄目なんじゃないでしょうか(関節角度が使われてしまう)
先端位置は3自由度しかなくて、逆運動学では6つの関節角度を求めるので、有顔ベクトルは
足の甲を水平にするとか、さらに拘束条件が必要な気がします。
すなわち、有顔ベクトルは求めるものではなく与えるものということではないでしょうか?
違っていたら済みません。もし、myuさんが、運動学で求めてて普通に歩行が出来ていれば
その旨教えて頂ければ助かります。
あるいは、初期値が地面に平行なので、そのままでも何となく出来てしまうのかも。
demuさん、お久しぶりです。以前質問させて頂いたくないです。
ODEのシミュレーションを画像として保存したいのですが、
見つけた方法ではVisual C++を使っているからか分かりづらく、
自分はcodeblocksを使っているので応用できないかと思い試してみましたがうまくいきません。
よろしければ、codeblocksでのシミュレーション画像の保存方法を教えていただけませんか?
くないさん、
返事が大変遅くなりすみません。
動画キャプチャソフトを使うのが一番簡単だと思います。
でも、そのような機能があればうれしいですよね。
irrDrawStuffに追加できるよう頑張ります。
でむ
はじめまして、秋田県立大学の4年生です。力覚の研究をしています。PHANTOM-omniで、ODEのアームのサンプルプログラムに力覚を提示させてみようとしてるのですがうまくいきません。よろしければアドバイスお願いします。
Maedaさん,
はじめまして.
PHANTOM-omniを使ったことがないので良くわかりません.
ODEの摩擦モデルはシンプルなので,物を掴むなどの摩擦モデルが重要になるシミュレーションには向いていないと思います.
でむ
こんにちは。4軸ロボットのシミュレータの制作をしているstarです。
自分は今、4軸ロボットにボールの追跡をさせるプログラムを制作していますが、ボールとロボットとの座標の表示の仕方や座標の算出方法などが分かりません。
よろしければ教えてください。
先ほどの質問の補足です。
物体の座標の位置を取得の方法についてですが、『dBodyGetPosition(dBodyID);』を使えばいいと自分では考えてますが、そうすると
‘dBodyGetPosition’ : 1 番目の引数を ‘MyObject’ から ‘dBodyID’ に変換できません。
というエラーが発生してしまいます。
やり方が間違っているのでしょうか?
因みに、4軸ロボットのシミュレータはこちらのページにあったサンプルを参考に制作しています。
starさん、
こんにちは。
エラーの出たdBodyGetPositionの行だけ全て教えてください。エラーを見る限り、引数の渡し方が間違っているように思えます。例えば、MyObject link; で宣言したら第1引数はlink.bodyになります。
でむ
返信ありがとうございます。
4軸ロボットの本体(base)の座標を獲得しようとmakebase関数の後に、
void printbasePosition()
{
double *po = (double *) dBodyGetPosition(base);
printf(“Current Position: x=%6.2f y=%6.2f z=%6.2f \n”,po[0],po[1],po[2]);
}
と入力したら、
error C2664: ‘dBodyGetPosition’ : 1 番目の引数を ‘MyObject’ から ‘dBodyID’ に変換できません。(新しい機能 ; ヘルプを参照)
この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。
というエラーが発生しました。
引数を変えようにもプログラムが余計複雑になってしまいます。
baseがMyObject構造体なら、一番目の引数はbase.bodyあるいbaseがポインタならbase->bodyになると思います。
試してもらえますか?
でむ
返信ありがとうございます。おかげさまで座標が表示されるようになりました。
もう一つ質問ですが、このプログラムの場合po[0]にx軸、po[1]にy軸が入っていることになるんですよね?
starさん,
よかったですね.
はい, x,y,zの値が順番に入っています.
でむ
はじめまして,よく利用させていただいています.
早速,質問なのですが
mm単位の物体を,実寸で再現したい(プログラムに書きこんだ数値は国際単位系基準で書いている)のですが,地面スレスレにカメラを(作製した物体の近くにviewpointを)もっていくと描画がおかしくなり,地面のテクスチャもおかしくなってしまいます.
すごく初歩的なことを聞いているのかもしれませんが,なにか御存じであれば教えて頂けると有難いです.
よろしくお願いします.
Kiuiさん、
ODEは動力学エンジンで、描画の部分はdrawstuffとうOpenGLで書かれた簡易ライブラリが担当しています。おかしくなるという意味が良くわかりませんが、テクスチャの解像度のためかもしれません。
画面一杯にテクスチャを拡大すると、荒が見えてしまいます。
でむ
遅くなって申し訳ありません.
返信ありがとうございます.
ある程度まとまってから・・と思っていたのですが,結局まとまらず.
>おかしくなるという意味が良くわかりませんが
具体的に言いますと,半径×長さ= 0.0005[m]×0.001[m]の円筒をODEで生成し,キー入力(コマンド入力)でカメラを近づけるようなプログラムを書きました.
ところが,0.001[m]づつカメラを近づけていくと,生成した物体がチラついたり,消えてしまったり,(地面のテクスチャはデフォルトのコンクリートのようなものを使用しているのですが)画面が全て灰色になったりします.
これ以上近づいてはいけない,みたいな制約があるのでしょうか?
現在はdrawsutff内,OPenGLの内のglFrustum()という関数が怪しいのではないか?と考え,書き変えてみましたが,こちらはこれでvs2008内のdemoプログラムには反映されるのですが,自身のプログラムには反映されてない・・・というような状況です.
まとまらない文章になってしまいましたが,よろしくおねがいします.
kiuiさん,
確かに,glFrustumはdrawstuffで以下のようになっていて,vnearが0.1fなので,それより近いところは見えなくなりますね.
const float vnear = 0.1f;
const float vfar = 100.0f;
const float k = 0.8f; // view scale, 1 = +/- 45 degrees
if (width >= height) {
float k2 = float(height)/float(width);
glFrustum (-vnear*k,vnear*k,-vnear*k*k2,vnear*k*k2,vnear,vfar);
}
else {
float k2 = float(width)/float(height);
glFrustum (-vnear*k*k2,vnear*k*k2,-vnear*k,vnear*k,vnear,vfar);
}
なお,drawstuffのテクスチャは256×256ピクセルで2×2単位距離です.ODE本ではSI単位系を使っていて2x2mの領域を256×256ピクセルで表現しています.
vnearを小さな値にしても,テクスチャの粒度と比較して円柱が小さすぎるので,テクスチャの見え方はおかしくなると思います.
ODE自体はSI単位系でなくてもよいので,1単位距離を例えば0.001mmなどと考えてサイズを変更してみてはいかがでしょうか.
また,vs2008内のdemoプログラムに反映されるが,自身のプログラムに反映されないということは考えづらいです.自身のプログラムをdemoプログラムと同じところに置き,ode-0.11.1\build\premake4.luaに自身のプログラム名を追加し,premake, buildしてみてはいかがでしょうか.
でむ
度々返信が遅くなって申し訳ありません.
言い訳をさせていただけるなら,実は卒業研究でODEを使って研究をしております.
その提出の期限が迫ってきてしまい,結局バタバタし遅れてしまうような始末であります.
本来は,自身で解決をしなければならないところなのですが…
私の研究は,生物のシミュレータを作製し運動のメカニズムなどを解析しようというのが目的で,大きさが変わってしまえば物体の密度や慣性も単位が変わってしまうし,リズムや動き自体も変化し,生物の動きの解析になりえるのか?という懸念があり,実寸サイズでつくるというようなところにこだわっていました.
2x2mの領域を256×256ピクセルということですので,ピクセルの表示限界まで近づいてしまったのではないか?という考えに達しました.
しかし,(期限ギリギリなので)おっしゃられて通りスケールを変更し作製(生物の1部分の挙動を確認)するという方向で(今回は)回避することにしました.
また,反映されないという問題はプログラムを置く場所を間違えていたようなので,これら二つの問題は時間があるときに解決をしていこうと考えています.
長くなってしまいましたが,お忙しいところ回答ありがとうございます.
Kiuiさん,
お互い忙しいと思いますので返信の遅れても問題ないです.
卒研のお役に立ててうれしいです.発表会頑張ってくださいね.
でむ
壁に近づいたら後退するプログラムについて教えてください。
Sakumaさん、
すみません。ODEの質問だけに限らせてください。
ロボットプログラム全般の質問ですと、範囲が膨大で収集がつかなくなりますから。
でむ
壁に近づくまで直進し,壁に近づいたら後退する自律移動ロボットコントローラを左壁沿い行動を行うようなコントローラにプログラムを修正する。
Sakumaさん
リンゴの落下のプログラムにdBodyGetForceと言う関数を入ると printfでしめす、なんで全部zeroになります?
どうか教えてください。
すみません。僕はこのことについて全然わかりません。
Sophieさん
重力や拘束力をdBodyGetForceで取得できません。以下のページをご覧ください。
http://groups.google.com/group/ode-users/browse_thread/thread/b61e5d8a1c59a52f/0d8459bf8a710c24?lnk=gst&q=dBodyGetForce#0d8459bf8a710c24
bodyに働く力は以下の式で計算するより他はありません。
質量 x 加速度 / ステップサイズ
りんご落下のプログラムに追加すると次のようになります。
static void simLoop (int pause)
{
dReal step_size = 0.01;
const dReal *pos,*R,*force,*v;
static dReal a[3], f[3], v_prev[3];
dWorldStep(world, step_size);
v = dBodyGetLinearVel(ball);
for (int i =0; i < 3; i++ ) { a[i] = (v[i] - v_prev[i])/step_size; v_prev[i] = v[i]; f[i] = mass * a[i]; } printf("fx=%f fy=%f fz=%f\n",f[0],f[1],f[2]); dsSetColor(1.0,0.0,0.0); pos = dBodyGetPosition(ball); R = dBodyGetRotation(ball); dsDrawSphere(pos,R,radius); } でむ
3個の物体の初期位置は,物体同士が重ならずの時の書き方は、if (n>0) でよろしいのですか。
Sakumaさん、
すみません。意味がわかりません。if (n>0)はどの関数内で、nは接触点数ですか? 初期位置はdBodySetPositionで設定すれば良いだけですが。
でむ
①ODEで直方体を2個生成する。
②2個の初期位置は,直方体同士が重ならず,地面に接していないこととする。
③2個の直方体の色を赤(直方体1)と青(直方体2)とする。
④直方体1はz軸方向に長く,直方体2はx軸方向に長くなるように大きさを設定する。※質量は,任意に設定して良い。
⑤直方体1は地面で弾まないように,直方体2は地面で弾むように設定する。
このようなプログラムソースコードの例を教えてください。
ここまで出来ているのですが、この先から進みません
#include
#include
#ifdef dDOUBLE
#define dsDrawSphere dsDrawSphereD
#define dsDrawBox dsDrawBoxD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCapsule dsDrawCapsuleD
#define dsDrawLine dsDrawLineD
#define dsDrawTriangle dsDrawTriangleD
#endif
static void nearCallback(void *data, dGeomID o1, dGeomID o2);
static void simLoop(int pause);
void start();
void setDrawStuff();
static void makeSphere(dReal m, double r, double *position);
static void makeBox(dReal m, double *sides, double *position);
static void makeCapsule(dReal m, double r, double l, double *position);
typedef struct {
dBodyID body;
dGeomID geom;
double m;
double l,r;
double sides[3];
} MyObject;
dWorldID world;
dSpaceID space;
dGeomID ground;
dJointGroupID contactgroup;
MyObject sphere;
MyObject box;
MyObject capsule;
dsFunctions fn;
int main(int argc, char **argv)
{
dReal m1 = 1.0;
double r1 = 0.2;
double p1[3] = {0.0, 0.06, 1.0};
dReal m2 = 1.0;
double sides[3] = {0.1,0.3,0.5};
double p2[3] = {0.01, 0.06, 2.0};
dReal m4 = 0.1;
double r4 = 0.1;
double l4 = 0.1;
double p4[3] = {0.0, 0.06, 3.0};
setDrawStuff();
dInitODE();
world = dWorldCreate();
dWorldSetGravity(world,0,0,-9.8);
space = dHashSpaceCreate(0);
contactgroup = dJointGroupCreate(0);
ground = dCreatePlane(space,0,0,1,0);
makeSphere(m1, r1, p1);
makeBox(m2, sides, p2);
makeCapsule(m4, r4, l4, p4);
dsSimulationLoop(argc,argv,640, 480,&fn);
dSpaceDestroy(space);
dWorldDestroy(world);
dCloseODE();
return 0;
}
void start()
{
static float xyz[3] = {2.0,0.0,2.0};
static float hpr[3] = {-180, -45, 0};
dsSetViewpoint(xyz,hpr); }
void setDrawStuff()
{
fn.version = DS_VERSION;
fn.start = &start;
fn.step = &simLoop;
fn.path_to_textures = “../../drawstuff/textures”;
}
void simLoop(int pause)
{
dSpaceCollide(space,0,&nearCallback);
dWorldStep(world,0.01);
dJointGroupEmpty(contactgroup);
dsSetColor(1.0,0.0,0.0);
const dReal *pos1 = dBodyGetPosition(sphere.body);
const dReal *R1 = dBodyGetRotation(sphere.body);
dsDrawSphere(pos1,R1,(const float)sphere.r);
dsSetColor(0.0,1.0,0.0);
const dReal *pos2 = dBodyGetPosition(box.body);
const dReal *R2 = dBodyGetRotation(box.body);
dsDrawBox(pos2,R2,box.sides);
dsSetColor(0.0,0.0,1.0);
const dReal *pos4 = dBodyGetPosition(capsule.body);
const dReal *R4 = dBodyGetRotation(capsule.body);
dsDrawCapsule(pos4,R4,(const float)capsule.l,(const float)capsule.r); }
static void nearCallback(void *data, dGeomID o1, dGeomID o2) {
static const int N = 10;
dContact contact[N];
int n = dCollide(o1,o2,N,&contact[0].geom,sizeof(dContact));
//if (isGround) {
if (n>0) {
for (int i = 0; i < n; i++) {
contact[i].surface.mode = dContactBounce;
contact[i].surface.bounce = 0.5;
contact[i].surface.bounce_vel = 0.0;
contact[i].surface.mu=1.0;
dJointID c = dJointCreateContact(world,contactgroup,
&contact[i]);
dJointAttach(c,dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));
}
}
}
static void makeSphere(dReal m, double r, double *position){
dMass mass;
sphere.body = dBodyCreate(world);
dMassSetZero(&mass);
dMassSetSphereTotal(&mass,m,r);
dBodySetMass(sphere.body,&mass);
dBodySetPosition(sphere.body,position[0],position[1],position[2]);
sphere.r = r;
sphere.geom = dCreateSphere(space,sphere.r);
dGeomSetBody(sphere.geom,sphere.body); }
static void makeBox(dReal m, double *sides, double *position){
dMass mass;
box.body = dBodyCreate(world);
dMassSetZero(&mass);
dMassSetBoxTotal(&mass,m,sides[0],sides[1],sides[2]);
dBodySetMass(box.body,&mass);
dBodySetPosition(box.body,position[0],position[1],position[2]);
box.sides[0] = sides[0];
box.sides[1] = sides[1];
box.sides[2] = sides[2];
box.geom = dCreateBox(space,box.sides[0],box.sides[1],box.sides[2]);
dGeomSetBody(box.geom,box.body); }
static void makeCapsule(dReal m, double r, double l, double *position){
dMass mass;
capsule.body = dBodyCreate(world);
dMassSetZero(&mass);
dMassSetCapsuleTotal(&mass,m,3,r,l);
dBodySetMass(capsule.body,&mass);
dBodySetPosition(capsule.body,position[0],position[1],position[2]);
capsule.r=r;
capsule.l=l;
capsule.geom = dCreateCapsule(space,capsule.r,capsule.l);
dGeomSetBody(capsule.geom,capsule.body);
}
takayuki-fさん,
御質問はなんでしょうか?
動かないのでソースコードを見て直して欲しいという御要望は,いろいろ立て込んでいるので対応できそうにありません.
すみません.
具体的には①から④までのうち,どれができなくて,何がわからないのでしょうか?
でむ
いきなりですみません。
④の所ができなくて困っています。
球を作っても上のプログラムでは、貫通してしまい、物体同士が衝突した時は弾み,物体と地面が衝突した時は弾まないように設定することができません。
よろしくお願いします。
nearCallback関数の引数o1とo2に衝突する可能性のあるジオメトリIDが入ります.それにより場合わけしてください.例えば,以下のようになります.
int isGround = ((ground == o1) || (ground == o2))
if (isGround)
{
弾まない設定に関するコードを書く
}
else
{
弾む設定に関するコードを書く
}
これで解決すれば良いのですが...
でむ
①ODEで球を1個,直方体を1個,カプセルを1個生成する。※大きさ,質量は,任意に設定
②3個の物体の初期位置は,物体同士が重ならず,地面に接してなく,シミュレーション開始後に衝突するような場所とする。
③球の色を赤,直方体の色を緑,カプセルを青とする。
④物体同士が衝突した時は弾み,物体と地面が衝突した時は弾まないように設定する。
物体同士が衝突した時は弾み,物体と地面が衝突した時は弾まないように設定することがよくわかりません。どうか教えてください。
nearCallback関数の引数o1とo2に衝突する可能性のあるジオメトリIDが入ります.それにより場合わけしてください.例えば,以下のようになります.
int isGround = ((ground == o1) || (ground == o2))
if (isGround)
{
弾まない設定に関するコードを書く
}
else
{
弾む設定に関するコードを書く
}
これで解決すれば良いのですが弾まない設定に関するコードと弾む設定に関するコードを教えてください。
答えは見つかりましたか。
答えを見つけるのは私ではないと思いますが…
弾まない設定は、反発係数を0にすれば良いと思います。
反発係数の設定法は、ODEのマニュアルと拙著に書いてありますよ。
でむ