使用arrow( )創建三個坐標軸代表一個坐標系,其中X0-Y0-Z0為參考坐標系(固定不動),X-Y-Z為運動坐標系,這兩個坐標系原點重合,運動坐標系可以繞參考坐標系或其自身旋轉。在屏幕上輸出一個轉換矩陣,該矩陣描述了動坐標系相對於參考坐標系的姿態,矩陣第一列表示動坐標系的X軸在參考坐標系中的方向,第二列表示動坐標系的Y軸在參考坐標系中的方向,第二列表示動坐標系的Z軸在參考坐標系中的方向。顯而易見,當兩個坐標系姿態一致時,轉換矩陣為3階單位矩陣。
程序中按鍵盤的上下方向坐標系繞Y軸旋轉,按左右鍵坐標系繞Z軸旋轉,按W,S鍵繞X軸旋轉。由於本例子使用的是VPython5,對於鍵盤事件只支持輪詢方式檢測,即在while循環中不停地檢測是否有按鍵按下。在最新的VPython6中支持了鍵盤事件響應,可以自定義事件響應的回掉函數。
對於繞Z軸旋轉這一動作來說,可以使繞參考坐標系的Z軸,也可以是繞動坐標系自身的Z軸。繞自身坐標軸旋轉的角度稱為歐拉角,而飛行器和航海中常用的RPY角(Roll-Pitch-Yaw:橫滾、俯仰、偏航)是繞固定坐標系旋轉。
對於旋轉三個坐標軸來說可以將其放在一個自定義的旋轉函數中,每次旋轉只需調用該函數;也可以將其添加進同一個frame,旋轉frame時frame中的所有對象都會跟着一起旋轉。注意:下面的程序中旋轉frame時是繞着參考坐標系的坐標軸旋轉的,調用自定義的旋轉函數旋轉坐標系時是按照動坐標系的坐標軸旋轉的。
1 # -*- coding: utf-8 -*- 2 from visual import * 3 4 scene.title = 'Coordinates' # 設置窗口標題 5 scene.width = 600 # 設置窗口寬度和高度 6 scene.height = 600 7 scene.forward = (-1,-1,-1) # 設置camera視線方向 8 9 # Create a frame object,group objects together to make a composite object 10 f = frame() 11 12 # 定義參考坐標系 13 X0 = arrow(pos=(0,0,0), axis=(1,0,0), color=color.cyan, shaftwidth=0.05) 14 Y0 = arrow(pos=(0,0,0), axis=(0,1,0), color=color.cyan, shaftwidth=0.05) 15 Z0 = arrow(pos=(0,0,0), axis=(0,0,1), color=color.yellow,shaftwidth=0.05) 16 17 18 # 定義運動坐標系的X,Y,Z軸 19 X = arrow(frame = f, pos=(0,0,0), axis=(1,0,0), color=(1,0,0), shaftwidth=0.1) 20 Y = arrow(frame = f, pos=(0,0,0), axis=(0,1,0), color=(0,1,0), shaftwidth=0.1) 21 Z = arrow(frame = f, pos=(0,0,0), axis=(0,0,1), color=(0,0,1), shaftwidth=0.1) 22 23 tf_str = 'Transformation matrix:\n%-8.2f %-8.2f %-8.2f\n%-8.2f %-8.2f %-8.2f\n%-8.2f %-8.2f %-8.2f\n'%(1,0,0,0,1,0,0,0,1) 24 25 # With the label object you can display 2D text in a box, and the label always faces forward 26 info = label(pos=(-0.5,0.5,0), text = tf_str, box=False, opacity=0, height=16) 27 28 29 delta_angle = radians(2) # 2° 30 31 def rotate_axis(angle, axis, origin): 32 X.rotate(angle=angle, axis=axis, origin=origin) 33 Y.rotate(angle=angle, axis=axis, origin=origin) 34 Z.rotate(angle=angle, axis=axis, origin=origin) 35 36 while True: 37 rate(100) 38 39 if scene.kb.keys: # event waiting to be processed? 40 s = scene.kb.getkey() # get keyboard info 41 42 # 按左右箭頭繞Z軸旋轉 43 if s == 'left': 44 #f.rotate(angle=delta_angle, axis=Z.axis, origin=(0,0,0)) 45 rotate_axis(angle = delta_angle, axis = Z.axis, origin = (0,0,0)) 46 elif s == 'right': 47 #f.rotate(angle=-delta_angle, axis=Z.axis, origin=(0,0,0)) 48 rotate_axis(angle = -delta_angle, axis = Z.axis, origin = (0,0,0)) 49 50 # 按上下箭頭繞Y軸旋轉 51 if s == 'up': 52 #f.rotate(angle=delta_angle, axis=Y.axis, origin=(0,0,0)) 53 rotate_axis(angle = delta_angle, axis = Y.axis, origin = (0,0,0)) 54 elif s == 'down': 55 #f.rotate(angle=-delta_angle, axis=Y.axis, origin=(0,0,0)) 56 rotate_axis(angle = -delta_angle, axis = Y.axis, origin = (0,0,0)) 57 58 # 按w,s鍵繞X軸旋轉 59 if s == 'w': 60 #f.rotate(angle=delta_angle, axis=X.axis, origin=(0,0,0)) 61 rotate_axis(angle = delta_angle, axis = X.axis, origin = (0,0,0)) 62 elif s == 's': 63 #f.rotate(angle=-delta_angle, axis=X.axis, origin=(0,0,0)) 64 rotate_axis(angle = -delta_angle, axis = X.axis, origin = (0,0,0)) 65 66 info.text = 'Transformation matrix:\n%-8.2f %-8.2f %-8.2f\n%-8.2f %-8.2f %-8.2f\n%-8.2f %-8.2f %-8.2f\n'\ 67 % (X.axis[0],Y.axis[0],Z.axis[0],\ 68 X.axis[1],Y.axis[1],Z.axis[1],\ 69 X.axis[2],Y.axis[2],Z.axis[2])