VPython三维仿真(NO.5) 移动模型和调整姿态

模型运动

三维模型的运动涉及六个自由度,分别是模型质心沿笛卡尔直角坐标系三个轴x、y、z的线位移和绕三个轴的角位移。模型运动就是以上六个位移的复合运动,三维仿真的核心就是弄清楚如何在场景中设置模型这六个自由度的方法。

复杂模型对象

在第三节“VPython三维仿真(NO.3) 导入复杂模型”中,将STL文件中的三角面画出后,将所有三角面存入tris列表中,移动模型需要通过compound(复合体)封装复杂模型的所有三角面,compound对象具有基本模型的属性和函数,可以像操作基础模型一样移动、转动导入的复杂模型。
在函数FileToModel中下列代码将复杂模型的三角面tris列表封装到compound中,然后FileToModel函数返回vpython.vpython.compound对象。

if makeComp==True:
        tt=compound(tris,make_trail=tail) #make_trail=True显示模型尾迹
        return tt #vpython.vpython.compound对象

移动模型

compound和基础模型通过pos属性可设置模型在场景的位置,移动模型有两种方式,一是设置模型的绝对空间位置,即每次将模型在场景空间的坐标赋值给模型pos属性;二是设置模型的空间位置增量,即在模型当前位置上增加一个向量值,使模型移动到正确的位置上,在三维仿真中,如飞行器飞行的仿真,通常使用时间冻结法,根据仿真步长和飞行器的运动学、动力学方程,计算出模型下一时刻的线位移增量和角位移增量,故通常使用第二种方法。
移动模型的代码如下:

#vector为模型位置坐标
m.pos=vector(1,2,3)

#分别设置三轴坐标
m.pos.x=1
m.pos.y=2
m.pos.z=3

转动模型

compound和基础模型通过函数rotate转动模型,函数参数包括转动角度和指定旋转轴,需要注意的是,模型从一个姿态转到另一个姿态,绕x、、y、z三个轴旋转的次序不同,每次旋转的角度可能不同。
转动模型的代码如下:

#转动角度angle单位为弧度
#vec(1,0,0)绕x轴转,vec(0,1,0)绕y轴转,vec(0,0,1)绕z轴转
m.rotate(angle=30*3.14/180,axis=vec(0,1,0))

动画帧率控制

VPython提供了函数rate,可方便的控制动画的帧率,如rate(25)为每秒25帧,即每隔40ms更新一次模型位置和姿态。没有该函数需要自己读取系统时钟完成定时,会更复杂。人眼的视觉暂留现象要求每秒大于24帧即可看到连续的动画,帧率越高动画越连贯,高帧率同时缩短了软件计算运的时间,帧率选择应满足计算运动数据所需的时间。

尾迹

使模型运动更直观的方法是显示模型运动的尾迹tail,就像特技飞行表演拉出的尾烟一样,可看到飞机飞过的路径。compound和基础模型都提供该属性,

飞机绕圈飞行

本例综合运用了对飞机模型的运动和转动,通过坐标系和尾迹(飞机拖曳出的白色圆圈)使飞机的飞行更易于观察。代码如下,动画效果见视频1。

下一节简介

VPython三维仿真(NO.6)操作场景与摄像机 介绍对场景的控制和摄像机跟随模型运动。

视频1:飞机绕圈飞行

# -*- coding: utf-8 -*-
import pandas as pd
from vpython import *
import numpy
from stl import mesh

#从stl文件中读取数据构建模型
#file:stl文件名
#makeComp:是否构建compound,True输出compound,False输出0
#tail:是否有尾迹
#model_color:模型颜色
def FileToModel(file,makeComp=False,tail=False,model_color=vec(0.5,0.5,0.5)):
    temp_mesh = mesh.Mesh.from_file(file) #STL数据读入temp_mesh
    tris=[]
    num=int(temp_mesh.normals.size/3) #三角面数量
    for a in range(num):
        aa = temp_mesh.vectors[a][0] #三角面顶点1
        bb = temp_mesh.vectors[a][1] #三角面顶点2
        cc = temp_mesh.vectors[a][2] #三角面顶点3
        nn = temp_mesh.normals[a] #三角面方向向量
        #建立三角形三个顶点,normal顶点方向向量,colord顶点颜色
        p=vector(0,0,0)
        a = vertex(pos=vector(aa[0], aa[1], aa[2])+p,normal=vector(nn[0], nn[1], nn[2]),color=model_color)
        b = vertex(pos=vector(bb[0], bb[1], bb[2])+p,normal=vector(nn[0], nn[1], nn[2]),color=model_color)
        c = vertex(pos=vector(cc[0], cc[1], cc[2])+p,normal=vector(nn[0], nn[1], nn[2]),color=model_color)
        t=triangle(v0=a,v1=b,v2=c) #由三个顶点生成三角面
        tris.append(t) #三角面数组
    if makeComp==True:
        tt=compound(tris,make_trail=tail) #将三角面组成组件
        return tt
    return 0

#构建坐标系/
#axis_lenth:坐标轴长度
#axis_rad:坐标轴直径
#cone_rad:坐标箭头直径
def Coord_Sys(axis_len=100,axis_radius=1,cone_radius=1):
    cone_len = 3*cone_radius
    x_axis_line = cylinder(pos=vector(0, 0, 0), axis=vec(axis_len, 0, 0), radius=axis_radius)
    x_axis_line.color = vector(255, 0, 0)
    x_axis_cone = cone(pos=vector(axis_len, 0, 0), axis=vec(cone_len, 0, 0), radius=cone_radius)
    x_axis_cone.color = vector(255, 0, 0)
    # y轴线和箭头
    y_axis_line = cylinder(pos=vector(0, 0, 0), axis=vec(0, axis_len, 0), radius=axis_radius)
    y_axis_line.color = vector(0, 255, 0)
    y_axis_cone = cone(pos=vector(0, axis_len, 0), axis=vec(0, cone_len, 0), radius=cone_radius)
    y_axis_cone.color = vector(0, 255, 0)
    # z轴线和箭头
    z_axis_line = cylinder(pos=vector(0, 0, 0), axis=vec(0, 0, axis_len), radius=axis_radius)
    z_axis_line.color = vector(0, 0, 255)
    z_axis_cone = cone(pos=vector(0, 0, axis_len), axis=vec(0, 0, cone_len), radius=cone_radius)
    z_axis_cone.color = vector(0, 0, 255)

#飞机飞行
def Flying(target):
    #global target
    #移动目标
    m=1000 #m为单位米
    i=0
    kk=3.14*2/250 #飞机绕圆心转动每帧角度增量
    target.pos.y = 3*m #固定飞行高度50米
    target.rotate(angle=-30*3.14/180,axis=vec(1,0,0)) #飞机倾斜30度
    while True:
        rate(25) #每秒25帧
        ang=i*kk #飞行绕圆心角度
        target.pos.x = 3*m*sin(ang)   
        target.pos.z = 3*m*cos(ang)
        target.rotate(angle=kk,axis=vec(0,1,0)) #飞机绕Y轴转动
        i += 1

def main(): 
    #画坐标系
    Coord_Sys(5000,50,100)
    #生成飞机
    aa=FileToModel('plane1.stl',makeComp=True,tail=True,model_color=vec(1,1,0))
    print(type(aa))
    #飞机飞行
    Flying(aa)
    
if __name__ == '__main__':
    main()
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

合金弹头001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值