<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic How do I convert from a rotation matrix to Heading, Pitch, and Roll? in .NET Maps SDK Questions</title>
    <link>https://community.esri.com/t5/net-maps-sdk-questions/how-do-i-convert-from-a-rotation-matrix-to-heading/m-p/729775#M9185</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Starting with a 3D rotation matrix, how do I compute the Heading, Pitch, and Roll values that the various 3D symbols desire?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;More Detail:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;So, given a rotation matrix that looks like this:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;[ M00, M01, M02 ]&lt;/P&gt;&lt;P&gt;[ M10, M11, M12 ]&lt;/P&gt;&lt;P&gt;[ M20, M21, M22 ]&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;And I'm trying to create a ConeMarkerSymbol.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;First I tried this computation (&lt;A href="http://planning.cs.uiuc.edu/node103.html"&gt;source&lt;/A&gt;&lt;span class="lia-unicode-emoji" title=":disappointed_face:"&gt;😞&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Heading = Math.Atan2(M10, M00) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;Pitch = Math.Atan2(-M20, Math.Sqrt(M21 * M21 + M22 * M22)) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;Roll = Math.Atan2(M21, M22) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;But that didn't yield the correct results.&amp;nbsp; Then I tried this computation (&lt;A href="http://stackoverflow.com/questions/11514063/extract-yaw-pitch-and-roll-from-a-rotationmatrix"&gt;source&lt;/A&gt;&lt;span class="lia-unicode-emoji" title=":disappointed_face:"&gt;😞&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Heading = Math.Atan2(M20, M21) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;Pitch = Math.Acos(M22) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;Roll = -Math.Atan2(M02, M12) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;But that didn't get it either.&amp;nbsp; What's the correct calculation?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Even More Details:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I'm doing all of my business logic using a state planar projection and then converting it to WGS84 to display it in a SceneView.&amp;nbsp; The GraphicsLayer is using a SurfacePlacement of Absolute and I'm able to place all of the objects correctly, but getting them oriented properly is a challenge.&amp;nbsp; I am able to render the objects in an DirectX window with the correct orientation, so I think the rotation matrix is correct,&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I'm using C# and the .NET runtime SDK.&amp;nbsp; Thanks in advance!&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Fri, 18 Sep 2015 02:32:17 GMT</pubDate>
    <dc:creator>meme2</dc:creator>
    <dc:date>2015-09-18T02:32:17Z</dc:date>
    <item>
      <title>How do I convert from a rotation matrix to Heading, Pitch, and Roll?</title>
      <link>https://community.esri.com/t5/net-maps-sdk-questions/how-do-i-convert-from-a-rotation-matrix-to-heading/m-p/729775#M9185</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Starting with a 3D rotation matrix, how do I compute the Heading, Pitch, and Roll values that the various 3D symbols desire?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;More Detail:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;So, given a rotation matrix that looks like this:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;[ M00, M01, M02 ]&lt;/P&gt;&lt;P&gt;[ M10, M11, M12 ]&lt;/P&gt;&lt;P&gt;[ M20, M21, M22 ]&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;And I'm trying to create a ConeMarkerSymbol.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;First I tried this computation (&lt;A href="http://planning.cs.uiuc.edu/node103.html"&gt;source&lt;/A&gt;&lt;span class="lia-unicode-emoji" title=":disappointed_face:"&gt;😞&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Heading = Math.Atan2(M10, M00) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;Pitch = Math.Atan2(-M20, Math.Sqrt(M21 * M21 + M22 * M22)) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;Roll = Math.Atan2(M21, M22) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;But that didn't yield the correct results.&amp;nbsp; Then I tried this computation (&lt;A href="http://stackoverflow.com/questions/11514063/extract-yaw-pitch-and-roll-from-a-rotationmatrix"&gt;source&lt;/A&gt;&lt;span class="lia-unicode-emoji" title=":disappointed_face:"&gt;😞&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Heading = Math.Atan2(M20, M21) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;Pitch = Math.Acos(M22) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;Roll = -Math.Atan2(M02, M12) * (180 / Math.PI)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;But that didn't get it either.&amp;nbsp; What's the correct calculation?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Even More Details:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I'm doing all of my business logic using a state planar projection and then converting it to WGS84 to display it in a SceneView.&amp;nbsp; The GraphicsLayer is using a SurfacePlacement of Absolute and I'm able to place all of the objects correctly, but getting them oriented properly is a challenge.&amp;nbsp; I am able to render the objects in an DirectX window with the correct orientation, so I think the rotation matrix is correct,&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I'm using C# and the .NET runtime SDK.&amp;nbsp; Thanks in advance!&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Fri, 18 Sep 2015 02:32:17 GMT</pubDate>
      <guid>https://community.esri.com/t5/net-maps-sdk-questions/how-do-i-convert-from-a-rotation-matrix-to-heading/m-p/729775#M9185</guid>
      <dc:creator>meme2</dc:creator>
      <dc:date>2015-09-18T02:32:17Z</dc:date>
    </item>
    <item>
      <title>Re: How do I convert from a rotation matrix to Heading, Pitch, and Roll?</title>
      <link>https://community.esri.com/t5/net-maps-sdk-questions/how-do-i-convert-from-a-rotation-matrix-to-heading/m-p/729776#M9186</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Calculation:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class TaitBryanAngles&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static TaitBryanAngles FromMatrix(Matrix3D matrix)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; double psi, theta, phi;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!(matrix.M02 == 1 || matrix.M02 == -1))&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; theta = -Math.Asin(matrix.M02);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; psi = Math.Atan2(matrix.M12, matrix.M22);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; phi = Math.Atan2(matrix.M01, matrix.M00);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; phi = 0.0;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (matrix.M02 == -1)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; theta = Math.PI / 2;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; psi = phi + Math.Atan2(matrix.M10, matrix.M20);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; theta = -Math.PI / 2;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; psi = -phi + Math.Atan2(-matrix.M10, -matrix.M20);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new TaitBryanAngles(phi * 180 / Math.PI, psi * 180 / Math.PI, theta * 180 / Math.PI);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public TaitBryanAngles(double heading, double roll, double pitch)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Heading = heading;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Roll = roll;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pitch = pitch;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public double Heading { get; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public double Roll { get; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public double Pitch { get; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Explanation:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The values that are expected are the &lt;A href="https://en.wikipedia.org/wiki/Euler_angles#Tait.E2.80.93Bryan_angles"&gt;Tait-Bryan&lt;/A&gt; XYZ angles.&amp;nbsp; In order to derive these angles, I followed this paper here:&lt;/P&gt;&lt;P&gt;&lt;A href="http://staff.city.ac.uk/~sbbh653/publications/euler.pdf" title="http://staff.city.ac.uk/~sbbh653/publications/euler.pdf"&gt;http://staff.city.ac.uk/~sbbh653/publications/euler.pdf&lt;/A&gt;&lt;/P&gt;&lt;P&gt;In that paper, they derive the ZYX angles.&amp;nbsp; However, the API expects the XYZ angles.&amp;nbsp; So, I followed the same procedure with a different order of the rotation matrix multiplication and arrived at the answer given above.&amp;nbsp; Hopefully this is helpful for someone else!&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Wed, 30 Sep 2015 14:58:01 GMT</pubDate>
      <guid>https://community.esri.com/t5/net-maps-sdk-questions/how-do-i-convert-from-a-rotation-matrix-to-heading/m-p/729776#M9186</guid>
      <dc:creator>meme2</dc:creator>
      <dc:date>2015-09-30T14:58:01Z</dc:date>
    </item>
  </channel>
</rss>

