Hatena::ブログ(Diary)

urekatのスカンク日記3 このページをアンテナに追加 RSSフィード

2007-06-22

[][]rubyで3D物理シミュレーション

rubyからODEを使えるようになったのでとりあえずうp。

http://ssktkr.com/ode-ruby5.tgz

D


こんなソースで3Dシミュレーションできます!

require "ode"
require "draw_stuff"
require "pp"
require "dl"

$world = Ode::World.new
$world.gravity = [0.0, 0.0, -0.2]                            # 重力設定
$space        = Ode_lib.dHashSpaceCreate(nil);               # 衝突用空間の創造
$contactgroup = Ode_lib.dJointGroupCreate(0);                # ジョイントグループの生成
$ground       = Ode_lib.dCreatePlane($space, 0,0, 1.0, 0.0); # 平面ジオメトリの生成

def rand_within(from, to)
  rand*(to-from)+from
end

$objects = []
100.times{
  $objects << Ode::Material::Ball.new(:m=>rand_within(1,9),
                                      :r=>rand_within(1,5),
                                      :position=>[rand_within(-7,7), rand_within(-7,7), rand_within(5,500)],
                                      :color=>[rand(2).to_f, rand(2).to_f, rand(2).to_f] )
}
$objects << Ode::Material::Box.new(:m=>1000.0,
                                   :x=>10.0, :y=>50.0, :z=>50.0,
                                   :position=> [-30.0, 0.0, 30.0],
                                   :color   => [0.3, 0.0, 0.0] )

ds = DrawStuff.new
ds.world  = $world
ds.width  = 800
ds.height = 600
ds.path_to_textures = "../drawstuff/textures"
def ds.start
  puts "start"
  xyz = [  50.0,   0.0,   1.0] # 視点の位置
  hpr = [-180.0,  20.0,   0.0] # 視線の方向
  DrawStuff::DSLib.dsSetViewpoint(xyz.to_ptr("F"), hpr.to_ptr("F")) # カメラの設定
end

def ds.step(pause)
  @step_count += 1
  if @step_count%5000==0
    puts "=============================================="
    puts "step #{pause} #{@step_count}"
    xyz = [0.0, 0.0, 0.0].to_ptr("F") # 視点の位置
    hpr = [0.0, 0.0, 0.0].to_ptr("F") # 視線の方向
    DrawStuff::DSLib.dsGetViewpoint(xyz, hpr)
    puts "xyz = " + xyz.to_a("F").inspect
    puts "hpr = " + hpr.to_a("F").inspect
  end

  Ode_lib.dSpaceCollide($space, Proc.new{|o1,o2|
#    puts "cb #{o1._ptr} #{o2._ptr} #{$ground._ptr} #{$ground._ptr==o1._ptr} #{$ground._ptr==o2._ptr}"
    # 衝突検出
    #if $ground._ptr==o1._ptr || $ground._ptr==o2._ptr
      contact_geoms = Ode_lib.dCollide(o1, o2, 10000) # 衝突情報の生成
      contact_geoms.each do |cg|
        # pp cg
        contact = Ode_lib::DContact.new
        contact.geom = cg
        contact.surface.mode       = Ode_lib::DContactBounce; # 接触面の反発性を設定
        contact.surface.bounce     = 0.8;            # 反発係数(0.0から1.0)
        contact.surface.bounce_vel = 1.0;            # 反発に必要な最低速度
        # 接触ジョイントの生成
        joint = Ode_lib.dJointCreateContact($world._id, $contactgroup, contact)
        # 接触している2つの剛体を接触ジョイントにより拘束
        Ode_lib.dJointAttach(joint, Ode_lib.dGeomGetBody(cg.g1), Ode_lib.dGeomGetBody(cg.g2))
      end
    #end
  });

  @world.step(0.05)
  Ode_lib.dJointGroupEmpty($contactgroup); # ジョイントグループを空にする
  $objects.each{|o| o.draw }
end

def ds.command(cmd)
  puts "command #{cmd}"
end

def ds.stop
  puts "stop"
end

ds.run

今回学んだ技術:

- SWIG

- Ruby/DL

- Ruby拡張ライブラリの作り方

- Rubyの中身を少々(Ruby Hacking Guideを読んだ)

- ODE この本がすごい!

簡単!実践!ロボットシミュレーション - Open Dynamics Engineによるロボットプログラミング

簡単!実践!ロボットシミュレーション - Open Dynamics Engineによるロボットプログラミング



Wiiリモコンと組み合わせたら絶対たのしい。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト

コメントを書くには、なぞなぞ認証に回答する必要があります。

トラックバック - http://d.hatena.ne.jp/urekat/20070622/1182484745