2018年7月5日木曜日
pyode ボール 直方体以外のバウンドのおかしなところ
ボール 直方体以外のバウンドのおかしなところ
self.v_box = box( pos=pos, width=w, height=h, length=l)
とvisualのboxを設定しても、物理シュミレーションをupdateすると
def update(self):
pos = self.geom.getPosition()
mat = self.geom.getRotation()
self.v_box.pos = pos
self.v_box.axis = mat[0], mat[3], mat[6]
self.v_box.up = mat[1], mat[4], mat[7]
の
self.v_box.axis = mat[0], mat[3], mat[6]
self.v_box.up = mat[1], mat[4], mat[7]
を拾ってきて、寸法がおかしくなり、その方向も90度おかしい。
何か物理シュミレーション用に変更されているみたいだ。
物理シュミレーションするなら(バウンドなど)ボール 直方体以外は
してはおかしなシュミレーションになる。
つまり、物体の大きさ、方向が変わってしまう。
しかし、その表現された物体としてはまあまあのシュミレーションがされる。
物体の大きさ、方向を保つなら上の2行をupdateから削除し
posだけupdateしたらよい。つまりpyodeのジョイント、モータなどをつかうだけなら
このほうがいい。
以下画像は左が下の2行を削除したもの。 vpython的にはboxは正確に表現されている。
上が2行を残したもの。 vpythonの寸法、方向はおかしいが pyodeの落下シュミレーション
を実現している。
boxが全然ちがうものになっている。
K:\MyBackups\goolgedrive\myprg_main\python_my_prg\vpython\zahyou_kakunin_cylinder.py
# coding: UTF-8
#https://www10.atwiki.jp/bambooflow/pages/242.html
#スライダーでスプリングダンパーモデル
#上サイトを参考に、pyode + vpython でやってみる
#上ボールが固定されていて、下ボールがスライダージョイントで
#接続されている
#キーのmで下ボールが下がり、バネの動作で何回か上下に振動す
#る。
#元サイトのように連続で振動しなかった。
#重力0で実行、重力をかけるとさらに振動しなくなる
import ode
from visual import *
boxList = []
ballList = []
class Field:
"""
scene = display(forward=visual.norm((-2.0,-1.0,-1.0)))
ベクトル:forward はカメラが見ている方向と同じ向きを指します。
(すなわち、scene.mouse.camera で与えられる現在のカメラ位置から scene.center へ向かう方向です
<http://www.nasuinfo.or.jp/FreeSpace/kenji/sf/visualj/display.html>
norm( vector )
vector オブジェクトから長さ 1 の vector オブジェクトを生成して返します
"""
scene = display(forward=norm((-0.05,-0.3,-1.0)),
range=(7,7,7), autoscale=0
)
#物理世界を作成
world=ode.World()
world.setGravity((0, -9.81, 0))
#自由落下させたいなら worldのコメントアウトのほうを生かし
# 最後の方の ball.body.addForce((0,-1000,0)) を殺す
#world.setGravity((0, 0, 0))
#地平面を作成?
space=ode.Space()
#座標確認用
ball = sphere(pos=(5,0,0), radius=0.2, color=color.red)
ball = sphere(pos=(0,5,0), radius=0.2, color=color.yellow)
ball = sphere(pos=(0,0,5), radius=0.2, color=color.blue)
ball = sphere(pos=(0,0,0), radius=0.2, color=color.white)
#衝突関係
jointgroup=ode.JointGroup()
ode_floor=ode.GeomPlane(space,(0,1,0),0)
#()なかの引数 上の例ではy軸方向に重力が発生
#多分 spaceの最後の引数が y軸の座標を示す
#ode_floor.setCategoryBits(5)
#ode_floor.setCollideBits(5)
ode_floor.viz=box(
pos=(0,-0.03,0),
width=10,length=10,height=0.06,color=(0.5,0.5,1.0))
target_fps=30
#target_fps=30だから1秒間に30回の処理をする
dt=1.0/target_fps
def near_callback(self,args,geom1,geom2):
for c in ode.collide(geom1,geom2):
#接触ジョイント (Contact joint)
#mu 摩擦係数 (摩擦方向1) mu2 摩擦係数 (摩擦方向2)
#bounce 反発係数
c.setBounce(0.8)
c.setMu(50)
c.setMu2(50)
j=ode.ContactJoint(self.world,self.jointgroup,c)
j.attach(geom1.getBody(),geom2.getBody())
def tick(self):
cyl.update()
ball1.update()
ball2.update()
box.update()
#time.sleep(0.23)
self.space.collide((),self.near_callback)
self.world.step(self.dt)
# self.check_timeの間隔で世界を動かしていく
self.jointgroup.empty()
return True
class Cylinder:
def __init__(self, field, r, h):
#def __init__(self, field, pos, r, h):
#res = Cylinder(field, radius=0.3, length=0.7)
#このコードにはCylinderのインスタンスコードは上のものしかないので
#**keysには radius lengthが格納される
self.body = ode.Body(field.world)
M = ode.Mass()
M.setCylinder( 0.01, 3, r, h)
self.body.setMass(M)
# setCylinder (密度、方向、半径 長さ)
#方向:1だからgeomはx方向に長い
# http://www10.atwiki.jp/bambooflow/pages/226.html#id_8fb8a607
#0000000000簡単のためCCylinderでなくcylinderにする
self.geom = ode.GeomCCylinder(
space=field.space, radius=r, length=h)
#self.geom = ode.GeomCCylinder(
# space=field.space, radius=r, length=h)
#CCylinder GeomCapsuleの別名
#self.geom.setCategoryBits(5)
#self.geom.setCollideBits(5)
self.body.setPosition((0,5,0))
self.geom.setBody(self.body)
#self.geom.setPosition((0,5,0))
#vpythonのcylinder 円柱の部分センターがposとなる
#これのみだと、x方向へhの長さのcylinderとなる
#以下コード間違い length → axis
self.vcyl = cylinder( pos=(0,5,0), radius=r, length=h, color=color.red)
#self.vcyl = cylinder( radius=r, axis=(h, 0, 0), color=color.red)
#self.vcyl.rotate(angle=pi/2, axis=(0,0,1), origin=(0,5,0))
#self.vcyl.pos = (0,5,0)
print self.vcyl.pos
def update(self):
#pos = self.body.getPosition()
pos = self.geom.getPosition()
print pos
#mat = self.body.getRotation()
mat = self.geom.getRotation()
self.vcyl.pos = pos
#以下のコードを活かすと正しく h が表示されなく短くなる
self.vcyl.axis = mat[0], mat[3], mat[6]
self.vcyl.up = mat[1], mat[4], mat[7]
#これも姿勢に関するもの あとで詳しく調べよう
class Ball:
def __init__(
self,field,
m_density=0.01,
m_radius=0.3,
g_radius=0.3,
v_radius=0.3,
b_pos=vector(1,3,0),
b_sp =vector(10,0,0),
v_color=color.cyan
):
self.body=ode.Body(field.world)
M=ode.Mass()
M.setSphere(m_density, m_radius)
#(密度,半径)
self.body.setMass(M)
self.body.setPosition(b_pos)
#self.body.addForce(b_sp)
self.geom=ode.GeomSphere(
space=field.space,
radius=g_radius
)
#このradiusが実際のバウンドを決める
#多分 sphereの座標が0で radiusが0.3だから
#posが0.3ぐらいのバウンド点になる
#self.geom.setCategoryBits(5)
#self.geom.setCollideBits(5)
#ボール同士の衝突を避ける
#上は Boxのジオメトリを作成
self.geom.setBody(self.body)
# 剛体にジオメトリをセット
self.vball=sphere(
radius=v_radius,
color=v_color
)
def update(self):
pos=self.geom.getPosition()
#boxのジオメトリの位置を得る
self.vball.pos=pos
#print pos,
class Box:
def __init__(self, field, pos, w, h, l):
#初期的設定では、Vehicleクラスのなかで以下行のようにしているので
#self.body = Box(field, width=2.0, height=0.5, length=3.5)
self.old_pos = []
self.body = ode.Body(field.world)
M = ode.Mass()
M.setBox( 1, w, h, l)
#引数 d:密度 w: h: l:
self.body.setMass(M)
self.body.setPosition(pos)
#vpythonと引数l wの順序が入れ替わる
self.geom = ode.GeomBox( space=field.space, lengths=(l, h, w))
# lengthの引数 w h l
self.geom.setBody(self.body)
#self.geom.setPosition(pos)
self.v_box = box( pos=pos, width=w, height=h, length=l)
#self.v_box.rotate(angle=pi/2.0, axis=(0,1,0))
def update(self):
pos = self.geom.getPosition()
mat = self.geom.getRotation()
self.v_box.pos = pos
self.v_box.axis = mat[0], mat[3], mat[6]
self.v_box.up = mat[1], mat[4], mat[7]
if __name__=='__main__':
field = Field()
#cyl = Cylinder(field, 0.3, 0.7, "red")
#cyl = Cylinder(field,(0, 5, 0), 0.3, 5.0)
#cyl = Cylinder(field,(0, 5, 0), 0.3, 5.0)
cyl = Cylinder(field, 0.3, 5.0)
#cyl.body.setPosition((0, 5, 0))
ball1 = Ball(field, b_pos=(1,2,0))
ball2 = Ball(field, b_pos=(1,1,0), v_color=color.red)
box = Box(field, (-4, 5, 0), 2, 1, 4 )
#box.v_box.rotate(angle=pi/20, axis=(0,0,1))
while True:
rate(100)
time.sleep(0.05)
field.tick()
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿