ラベル Translate の投稿を表示しています。 すべての投稿を表示
ラベル Translate の投稿を表示しています。 すべての投稿を表示

2008/05/09

Robot2 - simple humanoid

11軸の単純な人間型ロボットを作ってみました。胴体を中心とした全体回転1軸、頭2軸、手足各2軸x4本です。これも"OpenGL入門" エドワード・エンジェル著、滝沢徹・牧野祐子訳、ピアソン・エデュケーション刊を参考にして作ってみました。軸は多くなりましたが、glPush/PopMatrixが追加されただけで、原理は昨日のサンプルと全く同じです。Pythonはインタープリタでありデバッグが簡単なので、これくらいのコードなら数時間で動かせます。とても手軽です。キーボードで操作できます。大文字は逆方向に動きます。
e/E r/R (頭)
a/A s/S d/D f/F g/G (腕、胴体)
z/Z x/X c/C v/V (足)

Simple humanoid type robot with 11 moving axis, 1 for entire body, 2 for head, 2 for each leg, by refering a book "OpenGL, A PRIMER" by Edward Angel. glPush/PopMatrix is added to handle this complex structure. Python is pretty powerfull to debug my source code because it's an interpreter. You can operate the humanoid by using keyboard.

e/E r/R (head)
a/A s/S d/D f/F g/G (arms, entire body)
z/Z x/X c/C v/V (legs)


import sys
import math
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

TORSO_RADIUS=0.1
TORSO_HEIGHT=0.4

UPPER_ARM_HEIGHT=0.2
UPPER_ARM_WIDTH=0.07

LOWER_ARM_HEIGHT=0.2
LOWER_ARM_WIDTH=0.05

UPPER_LEG_HEIGHT=0.2
UPPER_LEG_WIDTH=0.08

LOWER_LEG_HEIGHT=0.2
LOWER_LEG_WIDTH=0.06

SHOLDER_WIDTH = 0.2
HIP_WIDTH = 0.2

HEADX=0.1
HEADY=TORSO_HEIGHT

LUAX=-1.0 * SHOLDER_WIDTH / 2
RUAX=SHOLDER_WIDTH / 2
LUAY=RUAY=TORSO_HEIGHT
LLAY=RLAY=LOWER_ARM_HEIGHT

LULX=-1.0 * HIP_WIDTH / 2
RULX=HIP_WIDTH / 2
LULY=RULY=0
LLLY=RLLY=LOWER_LEG_HEIGHT

t0=0.0
t1=0.0
t2=0.0
t3=90.0
t4=0.0
t5=90.0
t6=0.0
t7=180.0
t8=0.0
t9=180.0
t10=0.0

def display():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)

#TORSO
glLoadIdentity()
gluLookAt(2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
gray()
glRotatef(t0, 0.0, 1.0, 0.0)
torso()
glPushMatrix()

#HEAD
cyan()
glTranslatef(0.0, HEADX, 0.0)
glRotatef(t1, 1.0, 0.0, 0.0)
glRotatef(t2, 0.0, 1.0, 0.0)
glTranslatef(0.0, HEADY, 0.0)
head()

#LEFT UPPER ARM
glPopMatrix()
glPushMatrix()
red()
glTranslatef(LUAX, LUAY, 0.0)
glRotatef(t3, 1.0, 0.0, 0.0)
upper_arm()

#LEFT LOWER ARM
green()
glTranslatef(0.0, LLAY, 0.0)
glRotatef(t4, 1.0, 0.0, 0.0)
lower_arm()

#RIGHT UPPER ARM
glPopMatrix()
glPushMatrix()
blue()
glTranslatef(RUAX, RUAY, 0.0)
glRotatef(t5, 1.0, 0.0, 0.0)
upper_arm()

#RIGHT UPPER ARM
cyan()
glTranslatef(0.0, RLAY, 0.0)
glRotatef(t6, 1.0, 0.0, 0.0)
lower_arm()

#LEFT UPPER LEG
glPopMatrix()
glPushMatrix()
magenta()
glTranslatef(LULX, LULY, 0.0)
glRotatef(t7, 1.0, 0.0, 0.0)
upper_leg()

#LEFT LOWER LEG
yellow()
glTranslatef(0.0, LLLY, 0.0)
glRotatef(t8, 1.0, 0.0, 0.0)
lower_leg()

#RIGHT UPPER LEG
glPopMatrix()
glPushMatrix()
pink()
glTranslatef(RULX, RULY, 0.0)
glRotatef(t9, 1.0, 0.0, 0.0)
upper_leg()

#RIGHT LOWER LEG
gray()
glTranslatef(0.0, RLLY, 0.0)
glRotatef(t10, 1.0, 0.0, 0.0)
lower_leg()

glPopMatrix()
glFlush()

def torso():
glPushMatrix()
glRotatef(-90.0, 1.0, 0.0, 0.0)
gluCylinder(p, TORSO_RADIUS, TORSO_RADIUS, TORSO_HEIGHT, 10, 10)
glPopMatrix()

def head():
glPushMatrix()
glRotatef(-90.0, 1.0, 0.0, 0.0)
glutWireSphere(0.1, 10, 10)
glPopMatrix()

def upper_arm():
glPushMatrix()
glTranslatef(0.0, 0.5*UPPER_ARM_HEIGHT, 0.0)
glScalef(UPPER_ARM_WIDTH, UPPER_ARM_HEIGHT, UPPER_ARM_WIDTH)
glutSolidCube(1.0)
glPopMatrix()

def lower_arm():
glPushMatrix()
glTranslatef(0.0, 0.5*UPPER_ARM_HEIGHT, 0.0)
glScalef(LOWER_ARM_WIDTH, LOWER_ARM_HEIGHT, LOWER_ARM_WIDTH)
glutSolidCube(1.0)
glPopMatrix()

def upper_leg():
glPushMatrix()
glTranslatef(0.0, 0.5*LOWER_ARM_HEIGHT, 0.0)
glScalef(UPPER_LEG_WIDTH, UPPER_LEG_HEIGHT, UPPER_LEG_WIDTH)
glutSolidCube(1.0)
glPopMatrix()

def lower_leg():
glPushMatrix()
glTranslatef(0.0, 0.5*LOWER_ARM_HEIGHT, 0.0)
glScalef(LOWER_LEG_WIDTH, LOWER_LEG_HEIGHT, LOWER_LEG_WIDTH)
glutSolidCube(1.0)
glPopMatrix()

def red():
glColor3f(1.0, 0.0, 0.0)
def green():
glColor3f(0.0, 1.0, 0.0)
def blue():
glColor3f(0.0, 0.0, 1.0)
def cyan():
glColor3f(0.0, 1.0, 1.0)
def magenta():
glColor3f(1.0, 1.0, 0.0)
def yellow():
glColor3f(1.0, 0.0, 1.0)
def pink():
glColor3f(1.0, 0.5, 0.5)
def gray():
glColor3f(0.7, 0.7, 0.7)

def mykey(key, x, y):
global t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10
if key=='d': # TORSO
t0 = t0 + 10.0
elif key=='D':
t0 = t0 - 10.0
elif key=='e': # HEAD 1
t1 = t1 + 10.0
elif key=='E':
t1 = t1 - 10.0
elif key=='r': # HEAD 2
t2 = t2 + 10.0
elif key=='R':
t2 = t2 - 10.0
elif key=='s': # LUA
t3 = t3 + 10.0
elif key=='S':
t3 = t3 - 10.0
elif key=='a': # LLA
t4 = t4 + 10.0
elif key=='A':
t4 = t4 - 10.0
elif key=='f': # RUA
t5 = t5 + 10.0
elif key=='F':
t5 = t5 - 10.0
elif key=='g': # RLA
t6 = t6 + 10.0
elif key=='G':
t6 = t6 -10.0
elif key=='x': # LUL
t7 = t7 + 10.0
elif key=='X':
t7 = t7 - 10.0
elif key=='z': # LLL
t8 = t8 + 10.0
elif key=='Z':
t8 = t8 -10.0
elif key=='c': # RUL
t9 = t9 + 10.0
elif key=='C':
t9 = t9 - 10.0
elif key=='v': # RLL
t10 = t10 + 10.0
elif key=='V':
t10 = t10 - 10.0
elif key=='q':
sys.exit()

print "params: ", t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10
glutPostRedisplay()

glutInit( sys.argv )
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB )
glutInitWindowSize( 500, 500 )
glutInitWindowPosition(0,0)
glutCreateWindow( 'robot' )
glutDisplayFunc( display )
glutKeyboardFunc(mykey)
p=gluNewQuadric()
gluQuadricDrawStyle(p, GLU_LINE)

glClearColor(0.0, 0.0, 0.0, 0.0)

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(30, 1.0, 0.0, 100.0)

glutMainLoop()

2008/05/08

Robot - simple hierarchical model

移動(Translate)や回転(Rotate)は拡大・縮小はインクリメンタルであるため、リセットしなければ変換用の行列に加算や乗算がどんどん加えられて行きます。土台、下腕、上腕を持つ簡単なロボットの例を、"OpenGL入門" エドワード・エンジェル著、滝沢徹・牧野祐子訳、ピアソン・エデュケーション刊を参考にして作ってみました。Cで書かれた部分的なサンプルコードをPythonに書き直すのは至って簡単でした。Translateの基本概念が前回分かったので、うんと楽です。ただ、変換の順番が問題になると、まだよく分かっていないことが露呈します。

Instance transformation is incremental. This is good for hierarchical instances with dependency on other objects in parent hierarchy. By refering a book "OpenGL, A PRIMER" by Edward Angel, I made a simple robot example using Python. "base" instance has a child instance "lower_arm" and "lower_arm" has a child instance "upper_arm". Translating C sample code to Python was very easy because I learned how the MODELVIEW matrix works.

In the following example, use key 'q', 'a', 'w', 's', 'e', 'd' to move each part of the robot.


import sys
import math
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

BASE_RADIUS = 0.1
BASE_HEIGHT = 0.1
UPPER_ARM_WIDTH = 0.05
UPPER_ARM_HEIGHT=0.5
LOWER_ARM_WIDTH=0.08
LOWER_ARM_HEIGHT=0.3
tb=0
tl=45
tu=30

def display():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)

glLoadIdentity()
gluLookAt(2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
glColor3f(1.0, 0.0, 0.0)
glRotatef(tb, 0.0, 1.0, 0.0)
base()
glTranslatef(0.0, BASE_HEIGHT, 0.0)
glColor3f(0.0, 1.0, 0.0)
glRotatef(tl, 0.0, 0.0, 1.0)
lower_arm()
glTranslatef(0.0, LOWER_ARM_HEIGHT, 0.0)
glRotatef(tu, 0.0, 0.0, 1.0)
glColor3f(0.0, 0.0, 1.0)
upper_arm()
glFlush()

def base():
glPushMatrix()
glRotatef(-90.0, 1.0, 0.0, 0.0)
gluCylinder(p, BASE_RADIUS, BASE_RADIUS, BASE_HEIGHT, 10, 10)
glPopMatrix()

def upper_arm():
glPushMatrix()
glTranslatef(0.0, 0.5*UPPER_ARM_HEIGHT, 0.0)
glScalef(UPPER_ARM_WIDTH, UPPER_ARM_HEIGHT, UPPER_ARM_WIDTH)
glutSolidCube(1.0)
glPopMatrix()

def lower_arm():
glPushMatrix()
glTranslatef(0.0, 0.5*LOWER_ARM_HEIGHT, 0.0)
glScalef(LOWER_ARM_WIDTH, LOWER_ARM_HEIGHT, LOWER_ARM_WIDTH)
glutSolidCube(1.0)
glPopMatrix()

def mykey(key, x, y):
global tb, tl, tu
if key=='q': # +base
tb = tb + 5.0
elif key=='a': # -base
tb = tb - 5.0
elif key=='w': #+lower
tl = tl + 5.0
elif key=='s': #-lower
tl = tl - 5.0
elif key=='e': #+upper
tu = tu + 5.0
elif key=='d': #-upper
tu = tu - 5.0
print "tb=", tb, " tl=", tl, " tu=", tu
glutPostRedisplay()

glutInit( sys.argv )
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB )
glutInitWindowSize( 500, 500 )
glutInitWindowPosition(0,0)
glutCreateWindow( 'robot' )
glutDisplayFunc( display )
glutKeyboardFunc(mykey)
p=gluNewQuadric()
gluQuadricDrawStyle(p, GLU_LINE)

glClearColor(0.0, 0.0, 0.0, 0.0)

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(30, 1.0, 0.0, 100.0)

glutMainLoop()

2008/05/02

glScale


OpenGLの提供する3番目の標準変換は拡大縮小(スケーリング)です。この例では前の例のglRotateをglScaleに置き換えただけです。ただし、回転と違って拡大縮小は連続して同じ操作を行うと画面からはみ出してしまうか、または点になってしまいます。そこで、拡大を10回行ったら縮小を10回行うように制御してみました。Pythonのif文による制御はC言語に似ているので簡単です。{}を:とインデントに置き換えて、;を取り除けばOKです。グローバル変数は自由に参照できますが、グローバル変数の値を変更するにはglobal宣言が必要です。

I just replaced glRotatef to glScale to illustrate scaling translation of OpenGL. Not like glRotate, I cannot continue scale down becuase the triangle will be too small. I should control sclae up and down using control statement in Python. Python provedes "if" statement very similar to C.


sc = up = 0
def timer(value):
global sc, up
if up:
glScale(1.1 , 1.1 , 1)
sc += 1
if sc > 0:
up = 0
else:
glScale(0.9091 , 0.9091 , 1)
sc -= 1
if sc < -8:
up = 1
glutPostRedisplay()
glutTimerFunc(50 , timer , 0)

2008/04/28

glRotate

前回は行列を持いて回転を行いましたが、今回はglRotateコマンドを持ちいて回転を行います。こちらの方が普通のようです。前回からの変更点は
glMultMatrixf(translate)

glRotatef(2 , 0.5 , 1 , 0.25)
に代わっているだけです。
今回もhttp://wisdom.sakura.ne.jp/system/opengl/gl11.htmlを参照させて頂きました。

From my previous example, I made only one change. From glMultMatrixf(translate) to glRotatef(2 , 0.5 , 1 , 0.25). I don't have to use matrix. This would be more straight forward.


import sys
from math import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

def disp():
glClear(GL_COLOR_BUFFER_BIT)
glBegin(GL_POLYGON)
glColor3f(1 , 0 , 0)
glVertex2f(-0.9 , -0.9)
glColor3f(0 , 1 , 0)
glVertex2f(0 , 0.9)
glColor3f(0 , 0 , 1)
glVertex2f(0.9 , -0.9)
glEnd()
glFlush()

def timer(value):
glRotatef(2 , 0.5 , 1 , 0.25)
glutPostRedisplay()
glutTimerFunc(50 , timer , 0)

glutInit(sys.argv)
glutInitWindowPosition(100 , 50)
glutInitWindowSize(400 , 300)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA)
glutCreateWindow("rotate4.py")
glutDisplayFunc(disp)
glutTimerFunc(100 , timer , 0)
glutMainLoop()

Translate

モデル・ビュー変換というものを使って三角形を回転させてみましょう。今回も、
http://wisdom.sakura.ne.jp/system/opengl/gl11.html
を参考にさせて頂きました。Pythonに変換した時にわかったことは、C言語の配列
GLfloat translate[] = {
1 , 0 , 0 , 0 ,
0 , 1 , 0 , 0 ,
0 , 0 , 1 , 0 ,
0 , 0 , 0 , 1
};

はPythonでは単に
translate = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
と書けば良いようです。

By using Model-View translation, a triangle is rotated around Y axis.
During making Python sample from original C sample, I found that array in C,

GLfloat translate[] = {
1 , 0 , 0 , 0 ,
0 , 1 , 0 , 0 ,
0 , 0 , 1 , 0 ,
0 , 0 , 0 , 1
};
can be implemented in Python as follows.
translate = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]


import sys
from math import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

ANGLE = 0.2
translate = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]

def disp():
glClear(GL_COLOR_BUFFER_BIT)
glBegin(GL_POLYGON)
glColor3f(1 , 0 , 0)
glVertex2f(-0.9 , -0.9)
glColor3f(0 , 1 , 0)
glVertex2f(0 , 0.9)
glColor3f(0 , 0 , 1)
glVertex2f(0.9 , -0.9)
glEnd()
glFlush()

def timer(value):
glMultMatrixf(translate)
glutPostRedisplay()
glutTimerFunc(50 , timer , 0)

glutInit(sys.argv)
glutInitWindowPosition(100 , 50)
glutInitWindowSize(400 , 300)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA)
glutCreateWindow("rotate3.py")
glutDisplayFunc(disp)
glutTimerFunc(100 , timer , 0)
translate[0] = cos(ANGLE)
translate[2] = -sin(ANGLE)
translate[8] = sin(ANGLE)
translate[10] = cos(ANGLE)
glutMainLoop()