新しい質問や要望はこちらにお願いします!
なお、私のコメントやご自分の努力により問題が解決 された場合に、問題の原因がわかれば投稿して頂くと大変助かります。その情報はODEの初心者にとって重要なものです。ある程度たまりましたらFAQに掲載したいと思いますのでご協力のほどよろしくお願いします。
新しい質問や要望はこちらにお願いします!
なお、私のコメントやご自分の努力により問題が解決 された場合に、問題の原因がわかれば投稿して頂くと大変助かります。その情報はODEの初心者にとって重要なものです。ある程度たまりましたらFAQに掲載したいと思いますのでご協力のほどよろしくお願いします。
コメント
でむさん
ぽったーです
なるほど理解できました.
お忙しいところ,ありがとうございました.
ポッターさん、
dParamFMaxが定数である必要はありません。ODEに付属しているdemoのコードでは変数になっていると思います。ODE本では速く位置制御したいので大きな定数の値にしています。
ポッターさんのご指摘のとおりdParamVelとdParamFMaxは拘束として与えられます。(角)速度も制約として入ってきているので単純なトルク制御にならないと考えます。しかも、dParamFMaxは最大発揮できるトルク(最大値)なのでトルク制御は難しいでしょう。
ジョイントに内臓されているモータは、dParamVelの角速度または速度になるように最大dParamFMaxのトルクまたは力を加える働きをします。なお、dParamVelとdParamFMaxはヒンジジョイントの場合が角速度とトルクで、スライダジョイントの場合が速度と力になります。
なお、詳細についは以下のサイトをご覧ください。
http://www.ode.org/joints.pdf
でむさん
ぽったーです.
たしかにODE本のp.32-33に書いてありますね.
よく読まずに質問していました.
お忙しいところ申し訳ありません.
dJointSetHingeParam()ですが,dParamFMaxが定数である必要はありますか?
これを毎回計算して与えるとトルク制御に...なりますか?
わたしがソースを読んだ感じでは,dParamVelとdParamFMaxは
どちらも内部のモータのリミッタとして与えられているような気がします.
ポッターさん、
おひさしぶり。
ODE本のP32,33ページに記載していますが、
dJointSetHingeParam() は速度制御、
dJointAddHingeTorque()はトルク制御
に使います。
なお、dJointAddHingeTorque()は以下のソースコードのように、ボディにトルクを加えているだけです。ODEはオープンソースなのでソースコードを読むことをお勧めします。
void dJointAddHingeTorque (dJointID j, dReal torque)
{
dxJointHinge* joint = (dxJointHinge*)j;
dVector3 axis;
if (joint->flags & dJOINT_REVERSE)
torque = -torque;
getAxis (joint,axis,joint->axis1);
axis[0] *= torque;
axis[1] *= torque;
axis[2] *= torque;
if (joint->node[0].body != 0)
dBodyAddTorque (joint->node[0].body, axis[0], axis[1], axis[2]);
if (joint->node[1].body != 0)
dBodyAddTorque(joint->node[1].body, -axis[0], -axis[1], -axis[2]);
}
でむ
でむさん.
ぽったーです.
ジョイントの制御に関する質問です.
でむさんのサンプルプログラムで,車輪のヒンジジョイントを制御する際に
dJointSetHingeParam()
を使用していると思います.
これと
dJointAddHingeTorque()
を使用するのとでは,何が異なるのですか?
お忙しい時期だと思いますが,よろしくお願いします.
お恥ずかしながら先ほどの質問はなかった事にしてください。
勘違いしていました。
自信のあるプログラムだっただけに原因が全くわからず質問してしまいました。
すみませんでした。(^^;)
もうひとつ「簡単!実践!ロボットシミュレーション」の内容で質問してもよろしいでしょうか?
P160の図6.15と図6.16なのですが、3自由度のアームロボットは間接が見えイメージがつかみやすいのですが、6自由度となるとどこが4自由度目の間接で、どこが5自由度目の間接なのかイメージがつかめません。
イメージ的には図6.13の先端(3自由度のアームロボットの先端)にボールジョイント(ボールジョイントは確か3自由度ですよね?)をハンドの間にはさんだものがここで言う6自由度のアームロボットだと理解してもよろしいでしょうか?
初心者さん、
恐れ入りますが、プチプロジェクトの具体的な回答はお答えしない方針です。ODEの技術的な質問に限定させてください。
答えを教えるとプチプロジェクトの意味がありませんからね。私の経験では考えに考え考え抜くと不思議にわかるものです。頑張ってくださいね。
でむ
チップさん、
どうもありがとうございます。
ODE本の説明がわかりづらかったのが原因ですね。
言い訳するとページ数が限られていたので丁寧に説明できなかったのです。
わかりづらい箇所があれば、どんどん聞いてください。
でむ
御返答ありがとうございます!
本家様を参考に頑張ってみたいとおもいます。
チップです。
>何が問題で関節中心点を取得できなかったか
GetHingeAnchorで取ってきた値を元に線を描写すると、どうもへんな場所に描写されていて、
(後から気がついたんですが、最初からヒンジの関節中心点の位置設定がおかしかったみたいです。)
それで、本当にGetHingeAnchorは関節中心点を取ってくる関数なのかと思って
本の説明を読んでみると、「ボディ1上での・・」と書かれていて、普通に読むとでむさんが言ったような意味に
とれるのですが、懐疑的に読んでしまったせいで(すいません)上が「座標的な意味での上」を指すのか、
「ボディ1において」の意味で使っているのかわからなくなってしまった次第です。ご迷惑おかけしました。
今P181のプチプロ6.1に取り組んでいます。
円の媒介変数を用いて、以下のプログラムを追加したのですが、(-0.25,0.00,1.50)の位置になってしまうだけで、円軌道を描きません。アドバイスやヒントをお願いします。
/*** 円を描く関数 ***/
void ring()
{
float r, th, dth,; //変数定義
dth = 0.01*M_PI; //角度の刻みに値代入
r = 0.25; //半径に値代入
P[1] = 0.0;
for(th = 0.0; th <= 2M_PI; th=th+dth ){ //theta が0 から2π まで
P[0] = r * cos(th);
P[2] = r * sin(th) + 1.5;
}
}
/*** キー入力関数 ***/
void command2(int cmd)
{
switch (cmd) {
case ‘1’: ANSWER = 1; break; // 1キーを押すと姿勢1
case ‘r’: ring(); break; // 円を描く関数ring()の実行
}
}
チップさん、
何が問題で関節中心点を取得できなかったか教えて頂けますか?
そこがわかりづらいポイントだと思いますので。
でむ
でむさん、ありがとうございます!
おかげで表示することが出来ました。
サンプルプログラムまで作っていただいて本当にありがたかったです。
へっぽこさん、
はじめまして。ご質問ありがとうございます。
ODEご本家様のHowtosにあるHOWTO integrate simulation and visualizationが参考になると思います。
http://opende.sourceforge.net/wiki/index.php/HOWTO_integrate_simulation_and_visualization
解決してもしなくても結果を教えて頂ければありがたいです。
でむ
はじめまして。
現在、先生の本とサイトを参考に二足歩行にチャレンジしております。
サンプルプログラム、kensei,legged,warusapを改良して現段階では
危なっかしいながらも直進歩行するところまで完成しました。
そこで質問なんですが、実行するとスピードにむらが出てしまうのです…
(左脚が早くスムーズに動いたと思えば、急に右脚はゆっくり動くといったような)
マシンの計算能力の問題でしょうか?それともプログラム中に問題があるのでしょうか?
ちなみに、サンプルプログラムはテクスチャOFFにすれば問題なく実行できます。
初心者のため何かいいヒントをいただけたら幸いです。よろしくお願いします。
チップさん、
ご質問ありがとうございます。
dJointGetHingeAnchorで関節の中心点を取得できます。
ODE本(p86)で dJointGetHingeAnchorの説明「ボディ1上でのヒンジの中心点」とは、ボディ1に対応するヒンジの中心点です。dJointGetHingeAnchor2はボディ2に対応するヒンジの中心点です。
ヒンジを生成したときは両者の中心点は一致していますが、シミュレーションを重ねる度にずれが生じます。それぞれを直すのがEFPパラメータです。
なお、ヒンジ中心点を取得するサンプルコードを以下に示すので参考にしてください。
const dReal *pos[BODY_NUM],*R[BODY_NUM];
dMatrix3 R1;
dVector3 ap[BODY_NUM-1]; // anchor point
float ar = 0.06; // anchor radius
// draw anchors
dsSetColorAlpha(0.0, 0.0, 1.3, 1.0);
for (int i = 0; i < BODY_NUM-1; i++) {
dJointGetHingeAnchor(joint[i], ap[i]);
dsDrawSphere(ap[i], R1, ar);
}
// draw lines
dsSetColorAlpha(1.3, 1.3, 1.3, 1.0);
for (int i = 0; i < BODY_NUM-1; i++) {
dsSetColorAlpha(1.3, 1.3, 1.3, 1.0);
dsDrawLine(pos[i], ap[i]);
dsSetColorAlpha(0.0, 0.0, 0.0, 1.0);
dsDrawLine(ap[i], pos[i+1]);
}
この前テクスチャの切り替えについて質問させていただいたチップです。
物体1と物体2をヒンジで結合させ、物体1から関節中心点を赤で、物体2から関節中心点を青で
dsDrawLineを用いて描写したいのですが、関節中心点の絶対座標が取得できません。
どうすればいいのでしょうか。
dJointGetHingeAnchorで出来るのかと思ったのですが、違ったようです。
ちなみに、ODE本(p86)で dJointGetHingeAnchorの説明を書かれていますが、その説明中の
「ボディ1上でのヒンジの中心点」とは一体何なのでしょうか。
すみませんがよろしくおねがいします。
初心者
でむさん、ありがとうございます。
そうですよね!その文を追加していたのですが、跳ねていまう。
摩擦係数を0.0に設定してもだめでした。
原因は何かと、ゆっくりシミュレーションを見たところ、いきなり飛び跳ねていることがわかり、boxの初期位置に初歩的なミスをしていることがわかりました。
box=1.0でdBodySetPosition(ball.body, x0, y0, z0);がこのような状態でした。
つまり、地面のなかにboxがある状態?
dBodySetPosition(ball.body, x0, y0, z0+0.5);にしたら解決しました。
お騒がせすみませんでした。
ありがとうございました!
初心者さん、
コメントありがとうございます。
摩擦係数を変えるには、ODE本の89ページにあるようにmuを変えます。
具体例としてはP44 プログラム2.9の20行目にある
contact[i].surface.mu = dInfinity;
を変更します。dInifinityを設定したい摩擦係数に変更してください。
これではうまくいかないのでしょうか?
でむ
でむさん
修正しました。
あと、dLoadMeshFromX関数にも手を加えて、メモリ動的確保の部分と
ポリゴンデータの頂点数&三角メッシュ数の取得をまとめて処理できる
ようにしました。
新しいdLoadMeshFromX関数の使い方はリンク先に書いてあります。
MyTrimesh構造体を使うのがミソです。
こんにちわ。
「ロボットシミュレーション」P35、EX2.2ですが、図2.1のようなプログラムを実行したところ、ジョイントが伸びるとともに真上に飛び跳ねてしまいました。
その時は、2つのboxの初期位置を地面から0.5[m]ほど上げると解決し、スライダージョイントの学習でしたのでそれでよしとしていました。
しかし、やはり気になり、boxと地面の摩擦抵抗が原因だと思いました。
そこで、P88~P90やODEのサンプルプログラム、test.cyl(斜面を立方体が滑り落ちるプログラム?)のプログラムのソースコードを参考にしたのですが、なかなかうまくはいきません。
地面との摩擦抵抗を変えるにはどうすればよいでしょうか。
ひびきのさん、
ごくろうさま。
ソースコードを読みましたが、質量設定やトライメッシュに対するsimLoopの処理が不完全です。demo_moving_trimesh.cppやODE講座22のソースを参考にしてください。
ODE本のトライメッシュに関するサンプルプログラムはODE-0.6の頃作成したので古くなっています。そのころと比較してトライメッシュの処理は劇的に良くなっています。
でむさん
出来ましたよ。
VertexCountとIndexCountを取得する関数を作って、
VerticesとIndicesをそれぞれmallocで動的メモリ確保するようにしました。
リンク先にソース(と説明)を置いています。
レスありがとうございます。
ジオメトリだけの場合で移動は毎フレームSetPosition()で指定すると
壁などですり抜けてしまうので何かいい方法はないかな、と思い質問させてもらいました。
ちなみに地形データはTriMeshで生成しています。
ちょっと余白部分が大きくなりますが一応球でそれっぽく見せられそうです。
Rainlilyさん、
はじめまして、
ODEはゲームの用途にはぴったりですね。
私はゲームをあまり作ったことがないのですが、キャラクタがマップを移動するときに動力学計算する必要はあまりないので、物体にボディを設定しないで、ジオメトリだけを設定するのではだめですか?
でむ
ひびきのさん、
X Fileのローダーですが、 VerticesとIndicesの数をいちいち人間が入力するのは手間がかかるので、自動にできませんか。ひびきのさんの実力ならそんなに難しくないでしょう。
でむ
はじめまして、ゲームに利用しようとODEを触っています。
マップ上をキャラが歩くような処理をする時に、直立しているキャラをカプセルとして扱おうと思っているのですが、
通常の使い方では当然ですがカプセルは地面にそって倒れてしまいます。
重力を3軸とも0に設定しても坂のような場所では当然倒れてしまいます。
ジョイントで固定した状態でdBodySetLinearVel()を使って移動をしても
ジョイントした位置と移動後の位置をいったりきたりしてうまくいきませんでした。
回転軸が固定された移動のみの剛体として使う事はできないのでしょうか?
でむさん
出来ました!
アドバイスありがとうございました。
ひびきのさん、
返事が遅くなりすみません。Xファイルのローダーいいですね。
さて、AIBOシミュレータではポリゴンは描画にだけ使い、衝突計算はそれをボックス、シリンダ、球などで近似したものを使いました。
LCP Internal Errorを回避するにはstep sizeを小さくしたり、CFMやERPの値を変更したり、物体同士が深くめり込まないようにdWorldSetContactSurfaceLayer(world, depth)を呼び出します。このときdepthはめり込む最大の深さなので小さくします。
また、ひびきのさんのサンプルプログラムを試したところ、摩擦係数muを以下のように無限大にするとエラーが回避できました。試してください。
contact[i].surface.mu = dInfinity;
でむ
でむさんの言うとおり最新のバージョンにしたら実行できました。
ありがとうございました。
チップさん,
ヘッダファイルを変更した後に,
ODE自体をmake, make installし直しする必要があります.
また,ODE0.9でしょうか?
でむ
でむさん、回答ありがとうございます!
なるほど、描写の関数を呼び出さないと再描写されないんですね。
さっそくヘッダファイルに
DS_API void dsStartGraphics (int window_width, int window_height, struct dsFunctions *fn);
を追加してやってみたのですが、なぜかmake時にエラーが出ます。
undefined reference to `dsStartGraphics’
といわれ、また悩んでいる状況です、何が悪いのでしょうか。
MINGでやっております。
でむ さん
お久しぶりです。
DirectX用ポリゴンデータ(拡張子.x)をDrawstuffで表示するプログラムを作ったのですが、
LCP internal error が止まりません。地面と衝突したときの挙動もおかしいです。
ODEのデモ「demo_moving_trimesh」や、でむさんのAIBOシミュレータは、こういったエラー
無しで動いているように見えますが、何かコツがあるのですか?
ソースとバイナリデータはリンク先に置いてあります。
チップさん
はじめまして。
さて、simloopの中でpath_to_texturesのパスを変えてもテクスチャは変わりません。
dsStartGraphics()を使ってください。ただし、drawstuff.hの95行目のdsSimulationLoop()の下に以下の一行を追加して、ode-0.9でmakeし直してください。
DS_API void dsStartGraphics(int window_width, int window_height, struct dsFunctions *fn);
キー操作によるテクスチャ切り替えのサンプルを以下に紹介します。
void command(int cmd)
{
switch (cmd) {
case ‘t’:
fn.path_to_textures = “./textures”;
dsStartGraphics(640,480,&fn);
break;
case ‘u’:
fn.path_to_textures = “../../drawstuff/textures”;
dsStartGraphics(640,480,&fn);
break;
}
}
以上です。
でむ
はじめまして、本とサイトを見て勉強させてもらっています。
プログラムに関する質問なのですが、テクスチャをたくさん使うにはどうすればいいのでしょうか?
LOOPの中でfn.path_to_texturesのパスを変えてもテクスチャが変わらなくて悩んでいます。
よろしくおねがいします。
でむさん、
回答していただき、ありがとうございます。
参考にしてがんばってみます。
今後も、何かありましたらよろしくお願いします。
何度もすいません、でむさん
あれから試行錯誤を繰り返した結果
dRFromEulerAnglesを用いてみたら
できました。
位置座標もきちんとそれのような値をとっていたので
たぶんこれでいいと思います。
自分から相談しといてこのような結末になりまして本当にすいません。
サンプルコードまで書いてもらうなんて、大変うれしい限りです。
一応自分が書いたコード(角度計算)を載せるので
間違いなどを指摘してもらえたら幸いです。
//角度計算
static void radian(dReal fx, dReal fy, dReal fz)
{
radianyz=atan(fz/fy);
radianxy=atan(fx/sqrt(fz*fz+fy*fy));
}
//オイラー角の設定
dMatrix3 R1;
dRFromEulerAngles(R1, M_PI/2-radianyz, -radianxy, 0);
dBodySetRotation(pole.body, R1);
こんな感じになりました。
自分がやろうとしていたのは
ベクトル(fx、fy、fz)の方向にカプセル型のボディ(pole.body)を
向けさそうとしたものです。
これを用いてODEに弓矢の矢の軌道をシミュレーションさせようというプログラムを
自分は作っています。なんとか完成は間に合いそうです。
長文ですいません。このページはプログラムを作るうえで大変役立ちました。
親身に相談にのっていただき本当にありがとうございました。
ryupioneer
ryupioneerさん、
ご質問があるということは、ODE本の説明ではわかりづらいということですね。
任意の姿勢に向けることができます。具体的に、どの姿勢にしたいかを教えてください。その姿勢を向けるサンプルコードを書いてみます。
でむ
迅速なご返答ありがとうございました。
ただdRFromAxisAndAngleやdRFromEulerAnglesで何度も試しているのですが
うまくいきません。
一回の回転はできるのですが
複数回の回転ができません。
dRFromAxisAndAngleで設定できるのは
一つの回転命令だけなのでしょうか
やはり物体を中途半端な位置へ向けるのは
ODEでは無理なのでしょうか
何度もすいませんがよろしくお願いします
Shioさん、
ODEの世界へようこそ!
さて、試していませんが、物体から空洞部分をくりぬくのではなく、複数の物体で空洞を囲むように実装すればできると思います。
もし、実現できたら差し支えない範囲でご連絡をお願いします。
でむ
ryupioneerさん、
お急ぎのところ返事が遅れてすみません。韓国で開催されたRobot World 2007でヒューマノイドロボットのデモ展示のため出張で本日帰国しました。
さて、dRFromAxisAndAngle()で向けたい姿勢の回転行列を取得し、dBodySetPosition()でその姿勢にbodyを設定してください。ODE本のP75 プログラム3.3が参考になると思います。
でむ
はじめまして
理系学校で展示物の作成に
ODEをつかったソフトを開発しているのですが
ODEの初期姿勢で行き詰ったので質問させていただきます。
あるベクトル(x、y、z)があたえられていて
それと同じ方向に物体の姿勢を向けたいのですが
うまくいきません。
勉強不足だと思いますが、日数も残り少ないので
よろしくお願いします。
はじめまして。Shioと申します。
最近ODEを始めまして、参考書やこちらのサイトを参考にして学習しております。
ところで質問なのですが。
物体の内部に空洞を作って、その空洞の中に物体を入れるということはできるのでしょうか?
よろしくお願いします。
でむさん
ぽったーです
ode-0.9がリリースされましたね.
さっそくインストールしてみたのですが,demura.netで紹介されている
新しいデモのdemo_basket.exeを起動しても,Errorがでてしまいます.
環境は,windows xpでmingwとmsysです.
Errorは
could not load accelerators
です.
なにかインストールで不備があったのでしょうか?
よろしくお願いします.
mif805さん、
nearCallbackをざっと見たところ特に問題はなさそうですね。挙動を確認したいので差し支えなければhttp://demura.net/archives/4profile/mail.htmlのメールアドレスへソースコードを送っていただけませんか?
でむ
demuraさん、
わかりやすい説明ありがとうございました。大変助かりました。
でむさん、
できました!!
毎度、本当にありがとうございます!!
いろいろな形を試してみたいと思います。
takさん、
ご質問ありがとうございます。お久しぶりですね。
さて、ODEの特徴として、物体にはジオメトリとボディの属性があり、ジオメトリは衝突検出計算、ボディは動力学計算の対象となります。この特徴をうまくつかうと効率的なシミュレーションをすることができます。
例えば、自律移動ロボットが市街地を走行するシミュレーションをする場合、ビルなどは全く動かないものとして扱い、ロボットとの衝突だけを考慮するだけで良いと思います。そのような場合では、そのビルをジオメトリだけで定義することにより、特に必要のないビルに対する動力学計算を省略することができます。動力学計算を受けていないのでビルは当然動きません。
なお、ジャンプ台にボディを定義しても、boxが地面に沈まない方法もあります。それは、fixedジョイントをそのboxと静的(static)オブジェクトと結合すればOKです。静的オブジェクトのボディIDには0を設定してください。
以上です。
でむ
demuraさん
お久しぶりです、以前MacOSXへのインストールや物体が地面の上を滑ってしまう現象について質問させていただいたtakです。
今回はodeに付属のサンプルtest_buggyについてです。
斜面を作ろうとしたのですが、odeには三角形のオブジェクトがないので困っていた所、
test_buggyに三角形のジャンプ台の用なものがあったのを思い出しソースを眺めていたのですが、
boxを斜めにして地面にめり込ませるという方法をとっていました。
しかしこのジャンプ台はなぜかジオメトリ(geom)のみで定義されており、ボディ(body)は定義されてませんでした。
逆のパターンはODE講座5で見たので性質が分かっていたのですが、ジオメトリのみ定義された
オブジェクトの性質がいまいちつかみきれません。
実際にジャンプ台にボディを定義してみると(自前のソースに移植)、ジャンプ台となるはずのboxは地面に沈んでいってしまいます(当然ですが)。
そこで質問なのですが、ジオメトリのみで定義されたオブジェクトはどのような利点があるのでしょうか?
またなぜこのオブジェクトは最後まで沈まず途中で止まるのでしょうか?
ひょっとして講座のどこかで述べられていましたら申し訳ありません。