【qml-11】Quick3D实现机器人欧拉旋转、拖动视角

背景:

上一篇记录了使用Quick3D实现了一个晶圆机器人示教器的展示。更多是从零开始的实现思路。在制作过程中,有些问题比较头疼,甚至是有悖于人类的正常思维的。所以本次主要记录曾有疑问的要点。

因为我接触这些不超过三天,所以谈不上学术性,只能是个人记录。看官若要得到权威理论,还是要看正规著作。

坐标轴:

默认坐标轴是眼睛面向屏幕而言:x轴向右,y轴向上,z轴向外。

我得到模型默认也是这样的。

机器人组合完也是这样的:

上图已经加上颜色了。

所以组合时一定要记着这个规律。最后要实现最终想要的效果,是一定要进行整体旋转的。

用右手表示xyz轴时,大拇指x,食指y,中指z。

旋转方向:

旋转的概念是以坐标轴为基础而言的,以中学平面解析几何为例,x轴向右,y轴向上。假设以原点为轴,画一条直线与x轴夹角30度。

这种再常见不过的概念,在3d世界里叫围绕z轴转30度。

因为只看xy平面时,z轴正好是垂直屏幕向外的,也就是冲着人类眼睛的。

所谓对那个轴旋转,就是围绕这个轴旋转。这个轴的正数方向正对眼睛,角度是以平面几何的方向计算的,也就是逆时针方向是增大,顺时针是减小。

其实就是物理电学中的右手定则,大拇指指向坐标轴正数方向,四指弯曲指向角度增长方向。

欧拉旋转eulerRotation:

欧拉旋转的单位是角度,也是通常推荐使用的方式。还有四元旋转,我试过意义不大,实际开发中欧拉旋转即可。

三维空间旋转都是围绕坐标轴而言的,可以一次性指定三个轴的旋转角度:

eulerRotation:Qt.vector3d(40, 40, 40)

也可以分别指定:

eulerRotation.x:30

eulerRotation.y:60

eulerRotation.z:90

Qt.vector3d这个函数很有用,通常用于为三个轴指定参数。

**重要的是,欧拉旋转是有顺序的,qt手册里提到顺序概念,是zxy,但我试出来是yxz。亦即如果要依次围绕xyz轴旋转,得按照这个顺序,否则就万向节锁死。**啥叫锁死?实践中就是比如:

起始默认:x轴向右,y轴向上,z轴垂直屏幕向外。

我们希望某物体旋转时,xyz轴的三维空间能够保持。但实际是得按顺序逐个转,如果不按顺序,后转的轴就会保持上次的方向,不跟随三维空间一起转。

以上面的机器人为例,先看正确顺序yxz:

上面依次旋转90度,自己一边比划一边看,是正确的。

如果按照一个错误的顺序,比如xyz或者xzy再试试:

x之后,y旋转时,显然y还是初始方向,以向上为基准转的右手定则。后面z向下本来是对的,但因为前面y错了,所以z旋转又把y那次转回来了,最终还是错。

x之后,z旋转时,z向下是对的,因为z本来就该在x之后。再y旋转时,还是等于y向上做的右手定则,最终错。

所以我是尝试了很多次才明确,旋转的顺序就是yxz。

至于顺序影响结果的原因,AI说与矩阵算法有关,如果不是专门搞这个的,可以不深究,知道这个特性即可。

单位分离:

上述欧拉旋转的顺序问题,前提是针对一个3d单位进行xyz旋转。

实际制作时,机器人各关节都是独立的Model(node),机器人整体也是大环境的子node。

所以无论大场景怎么错,机器人再转也是对的,因为它是独立的单位。

会写程序的朋友已经想到,咱就使用node套壳不就行了,三层壳,分别管xyz轴。实际不对。因为咱们希望无论转哪个轴,另外两个轴的方向要随着三维空间联动。分层的话都是绝对方向,等于人为"万向节锁死"了。如果说非要进行某种计算才满足要求,我认为研究方向就错了,就不该较这个真,因为做项目需要效率,在一个问题上坑挖得太深,不是工程思维。搞不好都没信心继续了。

但分层控制有时候又是必须的,比如局部旋转,它本身就是相对的,而且只转一个轴,升降属于平移,不影响,做关节最合适了。

三维观察:

上面说了那么多旋转的问题,其实最初我想要物体任意顺序转都是对的,就是想实现三维空间上各角度观察物体。最好能用鼠标拖拽改变视角。

曾经想过转相机,思路就不对,因为所谓旋转都是对自己而言,直接转不行。

最终发现很简单,给View3D加个子节点即可:

javascript 复制代码
    WasdController {
        controlledObject: scene
        xSpeed: -0.1
        ySpeed: -0.1
    }

这个WasdController默认就可以拖拽转视角,但也是相对于被控制的那个node本身的,所以人眼看起来正好相反。

比如鼠标往上拖拽:一般我们是想把物体底面翻上来,但默认正好相反,物体会绕x轴正转(逆时针角度增加),所以等于是把顶面翻下来了。

如果鼠标往左拖拽:一般我们想要把右面翻出来看,但实际物体会绕y轴正转(逆时针角度增加),所以等于是把左面翻出来了。

所以必须要把xy反过来,翻过手册,有bool型反转属性,试过不行。最后尝试把速度设为default值取反,成功了。

但这种成功是局部的,如果物体把脸扭过来,人眼还是觉得是别扭的,做好了自己试试就知道了。相对值和绝对值的作用,想要完全用拖拽实现,难顾周全。以后有空再尝试更好的做法。

可以肯定的说一种有效的方法,不用拖拽,用两个slider,一个控制场景的x轴旋转(相当于纵向翻转),一个控制机器人原地转圈(相当于横向翻转)。

总结:

使用欧拉旋转实现的各关节运动。

使用WasdController实现的拖拽视角。场景x轴控制纵向翻转,机器人z轴控制横向旋转。

使用定义属性传递数据驱动模型运动。

反之,如果用鼠标操作关节产生数据,也是可以发给设备驱动真实的机器人的。但仔细想过意义不大,还不如界面控件或者机械手柄高效。

有关quick3d的应用目前就会这些,以后有需要再继续。

本文完。

相关推荐
用户805533698035 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner5 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz10 天前
QML Hello World 入门示例
qt
xcyxiner13 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner13 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner14 天前
DicomViewer (添加模型类)3
qt
xcyxiner14 天前
DicomViewer (目录调整) 2
qt
xcyxiner14 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
zzzzzz31016 天前
假如我是掘金管理员,我先给评论区装个'代码审查'系统
python·程序员·机器人