22
Maple/MapleSimを用いた 教育のための物理シミュレーション 大阪工業大学工学部 電気電子システム工学科 講師 田熊 隆史

Maple/MapleSimを用いた 教育のための物理シミュ …...Maple/MapleSimを用いた 教育のための物理シミュレーション 大阪工業大学工学部 電気電子システム工学科講師

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Maple/MapleSimを用いた

教育のための物理シミュレーション

大阪工業大学工学部

電気電子システム工学科 講師

田熊 隆史

概要自己紹介

本学科(電気系)におけるコンピュータリテラシ,プログラムのカリキュラム

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 ∂∂

−⎟⎟⎠

⎞⎜⎜⎝

⎛∂∂

∂∂

=&

τ

↑ここの偏微分に難儀しました

大阪工業大学工学部電気電子システム工学科におけるプログラミング授業

1年生配当(2コマ連続授業)

2年生配当

週1コマ15回授業に換算すると,だいたい1年分ぐらいの授業量

結果,四年生(三年生後期)研究室配属時

制御文(if, while…)は理解できる

• サンプルは読めるが,使いこなすまでにはなっていない

サブルーチンはかろうじて分かる(習った記憶がある)• 何のためにサブルーチンを設けるかは分からない

変数の扱いは分からない• グローバルとローカル変数,intとdoubleの違いが混同

• 配列はなんとか知っている(理解はしていない)構造体,クラスは習っていない

• 自力で学習可能な学生もいる

• 説明しても理解できない学生もいる

3年次の学習目標

電気系として,モータ駆動,発電器といった電機システム(電気・電子回路+機械)は実験を通し

て修得しておきたい

大学に実機(倒立振子)はあるが,,,

装置の使い方を説明するのに時間がかかってしまう

システム構成(重心位置など)の変更が難しい

• パラメタチューニングの難しさを知って欲しいので,「当たり」のパラメタ値(フィードバックゲインなど)を後発の学生に漏らさないよう工夫が必要

• 正確な物理パラメタが分からなくなる(答え合わせしにくい)

できるだけ早く実験の核心にたどり着きたい

シミュレーションの活用

物理パラメタの変更が比較的容易.しかし・・・

C言語など,プログラミング言語を用いたシミュレーションは(特に授業についていくのがやっとの学生に対して)導入困難

電気・電子回路と物理システム(力学)両方ともを扱えるシミュレータがあまり無い

SPICE : 電子回路シミュレータ

ODE : 物理シミュレータ(物理エンジン)

dSPACE:自動車用シミュレータ

simulink:両方を扱えるが高価

Maple / MapleSimの活用!

直感的なシミュレータ構成倒立振子を例に

ODE(物理エンジン)+C言語 MapleSim

ブロック数:3,関節:1

直感的なシミュレータ構成

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);

}

ブロック・関節が増えるごとに複雑化

電気-機械系複合シミュレーション

サイバネットシステム セミナー資料より

熱伝導率

熱容量

電気回路,機械システムに加えて熱も扱える

将来は回路の損失もシミュレートできる?

電気電子システム実験(3年次配当)におけるMaple/MapleSimの活用

電気電子システム実験bc

実験概要ACサーボモータ(一次系)のステップ応答観察

速度フィードバックの系(二次系)から適切なゲインを計算し,収束を確認

倒立振子による速度フィードバック制御

構成人数教員一名,TA(大学院生)一名

学生8~10名

実験期間3コマ(木曜2,3,4限)

実験詳細実験1

サーボモータ( 1次系)のステップ応答

• 時定数と定常状態のゲインを求める

実験詳細

実験2サーボモータの速度フィードバック

• 系全体の特性(ζ,ω)は既知として,適切なフィードバック係数を求める

• 目標角度に収束することを確認する

実験詳細実験3

倒立振子の制御• 速度フィードバックにより制御

今後の学生実験に向けて

ロボットアームの制御

モータで駆動する二関節機構ロボットアームの作成

モータの位置制御• センサでの角度・各速度獲得 ゲイン倍して速度制御

逆運動学を用いた手先軌道追従問題

• 説明が煩雑になりそうなときは,ブラックボックスを用意しておくのも良い(必要なものだけ見せる,触らせる)

柔軟リンクを有するアームの制御• 単純な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が生かせない

高い自由度が求められるものについては,プログラム言語が優勢?

まとめ

Maple/MapleSimの導入にあたりC言語の知識が乏しい学生には適切な素材

リンクや関節機構などが直感的に理解できる

ただし・・・時間をかければC言語の取得(C言語ベースのシミュレーション)は可能

研究のレベルまで持ち込もうとすると,汎用性の低さやマニュアル不足がネックになる