{"id":69,"date":"2016-05-21T14:25:49","date_gmt":"2016-05-21T18:25:49","guid":{"rendered":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/?page_id=69"},"modified":"2021-05-24T15:07:50","modified_gmt":"2021-05-24T19:07:50","slug":"kinect-code","status":"publish","type":"page","link":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/kinect-code\/","title":{"rendered":"Kinect Code"},"content":{"rendered":"<p>using System;<\/p>\n<p>using System.Collections.Generic;<\/p>\n<p>using System.Linq;<\/p>\n<p>using System.Text;<\/p>\n<p>using System.Windows;<\/p>\n<p>using System.Windows.Controls;<\/p>\n<p>using System.Windows.Data;<\/p>\n<p>using System.Windows.Documents;<\/p>\n<p>using System.Windows.Input;<\/p>\n<p>using System.Windows.Media;<\/p>\n<p>using System.Windows.Media.Imaging;<\/p>\n<p>using System.Windows.Navigation;<\/p>\n<p>using System.Windows.Shapes;<\/p>\n<p>using Microsoft.Kinect;<\/p>\n<p>using System.Collections;<\/p>\n<p>using System.IO.Ports;<\/p>\n<p>&nbsp;<\/p>\n<p>public class kinect1<\/p>\n<p>{<\/p>\n<p>public kinect1()<\/p>\n<p>{<\/p>\n<p>InitializeComponent();<\/p>\n<p>#include &lt;kdl\/frames.hpp&gt; \/\/ For KDL::Vector, KDL:Rotation, etc<\/p>\n<p>XnFloat* m; \/\/ Temporary variable for accessing matrix elements<\/p>\n<p>\/\/ Get torso xyz position<\/p>\n<p>XnSkeletonJointPosition xn_pos_torso;<\/p>\n<p>UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_TORSO, xn_pos_torso);<\/p>\n<p>KDL::Vector torso(joint_pos_torso.position.X, joint_pos_torso.position.Y, joint_pos_torso.position.Z);<\/p>\n<p>\/\/ Get torso rpy rotation<\/p>\n<p>XnSkeletonJointOrientation xn_orient_torso;<\/p>\n<p>UserGenerator.GetSkeletonCap().GetSkeletonJointOrientation(user, XN_SKEL_TORSO, xn_orient_torso);<\/p>\n<p>m = xn_orient_torso.orientation.elements;<\/p>\n<p>KDL::Rotation torso_rotation(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);<\/p>\n<p>\/\/Get right shoulder xyz position<\/p>\n<p>XnSkeletonJointPosition xn_pos_r_shoulder;<\/p>\n<p>UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_RIGHT_SHOULDER, xn_pos_r_shoulder);<\/p>\n<p>KDL::Vector right_shoulder(xn_pos_r_shoulder.position.X, xn_pos_r_shoulder.position.Y, xn_pos_r_shoulder.position.Z);<\/p>\n<p>\/\/ Get left shoulder xyz position<\/p>\n<p>XnSkeletonJointPosition xn_pos_l_shoulder;<\/p>\n<p>UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_LEFT_SHOULDER, xn_pos_l_shoulder);<\/p>\n<p>KDL::Vector left_shoulder(xn_pos_l_shoulder.position.X, xn_pos_l_shoulder.position.Y, xn_pos_l_shoulder.position.Z);<\/p>\n<p>\/\/ Get left shoulder rpy rotation<\/p>\n<p>XnSkeletonJointOrientation xn_orient_l_shoulder;<\/p>\n<p>UserGenerator.GetSkeletonCap().GetSkeletonJointOrientation(user, XN_SKEL_LEFT_SHOULDER, xn_orient_l_shoulder);<\/p>\n<p>m = xn_orient_l_shoulder.orientation.elements;<\/p>\n<p>KDL::Rotation left_shoulder_rotation(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);<\/p>\n<p>\/\/Get left elbow xyz position&#8217;<\/p>\n<p>XnSkeletonJointPosition xn_pos_l_elbow;<\/p>\n<p>UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_LEFT_ELBOW, xn_pos_l_elbow);<\/p>\n<p>KDL::Vector left_elbow(xn_pos_l_elbow.position.X, xn_pos_l_elbow.position.Y, xn_pos_l_elbow.position.Z);<\/p>\n<p>\/\/ Get left hand xyz position<\/p>\n<p>XnSkeletonJointPosition xn_pos_l_hand;<\/p>\n<p>UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_LEFT_HAND, xn_pos_l_hand);<\/p>\n<p>KDL::Vector left_hand(xn_pos_l_hand.position.X, xn_pos_l_hand.position.Y, xn_pos_l_hand.position.Z);<\/p>\n<p>\/\/ We need this inverse rotation to correct all of the other joints&#8217; XYZ and RPY into a torso relative space.<\/p>\n<p>KDL::Rotation torso_rotation_inverse = torso_rotation.Inverse();<\/p>\n<p>\/\/ Right shoulder position &#8211; remove torso rotation and translation<\/p>\n<p>right_shoulder = right_shoulder &#8211; torso;<\/p>\n<p>right_shoulder = torso_rotation_inverse * right_shoulder;<\/p>\n<p>\/\/ Left shoulder rotation &#8211; remove torso rotation and extract angles<\/p>\n<p>left_shoulder_rotation = left_shoulder_rotation * torso_rotation_inverse;<\/p>\n<p>double left_shoulder_roll, left_shoulder_pitch, left_shoulder_yaw;<\/p>\n<p>left_shoulder_rotation.GetRPY(left_shoulder_roll, left_shoulder_pitch, left_shoulder_yaw);<\/p>\n<p>\/\/ Left shoulder position &#8211; remove torso rotation and translation<\/p>\n<p>left_shoulder = left_shoulder &#8211; torso;<\/p>\n<p>left_shoulder = torso_rotation_inverse * left_shoulder;<\/p>\n<p>\/\/ Left elbow position &#8211; remove torso rotation and translation<\/p>\n<p>left_elbow = left_elbow &#8211; torso;<\/p>\n<p>left_elbow = torso_rotation_inverse * left_elbow;<\/p>\n<p>\/\/ Left hand position &#8211; remove torso rotation and translation<\/p>\n<p>left_hand = left_hand &#8211; torso;<\/p>\n<p>left_hand = torso_rotation_inverse * left_hand;<\/p>\n<p>\/\/ Now all of our data considers their (X,Y,Z) and (R,P,Y) to have their (0,0,0) at the torso rather than at the Kinect camera.<\/p>\n<p>\/\/ These coordinates are now ready to process to create useful joint angles to send to a robot.<\/p>\n<p>\/\/ The following vectors are normalized so that when we create triangles out of them we can treat them as being within the unit circle, and the trigonometry is simplified.<\/p>\n<p>\/\/ These first two vectors have the shoulder as the origin. Useful for calculating left shoulder pitch and roll<\/p>\n<p>KDL::Vector left_shoulder_right_shoulder = right_shoulder &#8211; left_shoulder;<\/p>\n<p>left_shoulder_right_shoulder.Normalize();<\/p>\n<p>KDL::Vector left_shoulder_elbow = left_elbow &#8211; left_shoulder;<\/p>\n<p>left_shoulder_elbow.Normalize();<\/p>\n<p>\/\/ These last two vectors have the elbow as the origin. Useful for calculating the elbow angle.<\/p>\n<p>KDL::Vector left_elbow_shoulder = left_shoulder &#8211; left_elbow;<\/p>\n<p>left_elbow_shoulder.Normalize();<\/p>\n<p>KDL::Vector left_elbow_hand = left_hand &#8211; left_elbow;<\/p>\n<p>left_elbow_hand.Normalize();<\/p>\n<p>static double robot_left_shoulder_angle_roll = 0;<\/p>\n<p>if (xn_pos_r_shoulder.fConfidence &gt;= 0.9 &amp;&amp; xn_pos_l_elbow.fConfidence &gt;= 0.9 &amp;&amp; xn_pos_l_shoulder.fConfidence &gt;= 0.9)<\/p>\n<p>{<\/p>\n<p>\/\/ Calculate the angle between two vectors. By comparing the left elbow, left shoulder, and right shoulder positions, we can get the inner angle.<\/p>\n<p>robot_left_shoulder_angle_roll = acos(KDL.dot(left_shoulder_elbow, left_shoulder_right_shoulder));<\/p>\n<p>\/\/ Shift the angle to consider arms down as zero position<\/p>\n<p>robot_left_shoulder_angle_roll = robot_left_shoulder_angle_roll &#8211; HALFPI;<\/p>\n<p>}<\/p>\n<p>static double robot_left_shoulder_angle_pitch = 0;<\/p>\n<p>\/\/ static: if a confidence check fails, previous iteration&#8217;s value is used.<\/p>\n<p>if (xn_pos_l_shoulder.fConfidence &gt;= 0.9 &amp;&amp; xn_pos_l_elbow.fConfidence &gt;= 0.9)<\/p>\n<p>{<\/p>\n<p>\/\/ Remember, Y from the Kinect coordinate system is actually Z on the robot.<\/p>\n<p>\/\/ This considers a triangle where the hypotenuse is your arm.<\/p>\n<p>\/\/ We want to take the inverse sign of the forward component of your arm to calculate the angle that we should send to the robot&#8217;s pitch joint.<\/p>\n<p>robot_left_shoulder_angle_pitch = asin(left_shoulder_elbow.y());<\/p>\n<p>\/\/ Shift the angle to consider arms down as zero position<\/p>\n<p>robot_left_shoulder_angle_pitch = robot_left_shoulder_angle_pitch + HALFPI;<\/p>\n<p>}<\/p>\n<p>\/\/ left shoulder yaw<\/p>\n<p>static double left_shoulder_angle_yaw = 0;<\/p>\n<p>if (xn_pos_l_shoulder.fConfidence &gt;= 0.9)<\/p>\n<p>{<\/p>\n<p>\/\/ In this case, we can take the rotation directly from the Kinect data.<\/p>\n<p>\/\/ However, this method isn&#8217;t very reliable.<\/p>\n<p>\/\/ The rotational information for joints frmo NITE is very unreliable.<\/p>\n<p>\/\/ In certain positions of the user&#8217;s arms, this method will fail.<\/p>\n<p>\/\/ I suggest that you try to make a better trigonometric solution.<\/p>\n<p>\/\/ Remember, robot yaw = kinect roll because robot Z = kinect Y<\/p>\n<p>left_shoulder_angle_yaw = left_shoulder_roll;<\/p>\n<p>}<\/p>\n<p>static double robot_left_elbow_angle = 0;<\/p>\n<p>if (xn_pos_l_hand.fConfidence &gt;= 0.9 &amp;&amp; xn_pos_l_elbow.fConfidence &gt;= 0.9 &amp;&amp; xn_pos_l_shoulder.fConfidence &gt;= 0.9)<\/p>\n<p>{<\/p>\n<p>\/\/ calculate the angle between two vectors.<\/p>\n<p>\/\/ by comparing the left shoulder, left elbow, and left hand positions, we can get the inner angle<\/p>\n<p>robot_left_elbow_angle = acos(KDL.dot(left_elbow_hand, left_elbow_shoulder));<\/p>\n<p>\/\/ Shift the angle to consider arms down as zero position<\/p>\n<p>robot_left_elbow_angle = left_elbow_angle &#8211; PI;<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Microsoft.Kinect; using System.Collections; using System.IO.Ports; &nbsp; public class kinect1 { public kinect1() { InitializeComponent(); #include &lt;kdl\/frames.hpp&gt; \/\/ For KDL::Vector, KDL:Rotation, etc XnFloat* m; \/\/ Temporary variable for accessing [&hellip;]<\/p>\n","protected":false},"author":9,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-69","page","type-page","status-publish","hentry","post-preview"],"_links":{"self":[{"href":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/wp-json\/wp\/v2\/pages\/69","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/wp-json\/wp\/v2\/comments?post=69"}],"version-history":[{"count":1,"href":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/wp-json\/wp\/v2\/pages\/69\/revisions"}],"predecessor-version":[{"id":71,"href":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/wp-json\/wp\/v2\/pages\/69\/revisions\/71"}],"wp:attachment":[{"href":"https:\/\/ece454designprojects.scranton.edu\/robertdudik\/wp-json\/wp\/v2\/media?parent=69"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}