Bug dcm2quat函数

9的观点(30天)
亚历山德罗
亚历山德罗 2014年11月29日
编辑: 詹姆斯Tursa 2020年4月6日
我花了一天时间了解一个意想不到的行为 dcm2quat 函数(航空工具箱函数集)。四元数的函数直接余弦变换矩阵,在大多数情况下做得很好。我注意到一个问题,转换时间DCM系列:我将情节“连续”四元数的值,但是在某些样本不连续。我发现这个当DCM的跟踪变得消极。函数的实现表明,有一个if - else语句处理这个检查;调查其他功能我发现,只有在相同的情况下(如转置不受影响)——一个标志的问题。你能找到实现MATLAB(例如通过F4)。
可能有点令人困惑的我将附上一些图形更好地给我是什么意思。
我期望:
发生了什么:
在这个例子中,第一个“跳”是样本之间的1059年和1060年DCM在哪里:
T_1059 =
0.4218 -0.3220 0.8475
0.7299 -0.4339 -0.5282
0.5378 0.8414 0.0520
T_1060 =
0.4312 -0.2603 0.8639
0.7289 -0.4637 -0.5036
0.5317 0.8469 -0.0102
和corrispondent四元数的值是:
dcm2quat (T_1059) = 0.5099 - -0.6715 -0.1518 - -0.5158
dcm2quat (T_1060) = -0.4892 - 0.6901 0.1698 - 0.5055
前者是正确的,但后者应该吗
Q_1060 = 0.4892 -0.6901 -0.1698 -0.5055
我已经双重检查 euclideanspace.com 在页面的底部和java applet是否按预期运行。
这不是一个大throuble因为我注意到quat2dcm逆函数转换适当的DCM正确这两个值,但如果mainwhile操纵的四元数,应该发生的奇怪的行为。
可以建议这个问题如何?
1评论
尼克洛Werneck
尼克洛Werneck 2016年8月23日
显然你的四元数只需要一个信号改变参数变得连续,但表示旋转还是一样的。你只需要检测这些“跳跃”和乘以1。在你的情况下,因为没有连续的旋转,你可以做一个参数总是积极的。

登录置评。

答案(2)

亚历山德罗
亚历山德罗 2014年12月1日
这是正确的dcm2quat功能:
函数q = dcm2quat_mod (dcm)
如果任何(~伊斯雷尔(dcm) | | ~ isnumeric (dcm))
错误消息(航空:dcm2quat: isNotReal));
结束
如果(尺寸(dcm, 1) ~ = 3) | |(大小(dcm, 2) ~ = 3))
错误消息(航空:dcm2quat: wrongDimension));
结束
我=大小(dcm, 3): 1:1
问(我,4)= 0;
tr =跟踪(dcm(:,:我));
如果(tr > 0)
sqtrp1 =√tr + 1.0);
问(我,1)= 0.5 * sqtrp1;
问(我,2)= (dcm(2、3、我)——dcm(3 2,我))/ (2.0 * sqtrp1);
问(我,3)= (dcm(3 1我)——dcm(我)1 3)/ (2.0 * sqtrp1);
问(我,4)= (dcm(1、2、我)——dcm(2, 1,我))/ (2.0 * sqtrp1);
其他的
d =诊断接头(dcm(:,:我));
如果(((2)> = d (1) & & (d (2) > = d (3)))
%最大价值dcm(2, 2,我)
如果(dcm (3 1 i) - dcm (1、3、i) > = 0)
sqdip1 =√d (2) - (1) - d (3) + 1.0);
其他的
sqdip1 = -√(d (2) - (1) - d (3) + 1.0);
结束
问(我,3)= 0.5 * sqdip1;
如果(sqdip1 ~ = 0)
sqdip1 = 0.5 / sqdip1;
结束
问(我,1)= (dcm(3 1我)——dcm(1、3、我))* sqdip1;
问(我,2)= (dcm (1、2) + dcm(2, 1,我))* sqdip1;
问(我,4)= (dcm(2、3、我)+ dcm(3 2,我))* sqdip1;
elseif((3)> = d (1))
%最大价值dcm(3, 3,我)
如果(dcm (1、2、1) - dcm (2, 1, i) > = 0)
sqdip1 =√d (3) - (1) - d (2) + 1.0);
其他的
sqdip1 = -√(d (3) - (1) - d (2) + 1.0);
结束
问(我,4)= 0.5 * sqdip1;
如果(sqdip1 ~ = 0)
sqdip1 = 0.5 / sqdip1;
结束
问(我,1)= (dcm(1、2、我)——dcm(2, 1,我))* sqdip1;
问(我,2)= (dcm(3 1我)+ dcm(1、3、我))* sqdip1;
问(我,3)= (dcm(2、3、我)+ dcm(3 2,我))* sqdip1;
其他的
%最大价值dcm(1, - 1,我)
如果(dcm (2、3、i) - dcm (3 2 i) > = 0)
sqdip1 =√(1) - d (2) - d (3) + 1.0);
其他的
sqdip1 = -√(d (1) - (2) - d (3) + 1.0);
结束
问(我,2)= 0.5 * sqdip1;
如果(sqdip1 ~ = 0)
sqdip1 = 0.5 / sqdip1;
结束
问(我,1)= (dcm(2、3、我)——dcm(3 2,我))* sqdip1;
问(我,3)= (dcm (1、2) + dcm(2, 1,我))* sqdip1;
问(我,4)= (dcm(3 1我)+ dcm(1、3、我))* sqdip1;
结束
结束
结束
我只是添加了一个符号校验每个if语句。例如,之前只有:
sqdip1 =√d (2) - (1) - d (3) + 1.0);
现在是:
如果(dcm (3 1 i) - dcm (1、3、i) > = 0)
sqdip1 =√d (2) - (1) - d (3) + 1.0);
其他的
sqdip1 = -√(d (2) - (1) - d (3) + 1.0);
结束

詹姆斯Tursa
詹姆斯Tursa 2016年8月23日
编辑:詹姆斯Tursa 2020年4月6日
我的建议是把代码中强迫的连续性。这样你不用担心一些极端例子,并不是你的喜欢dcm2quat你碰巧使用转换器,你不必担心测试dcm2quat转换器这些边界情况。例如,假设我们总是谈论小角度变化从一个dcm到下一个(大角变化连续性的概念分解和变得毫无意义)。然后只需确保最大级组件不会改变从一步到下一个迹象。所以使用的跟踪以前的四元数,然后做比较。例如,
quat_last = [0 0 0 0];%初始化最后四元数
:
皮疹=当前dcm2quat转换的结果
(~ x) = max (abs (quat_last));%选择指数的马克斯abs最后四元数
如果(皮疹(x) * quat_last (x) < 0)%如果信号改变…
皮疹=皮疹;%翻转所有迹象
结束
quat_last =皮疹;%保存皮疹下比较
注:总是有某种迹象在任何dcm2quat转换器使用模棱两可。虽然皮疹,皮疹表示相同的“最终结果”旋转,它们可以产生完全不同的结果如果如送入控制系统(这可能会指挥操作而不是周围359度长的路1度短操作你想)。我不会标签这个标志歧义作为一个“错误”的转换器,。它是由用户来检查所需的“连续性”,一步一步的结果,并相应地调整输出。
注:
我只是看着dcm2quat的医生,有一个不正确的例子(至少在R2015a)。特别是,这
dcm = [0 1 0;1 0 0;0 0 1);
q = dcm2quat (dcm)
q =
0.7071 0 0 0
使用的扩张型心肌病是一个无效的旋转矩阵。它的行列式为1(一个x - y反射矩阵),当它应该有一个+ 1的行列式。送入dcm2quat函数时,它返回一个无效的结果(不规范化和没有错误/警告消息)。垃圾在垃圾。也许有人不理解dcm或皮疹的应该是什么样子的炮制这个例子并没有注意到这个错误。一个正确的例子是:
> > dcm = [0 1 0;1 0 0;0 0 1]
dcm =
0 1 0
1 0 0
0 0 1
> >侦破(dcm)
ans =
1
> > q = dcm2quat (dcm)
q =
0.7071 0 0 0.7071
我想我应该提交一份文档错误报告在这…
追问:24 - 8月- 2016
TMW计划修复医生与一个不同的例子,并可能改变函数抛出一个错误如果输入dcm没有足够接近正确的旋转矩阵。看到技术支持案例# 0213万博1manbetx1384。
编辑
参见讨论MATLAB工具箱四元数的约定:

类别

找到更多的在单位转换帮助中心文件交换

社区寻宝

找到宝藏在MATLAB中央,发现社区如何帮助你!

开始狩猎!