Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
概要自己紹介
本学科(電気系)におけるコンピュータリテラシ,プログラムのカリキュラム
C言語の講義時間
本学3年次のC言語のスキル
電気電子システム実験(3年次配当)におけるMaple/MapleSimの活用
倒立振子の制御
卒業研究におけるMaple/MapleSimの活用
ロボティクス研究室での活用物理エンジンODEとの比較
講演者のMaple歴+シミュレーション歴
修士課程(1999.4-2001.3)ロボットの運動方程式をラグランジュ法で導出するために,Mapleを使用
大阪工業大学教員(2008.4-)ロボットのシミュレーションとしてODE(Open Dynamics Engine)+C言語を
使用
• 基本的にロボットを作って実世界で実験することが多い
授業での導入にあたり,Maple / MapleSimを評価(1年間)
卒業研究のために使用
• 体幹付き四脚ロボットの不整地踏破
• 学生の方が詳しいです.
qL
qL
t ∂∂
−⎟⎟⎠
⎞⎜⎜⎝
⎛∂∂
∂∂
=&
τ
↑ここの偏微分に難儀しました
結果,四年生(三年生後期)研究室配属時
制御文(if, while…)は理解できる
• サンプルは読めるが,使いこなすまでにはなっていない
サブルーチンはかろうじて分かる(習った記憶がある)• 何のためにサブルーチンを設けるかは分からない
変数の扱いは分からない• グローバルとローカル変数,intとdoubleの違いが混同
• 配列はなんとか知っている(理解はしていない)構造体,クラスは習っていない
• 自力で学習可能な学生もいる
• 説明しても理解できない学生もいる
3年次の学習目標
電気系として,モータ駆動,発電器といった電機システム(電気・電子回路+機械)は実験を通し
て修得しておきたい
大学に実機(倒立振子)はあるが,,,
装置の使い方を説明するのに時間がかかってしまう
システム構成(重心位置など)の変更が難しい
• パラメタチューニングの難しさを知って欲しいので,「当たり」のパラメタ値(フィードバックゲインなど)を後発の学生に漏らさないよう工夫が必要
• 正確な物理パラメタが分からなくなる(答え合わせしにくい)
できるだけ早く実験の核心にたどり着きたい
シミュレーションの活用
物理パラメタの変更が比較的容易.しかし・・・
C言語など,プログラミング言語を用いたシミュレーションは(特に授業についていくのがやっとの学生に対して)導入困難
電気・電子回路と物理システム(力学)両方ともを扱えるシミュレータがあまり無い
SPICE : 電子回路シミュレータ
ODE : 物理シミュレータ(物理エンジン)
dSPACE:自動車用シミュレータ
simulink:両方を扱えるが高価
Maple / MapleSimの活用!
直感的なシミュレータ構成
ODE(Cプログラム) MapleSimによる構成
初めて見ても(だいたい)分かる
#include <stdio.h>#include <ode/ode.h>#include <drawstuff/drawstuff.h>
#ifdef dDOUBLE
#ifdef _MSC_VER#pragma warning(disable:4244
4305) // for VC++, no precision loss complaints
#endif
#define dsDrawCapsule dsDrawCapsuleD
#define dsDrawBox dsDrawBoxD#define dsDrawLine dsDrawLineD#endif
dWorldID world; // 動⼒学計算⽤のワールド(for dynamics)
dSpaceID space; // 衝突検出⽤のスペース(for collision)
dGeomID ground; // 地⾯(ground)
dJointGroupID contactgroup; // 接触点グループ(contact group for collision)
dsFunctions fn; // ドロースタッフの描画関数(function of drawstuff)
typedef struct {dBodyID body;dGeomID geom;dReal m,x,y,z; // 質量(weight),
位置(positin:x,y,z)} MyLink;
MyLink base, arm, load;
// box sizedouble base_d, base_w, base_h,
arm_d, arm_w, arm_h, load_d, load_w, load_h;
dJointID joint, FixJoint;double JointPos[3]; // [][x/y/z]
// sub routinesvoid Initialize(void);
void SetParameters(void){
base_d = 1.0; base_w = 0.5; base_h = 0.1;arm_d = 0.1; arm_w = 0.1; arm_h = 1.0;load_d = 0.2; load_w = 0.2; load_h = 0.2;
base.x = 0.0; base.y = 0.0; base.z = 0.5*base_h+0.01;arm.x = 0.0; arm.y = 0.0; arm.z = base_h+0.5*arm_h+0.01;load.x = 0.0; load.y = 0.0; load.z = base_h+arm_h+0.5*load_h+0.01;
base.m = 100.0;arm.m = 1.0;load.m = 10.0;
JointPos[0] = 0.0; JointPos[1] = 0.0; JointPos[2] = base_h+0.01;
}
static void nearCallback(void *data, dGeomID o1, dGeomID o2) {int isGround = ((ground == o1) || (ground == o2));
dBodyID b1 = dGeomGetBody(o1), b2 = dGeomGetBody(o2);// if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact)) return;
// if ((o1 != ground) && (o2 != ground)) return;
static const int N = 20;dContact contact[N];int n = dCollide(o1,o2,N,&contact[0].geom,sizeof(dContact));
// if (n > 0) {if(isGround){for (int i=0; i<n; i++) {
contact[i].surface.mode = dContactSoftERP | dContactSoftCFM;contact[i].surface.mu = dInfinity; //2.0;contact[i].surface.soft_erp = 0.9;contact[i].surface.soft_cfm = 1e-5;dJointID c = dJointCreateContact(world,contactgroup,&contact[i]);dJointAttach(c,b1,b2);
}}
}void start(){
float xyz[3] = {2.5,2.5,0.5} ;//{ 1.0f, -1.2f, 0.5f}; // 視点[m] (View point)float hpr[3] = {285.0,10.0,0.0}; // 視線[°] (View direction)//float hpr[3] = {121.0f, -10.0f, 0.0f}; // 視線[°] (View direction)
dsSetViewpoint(xyz,hpr); // 視点と視線の設定(Set View point and direction)dsSetSphereQuality(3);dsSetCapsuleQuality(6);
}
void simLoop(int pause){
int result;result = balancing();dSpaceCollide(space,0,&nearCallback); // 衝突検出(collision detection)dWorldStep(world, 0.01); // ステップ更新(step a simulation)dJointGroupEmpty(contactgroup); // 接触点グループを空(empty jointgroup)
drawRobot(); // ロボットの描画(draw a robot)}
void SetDrawStuff() {fn.version = DS_VERSION;fn.start = &start;fn.step = &simLoop;fn.command = NULL;fn.path_to_textures = "../../../../drawstuff/textures";
}
void Initialize(void){// ODE環境作成
// dInitODE();dInitODE2( 0 );dAllocateODEDataForThread( dAllocateMaskAll );world = dWorldCreate();space = dHashSpaceCreate(0);contactgroup = dJointGroupCreate(0);ground = dCreatePlane(space,0,0,1,0);
// dWorldSetGravity(world, 0, 0, -9.8);dWorldSetGravity(world, .0, .0, .0);dWorldSetCFM(world, 1e-5); // CFMの設定(global CFM)dWorldSetERP(world, 0.9); // ERPの設定(global ERP)
}
int main(int argc, char *argv[]){
SetDrawStuff();Initialize();makeRobot();dsSimulationLoop (argc,argv,800,480,&fn);dSpaceDestroy(space);dWorldDestroy(world);dCloseODE();return 0;
}
void makeRobot(void){dMass mass;
SetParameters();
base.body = dBodyCreate(world);dMassSetZero(&mass);dMassSetBoxTotal(&mass, base.m, base_d, base_w, base_h);dBodySetMass(base.body, &mass);dBodySetPosition(base.body, base.x, base.y, base.z);base.geom = dCreateBox(space, base_d, base_w, base_h);dGeomSetBody(base.geom, base.body);
arm.body = dBodyCreate(world);dMassSetZero(&mass);dMassSetBoxTotal(&mass, arm.m, arm_d, arm_w, arm_h);dBodySetMass(arm.body, &mass);dBodySetPosition(arm.body, arm.x, arm.y, arm.z);arm.geom = dCreateBox(space, arm_d, arm_w, arm_h);dGeomSetBody(arm.geom, arm.body);
load.body = dBodyCreate(world);dMassSetZero(&mass);dMassSetBoxTotal(&mass, load.m, load_d, load_w, load_h);dBodySetMass(load.body, &mass);dBodySetPosition(load.body, load.x, load.y, load.z);load.geom = dCreateBox(space, load_d, load_w, load_h);dGeomSetBody(load.geom, load.body);
FixJoint = dJointCreateFixed(world, 0);dJointAttach(FixJoint, arm.body, load.body);dJointSetFixed(FixJoint);
joint = dJointCreateHinge(world, 0);dJointAttach(joint, base.body, arm.body);dJointSetHingeAnchor(joint, JointPos[0], JointPos[1], JointPos[2]);dJointSetHingeAxis(joint, 0, 1, 0);
}
void JointControl(void){dJointAddHingeTorque(joint, 0.0);
}
int balancing(void){JointControl();
return 0;}
void drawRobot(void){
double sides[3];
dsSetColor(1.0, .0, .0);sides[0] = base_d;sides[1] = base_w;sides[2] = base_h;dsDrawBox(dBodyGetPosition(base.body), dBodyGetRotation(base.body), sides);
dsSetColor(0.0,0.0,1.0);sides[0] = arm_d;sides[1] = arm_w;sides[2] = arm_h;dsDrawBox(dBodyGetPosition(arm.body), dBodyGetRotation(arm.body), sides);
dsSetColor(0.0,1.0,0.0);sides[0] = load_d;sides[1] = load_w;sides[2] = load_h;dsDrawBox(dBodyGetPosition(load.body), dBodyGetRotation(load.body), sides);
}
ブロック・関節が増えるごとに複雑化
電気電子システム実験bc
実験概要ACサーボモータ(一次系)のステップ応答観察
速度フィードバックの系(二次系)から適切なゲインを計算し,収束を確認
倒立振子による速度フィードバック制御
構成人数教員一名,TA(大学院生)一名
学生8~10名
実験期間3コマ(木曜2,3,4限)
今後の学生実験に向けて
ロボットアームの制御
モータで駆動する二関節機構ロボットアームの作成
モータの位置制御• センサでの角度・各速度獲得 ゲイン倍して速度制御
逆運動学を用いた手先軌道追従問題
• 説明が煩雑になりそうなときは,ブラックボックスを用意しておくのも良い(必要なものだけ見せる,触らせる)
柔軟リンクを有するアームの制御• 単純なPID制御では制御しきれない対象を簡単に用意
• 制御工学への動機付け
物理エンジンODE(Open Dynamics Engine)
物体(剛体)の挙動を計算
API関数を提供し,プラットフォームを選ばない
ブロック,カプセル,球などの剛体
ブロック-ブロック間を繋げる関節
衝突・接触時の挙動を自動で計算(手動計算も可能)
WindowsだけでなくLinuxにも対応
無料
全世界にユーザ(=ウェブページでのプログラム公開)
Maple/MapleSimとODEの比較
プログラム(C言語)の知識
必要
可(回路のダイナミクスを式で記述できれば可能だが,やや難)
可能(容易)電気回路との結合
充実(次スライド)少ない(ほぼヘルプのみ)マニュアル
汎用性を意識した設計コンポーネントやMapleのルールに依存
自由度(後述)
プログラム経験なしでも
OK難易度
コマンド(CUI)グラフィック(GUI)インタフェース
ODEMaple/MapleSim
四年次 卒業研究での活用
ODE+C言語によるシミュレーション
C言語で物理エンジンODEを呼び出し,配置したブ
ロック(リンク機構)の運動を計算させる
• ユーザはブロックの配置,関節にかける力の指定のみ
• 本学科学生のC言語のスキルはそれほど高くない・・・が,
ODEに関する良書がある
• 書籍を元に,自力でプログラム構築可能
研究室内のコンテストの結果• 製作期間:1ヶ月(実質1週間?)
ODEの自由度
汎用性:様々なデバイスとの組み合わせが可能
モーションキャプチャ,AD/DAボード・・・
モデルが自在に設計可能
粘弾性を持つアクチュエータを使いたい!等
Mapleでは用意されたコンポーネントしか使えない
• Mapleのカスタムコンポーネント(CUIベースのコマンド入力)にしてしまうと,せっかくのGUIが生かせない
高い自由度が求められるものについては,プログラム言語が優勢?