Clear Filters
Clear Filters

Why Does dcm2angle Work Like This?

61 views (last 30 days)
Paul on 19 May 2024 at 18:41
Commented: William Rose on 20 May 2024 at 0:07
Suppose I have a direction cosine matrix, brought to my attention by a colleague
C = round(angle2dcm(-pi/2,-pi/2,0,'ZYX'))
C = 3x3
0 0 1 1 0 0 0 1 0
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Extract the angles with @doc:dcm2angle (Aerospace Toolbox) using the Default option
[a1,a2,a3] = dcm2angle(C,'ZYX','Default');[a1,a2,a3]
ans = 1x3
0 -1.5708 0
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Because the middle angle is -pi/2, the extracted angle triplets have multiple solutions, but the default result isn't one of them.
Sometime after R2019b and before or at R2022a, an additonal optional argument can be specified, though I could find nothing about this new argument in the release notes nor the bug fixes.
[a1,a2,a3] = dcm2angle(C,'ZYX','Robust');[a1,a2,a3]
ans = 1x3
-1.5708 -1.5708 0
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Now we get a correct answer.
Trying with @doc:rotm2eul that's used in other toolboxes (Robotics, Navigation, UAV) we see that it returns a correct result without any optional arguments.
eul = rotm2eul(C.','ZYX')
eul = 1x3
0 -1.5708 -1.5708
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
ans = 3x3
0 0 1 1 0 0 0 1 0
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
@doc:dcm2angle with the Robust option actually computes two sets of angles, then computes the DCM with each set, and then compares the recomputed DCMs to the input DCM, and then returns the set of angles that result in a DCM that's closest to the input. @doc:rotm2eul uses a different approach altogether, though is limited to only three axes sequences.
To be sure, the Default option with @doc:dcm2angle is considerably faster than Robust, but Robust appears to take the same amout of time as @doc:rotm2eul
timeit(@() dcm2angle(repmat(C,1,1,1e5),'ZYX','Default'),3)
ans = 0.0065
timeit(@() dcm2angle(repmat(C,1,1,1e5),'ZYX','Robust'),3)
ans = 0.0101
timeit(@() rotm2eul(repmat(C.',1,1,1e5),'ZYX'),1)
ans = 0.0110
Does anyone have a thought as to why dcm2angle is implemented as it is with Default and forces the user to use Robust? And why wouldn't that same reason apply to rotm2eul?
Once MathWorks realized that dcm2angle Default was returning incorrect results in some cases, why patch it with Robust and keep Default instead of just fixing the bug?
Paul on 19 May 2024 at 19:51
Hi William,
As to the first part, If you haven't see it already, check out this answer from @Steven Lord (in his personal capacity).
Following this logic, it would be difficult for MathWorks to address any bug, for which a user has found their own workaround, without implementing the correction through some other means, like an optional argument as in the case of dcm2angle.
I might be able to be convinced otherwise, but the Default implementation is a bug and the way to fix a bug is to fix the bug. Users with critical processes should always check the release notes for bug fixes and behavior changes, though in this case the Robust option wasn't captured as either for R2021b, where it first shows up in the doc page.
William Rose
William Rose on 20 May 2024 at 0:07
@Paul, good points. And thanks for the link.

Sign in to comment.

Answers (0)


Find more on Quadcopters and Drones in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!