三维可视化系统的建立依赖于三维图形平台, 如 OpenGL、VTK、OGRE、OSG等,
传统的方法多采用OpenGL进行底层编程,即对其特有的函数进行定量操作, 需要开发人员熟悉相关函数, 从而造成了开发难度大、 周期长等问题。VTK、
ORGE、OSG等平台使用封装更好的函数简化了开发过程。下面将使用Python与VTK进行机器人上位机监控界面的快速原型开发。

完整的上位机程序需要有三维显示模块、机器人信息监测模块(位置/角度/速度/电量/温度/错误信息…)、通信模块(串口/USB/WIFI/蓝牙…)、控制模块等功能模块。三维显示模块主要用于实时显示机器人的姿态(或位置)信息。比如机器人上肢手臂抬起,程序界面中的虚拟机器人也会同时进行同样的动作。三维显示模块也可以用于对机器人进行控制,实现良好的人机交互。比如在三维图像界面中可以点击拾取机器人某一关节,拖拽部件(肢体)控制真实的机器人完成同样的运动。Aldebaran
Robotics的图形化编程软件Choregraphe可以完成上述的一些功能对NAO机器人进行控制。

对于简单的模型可以自己编写函数进行创建,但这种方法做出来的模型过于简单不够逼真。因此可以先在SolidWorks、Blender、3DMax、Maya、Rhino等三维设计软件中建立好模型,然后导出为通用的三维文件格式,再使用VTK将其读入并进行渲染。

在SolidWorks等三维设计软件中设计好机器人的大臂(upperarm)和小臂(forearm),然后创建装配体如下图所示。在将装配体导出为STL文件前需要注意几点:

  1. 当从外界读入STL类型的模型时,其会按照它内部的坐标位置进行显示,因此它的位置和大小是确定的。为了以后的定位以及移动、旋转等操作的方便,需要先在SolidWorks中创建一个坐标系。如下图所示,坐标系建立在大臂关节中心点。
  2. 如果将装配体整体输出为一个STL文件,则导入VTK后无法控制零部件进行相对运动。因此,需要将装配体各可动部件分别导出。

在SolidWorks的另存为STL对话框中,点开输出选项卡,如下图所示。注意之前提到的几点:如果勾选“在单一文件中保存装配体的所有零部件”则会将整个装配体导出为一个STL文件,否则就是分别命名的两个STL文件;输出坐标系下拉列表中选择之前创建的坐标系1,并勾选“不要转换STL输出数据到正的坐标空间”。

下面的Python代码简单实现了一个2自由度机械臂的三维仿真,可以拖动滑块或按键盘上的方向键控制肩关节或肘关节运动。当然程序还存在一些问题有待完善…

    #!/usr/bin/env pythonimport vtkimport mathfrom vtk.util.colors import *filenames = ["upperarm.stl","forearm.stl"]dt = 1.0    # degree step in rotationangle = [0, 0] # shoulder and elbow joint anglerenWin = vtk.vtkRenderWindow()assembly = vtk.vtkAssembly()slider_shoulder = vtk.vtkSliderRepresentation2D()slider_elbow = vtk.vtkSliderRepresentation2D()actor = list() # the list of links# Customize vtkInteractorStyleTrackballCamera class MyInteractor(vtk.vtkInteractorStyleTrackballCamera):def __init__(self,parent=None):self.AddObserver("CharEvent",self.OnCharEvent)self.AddObserver("KeyPressEvent",self.OnKeyPressEvent)# Override the default key operations which currently handle trackball or joystick styles is provided# OnChar is triggered when an ASCII key is pressed. Some basic key presses are handled here def OnCharEvent(self,obj,event):passdef OnKeyPressEvent(self,obj,event):global angle# Get the compound key strokes for the eventkey = self.GetInteractor().GetKeySym()# Output the key that was pressed#print "Pressed: " , key# Handle an arrow keyif(key == "Left"):actor[1].RotateY(-dt)      if(key == "Right"):actor[1].RotateY(dt)      if(key == "Up"):assembly.RotateY(-dt)angle[0] += dtif angle[0] >= 360.0:angle[0] -= 360.0slider_shoulder.SetValue(angle[0])  if(key == "Down"):assembly.RotateY(dt)angle[0] -= dtif angle[0] < 0.0:angle[0] += 360.0 slider_shoulder.SetValue(angle[0])# Ask each renderer owned by this RenderWindow to render its image and synchronize this processrenWin.Render()returndef LoadSTL(filename):reader = vtk.vtkSTLReader()reader.SetFileName(filename)mapper = vtk.vtkPolyDataMapper() # maps polygonal data to graphics primitivesmapper.SetInputConnection(reader.GetOutputPort())actor = vtk.vtkLODActor() actor.SetMapper(mapper)return actor  # represents an entity in a rendered scenedef CreateCoordinates():# create coordinate axes in the render windowaxes = vtk.vtkAxesActor() axes.SetTotalLength(100, 100, 100) # Set the total length of the axes in 3 dimensions # Set the type of the shaft to a cylinder:0, line:1, or user defined geometry. axes.SetShaftType(0) axes.SetCylinderRadius(0.02) axes.GetXAxisCaptionActor2D().SetWidth(0.03) axes.GetYAxisCaptionActor2D().SetWidth(0.03) axes.GetZAxisCaptionActor2D().SetWidth(0.03) #axes.SetAxisLabels(0) # Enable:1/disable:0 drawing the axis labels#transform = vtk.vtkTransform() #transform.Translate(0.0, 0.0, 0.0)#axes.SetUserTransform(transform)#axes.GetXAxisCaptionActor2D().GetCaptionTextProperty().SetColor(1,0,0)#axes.GetXAxisCaptionActor2D().GetCaptionTextProperty().BoldOff() # disable text boldingreturn axesdef ShoulderSliderCallback(obj,event):sliderRepres = obj.GetRepresentation()pos = sliderRepres.GetValue() assembly.SetOrientation(0,-pos,0)renWin.Render()def ElbowSliderCallback(obj,event):sliderRepres = obj.GetRepresentation()pos = sliderRepres.GetValue() actor[1].SetOrientation(0,-pos,0)renWin.Render()def ConfigSlider(sliderRep, TitleText, Yaxes):sliderRep.SetMinimumValue(0.0)sliderRep.SetMaximumValue(360.0)sliderRep.SetValue(0.0) # Specify the current value for the widgetsliderRep.SetTitleText(TitleText) # Specify the label text for this widgetsliderRep.GetSliderProperty().SetColor(1,0,0) # Change the color of the knob that slidessliderRep.GetSelectedProperty().SetColor(0,0,1) # Change the color of the knob when the mouse is held on itsliderRep.GetTubeProperty().SetColor(1,1,0) # Change the color of the bar sliderRep.GetCapProperty().SetColor(0,1,1) # Change the color of the ends of the bar#sliderRep.GetTitleProperty().SetColor(1,0,0) # Change the color of the text displaying the value# Position the first end point of the slidersliderRep.GetPoint1Coordinate().SetCoordinateSystemToDisplay()sliderRep.GetPoint1Coordinate().SetValue(50, Yaxes) # Position the second end point of the slidersliderRep.GetPoint2Coordinate().SetCoordinateSystemToDisplay()sliderRep.GetPoint2Coordinate().SetValue(400, Yaxes) sliderRep.SetSliderLength(0.02) # Specify the length of the slider shape.The slider length by default is 0.05sliderRep.SetSliderWidth(0.02) # Set the width of the slider in the directions orthogonal to the slider axissliderRep.SetTubeWidth(0.005)sliderRep.SetEndCapWidth(0.03)sliderRep.ShowSliderLabelOn() # display the slider text labelsliderRep.SetLabelFormat("%.1f")sliderWidget = vtk.vtkSliderWidget()sliderWidget.SetRepresentation(sliderRep)sliderWidget.SetAnimationModeToAnimate()return sliderWidgetdef CreateGround():# create plane sourceplane = vtk.vtkPlaneSource()plane.SetXResolution(50)plane.SetYResolution(50)plane.SetCenter(0,0,0)plane.SetNormal(0,0,1)  # mappermapper = vtk.vtkPolyDataMapper()mapper.SetInputConnection(plane.GetOutputPort())# actoractor = vtk.vtkActor()actor.SetMapper(mapper)actor.GetProperty().SetRepresentationToWireframe()#actor.GetProperty().SetOpacity(0.4) # 1.0 is totally opaque and 0.0 is completely transparentactor.GetProperty().SetColor(light_grey)'''# Load in the texture map. A texture is any unsigned char image.bmpReader = vtk.vtkBMPReader() bmpReader.SetFileName("ground_texture.bmp") texture = vtk.vtkTexture() texture.SetInputConnection(bmpReader.GetOutputPort()) texture.InterpolateOn() actor.SetTexture(texture)'''transform = vtk.vtkTransform()transform.Scale(2000,2000, 1)actor.SetUserTransform(transform)return actor  def CreateScene():# Create a rendering window and rendererren = vtk.vtkRenderer()#renWin = vtk.vtkRenderWindow()renWin.AddRenderer(ren)# Create a renderwindowinteractoriren = vtk.vtkRenderWindowInteractor()iren.SetRenderWindow(renWin)style = MyInteractor()style.SetDefaultRenderer(ren)iren.SetInteractorStyle(style)for id, file in enumerate(filenames):actor.append(LoadSTL(file))#actor[id].GetProperty().SetColor(blue)r = vtk.vtkMath.Random(.4, 1.0)g = vtk.vtkMath.Random(.4, 1.0)b = vtk.vtkMath.Random(.4, 1.0)actor[id].GetProperty().SetDiffuseColor(r, g, b)actor[id].GetProperty().SetDiffuse(.8)actor[id].GetProperty().SetSpecular(.5)actor[id].GetProperty().SetSpecularColor(1.0,1.0,1.0)actor[id].GetProperty().SetSpecularPower(30.0)assembly.AddPart(actor[id])# Add the actors to the scene#ren.AddActor(actor[id])# Also set the origin, position and orientation of assembly in space.assembly.SetOrigin(0, 0, 0) # This is the point about which all rotations take place #assembly.AddPosition(0, 0, 0)#assembly.RotateX(45)actor[1].SetOrigin(274, 0, 0) # initial elbow joint positionren.AddActor(assembly)# Add coordinatesaxes = CreateCoordinates()ren.AddActor(axes)# Add groundground = CreateGround()ren.AddActor(ground)# Add slider to control the robotsliderWidget_shoulder = ConfigSlider(slider_shoulder,"Shoulder Joint", 80)sliderWidget_shoulder.SetInteractor(iren)sliderWidget_shoulder.EnabledOn()sliderWidget_shoulder.AddObserver("InteractionEvent", ShoulderSliderCallback)sliderWidget_elbow = ConfigSlider(slider_elbow,"Elbow Joint", 160)sliderWidget_elbow.SetInteractor(iren)sliderWidget_elbow.EnabledOn()sliderWidget_elbow.AddObserver("InteractionEvent", ElbowSliderCallback)# Set background colorren.SetBackground(.2, .2, .2)# Set window sizerenWin.SetSize(600, 600)# Set up the camera to get a particular view of the scenecamera = vtk.vtkCamera()camera.SetFocalPoint(300, 0, 0)camera.SetPosition(300, -400, 350)camera.ComputeViewPlaneNormal()camera.SetViewUp(0, 1, 0)camera.Zoom(0.4)ren.SetActiveCamera(camera)# Enable user interface interactoriren.Initialize()iren.Start()if __name__ == "__main__":CreateScene()

下面是使用MFC搭建的机器人上位机监控平台,可以实现上述的一些基本功能。这个GIF动画使用开源软件ScreenToGif生成,非常好用!

总结

以上就是本文关于VTK与Python实现机械臂三维模型可视化详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

_python+pygame简单画板实现代码实例 _

_Python实现简单的语音识别系统 _

_Python内置模块turtle绘图详解 _

如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

VTK与Python实现机械臂三维模型可视化详解相关推荐

  1. python机械臂仿真_VTK与Python实现机械臂三维模型可视化详解

    三维可视化系统的建立依赖于三维图形平台, 如 OpenGL.VTK.OGRE.OSG等, 传统的方法多采用OpenGL进行底层编程,即对其特有的函数进行定量操作, 需要开发人员熟悉相关函数, 从而造成 ...

  2. python机械臂仿真_使用VTK与Python实现机械臂三维模型可视化

    三维可视化系统的建立依赖于三维图形平台, 如 OpenGL.VTK.OGRE.OSG等, 传统的方法多采用OpenGL进行底层编程,即对其特有的函数进行定量操作, 需要开发人员熟悉相关函数, 从而造成 ...

  3. 多自由度机械臂运动学正-逆解|空间轨迹规划控制|MATLAB仿真+实际机器调试

    多自由度机械臂运动学正-逆解|空间轨迹规划控制|MATLAB仿真+实际机器调试 ) DH建模法可以参考这个博客: 还有<机器人>这本书,一定要理论实践相结合,理解后可以用几何法建模也可以用 ...

  4. MATLAB机器人机械臂运动学正逆解、动力学建模仿真与轨迹规划

    MATLAB机器人机械臂运动学正逆解.动力学建模仿真与轨迹规划,雅克比矩阵求解.蒙特卡洛采样画出末端执行器工作空间 基于时间最优的改进粒子群优化算法机械臂轨迹规划设计 ID:4610679190520 ...

  5. 【机器人学】冗余七自由度机械臂的解析解逆解算法

    冗余七自由度机械臂的解析解逆解算法 参考 论文一 论文二 参考 -[1] An Analytical Solution for a Redundant Manipulator with Seven D ...

  6. 【机器人学】使用代数法求解3自由度拟人机械臂的逆运动学解

    这篇博客会讨论一下使用解析法求解3自由度拟人机械臂的逆解及分析. 一.机械臂的逆解 机械臂的逆运动学问题就是由给定的末端执行器位置和方向,确定机械臂各个关节变量的值.机械臂的求解方法可以分为两大类:数 ...

  7. python镜像下载包_python包详解

    干货大礼包!21天带你轻松学Python(文末领取更多福利) 点击查看课程视频地址 本课程来自于千锋教育在阿里云开发者社区学习中心上线课程<Python入门2020最新大课>,主讲人姜伟. ...

  8. python医学图像读取_对python读取CT医学图像的实例详解

    需要安装OpenCV和SimpleItk. SimpleItk比较简单,直接pip install SimpleItk即可. 代码如下: #coding:utf-8 import SimpleITK ...

  9. Python基础学习之 os 模块详解

    Python基础学习之 os 模块详解 文章目录 Python基础学习之 os 模块详解 1. 路径操作 1.1 os.chdir(),切换当前工作目录: 1.2 os.getcwd(),返回工作目录 ...

最新文章

  1. 推荐一位玩自动化的 Python 爱好者
  2. CSS3---8.盒模型
  3. CVPR2019目标检测方法进展综述
  4. C++实现软件自动更新功能
  5. 遥感影像滤波处理软件 — timesat3.2
  6. 《软件项目管理(第二版)》第 7 章——项目风险管理 重点部分总结
  7. 面向切面编程AspectJ在Android埋点的实践
  8. sqlplus登录问题
  9. 程序员编程知识经验总结
  10. 零基础入门语义分割-Task5 模型训练与验证
  11. 安全使用Mac教程 – 使用文件保险箱加密 Mac 数据
  12. Lucene查询结果高亮
  13. 一次对天翼安全网关的渗透
  14. 旅人随笔[01] 何为开源?
  15. linux安装gfortran出现错误,Fortran gfortran linux中出现“Segmentation Fault(core dumped)”错误...
  16. Euler配置yum源
  17. 记小辉人生中的第一刀
  18. 请说说CommonJS和ES module的区别
  19. Git 从0到入土 总结
  20. Java基础 学习笔记7

热门文章

  1. 好想学python 怎么猜人物_猜人物谜语大全及答案
  2. 伺服电机常用参数设置_伺服这些参数的设置很重要!切记!切记!
  3. java毕业设计售后管理系统(附源码、数据库)
  4. R-001 绘制基本图形 plot点线图,条形图,散点图
  5. YApi 接口管理平台
  6. 茴香豆的“茴”字有三种写法
  7. 广西十一届计算机应用,广西修订计算机应用基础和管理系统中计算机应用上机考核...
  8. js实现五星评分的效果
  9. 盛大云ubuntu主机配置django环境
  10. 常用数据结构——LinkedList