{"id":40,"date":"2016-05-21T18:22:01","date_gmt":"2016-05-21T22:22:01","guid":{"rendered":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/?page_id=40"},"modified":"2021-05-24T15:08:15","modified_gmt":"2021-05-24T19:08:15","slug":"electronic-portfolio","status":"publish","type":"page","link":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/electronic-portfolio\/","title":{"rendered":"Electronic Portfolio"},"content":{"rendered":"<p>Below is most of the written work for the robot as well as the code and links to the Kinect libraries we used for reference.<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-26\" src=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/Resized_20160420_111130-266x300.jpeg\" alt=\"Resized_20160420_111130\" width=\"266\" height=\"300\" srcset=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/Resized_20160420_111130-266x300.jpeg 266w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/Resized_20160420_111130-768x865.jpeg 768w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/Resized_20160420_111130-909x1024.jpeg 909w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/Resized_20160420_111130-842x948.jpeg 842w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/Resized_20160420_111130.jpeg 1416w\" sizes=\"auto, (max-width: 266px) 100vw, 266px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-29 size-medium aligncenter\" src=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/IMG_1812-e1463868760476-225x300.jpg\" alt=\"IMG_1812\" width=\"225\" height=\"300\" srcset=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/IMG_1812-e1463868760476-225x300.jpg 225w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/IMG_1812-e1463868760476-768x1024.jpg 768w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/IMG_1812-e1463868760476-749x999.jpg 749w\" sizes=\"auto, (max-width: 225px) 100vw, 225px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-30\" src=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/IMG_1813-e1463868838257-225x300.jpg\" alt=\"IMG_1813\" width=\"225\" height=\"300\" srcset=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/IMG_1813-e1463868838257-225x300.jpg 225w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/IMG_1813-e1463868838257-768x1024.jpg 768w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/IMG_1813-e1463868838257-749x999.jpg 749w\" sizes=\"auto, (max-width: 225px) 100vw, 225px\" \/><\/p>\n<p>Code:<\/p>\n<div>using System;<\/div>\n<div>using System.Collections.Generic;<\/div>\n<div>using System.Linq;<\/div>\n<div>using System.Text;<\/div>\n<div>using System.Windows;<\/div>\n<div>using System.Windows.Controls;<\/div>\n<div>using System.Windows.Data;<\/div>\n<div>using System.Windows.Documents;<\/div>\n<div>using System.Windows.Input;<\/div>\n<div>using System.Windows.Media;<\/div>\n<div>using System.Windows.Media.Imaging;<\/div>\n<div>using System.Windows.Navigation;<\/div>\n<div>using System.Windows.Shapes;<\/div>\n<div>using Microsoft.Kinect;<\/div>\n<div>using System.Collections;<\/div>\n<div>using System.IO.Ports;<\/div>\n<div><\/div>\n<div>\/\/namespace kinect1<\/div>\n<div>\/\/{<\/div>\n<div>public class kinect1<\/div>\n<div>{<\/div>\n<div>public kinect1()<\/div>\n<div>{<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 InitializeComponent();<\/div>\n<div>\/\/}<\/div>\n<div>#include &lt;kdl\/frames.hpp&gt; \/\/ For KDL::Vector, KDL:Rotation, etc<\/div>\n<div><\/div>\n<div>XnFloat* m; \/\/ Temporary variable for accessing matrix elements<\/div>\n<div><\/div>\n<div>\/\/ Get torso xyz position<\/div>\n<div>XnSkeletonJointPosition xn_pos_torso;<\/div>\n<div>UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_TORSO, xn_pos_torso);<\/div>\n<div>KDL::Vector torso(joint_pos_torso.position.X, joint_pos_torso.position.Y, joint_pos_torso.position.Z);<\/div>\n<div><\/div>\n<div>\/\/ Get torso rpy rotation<\/div>\n<div>XnSkeletonJointOrientation xn_orient_torso;<\/div>\n<div>UserGenerator.GetSkeletonCap().GetSkeletonJointOrientation(user, XN_SKEL_TORSO, xn_orient_torso);<\/div>\n<div>m = xn_orient_torso.orientation.elements;<\/div>\n<div>KDL::Rotation torso_rotation(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);<\/div>\n<div><\/div>\n<div>\/\/Get right shoulder xyz position<\/div>\n<div>XnSkeletonJointPosition xn_pos_r_shoulder;<\/div>\n<div>UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_RIGHT_SHOULDER, xn_pos_r_shoulder);<\/div>\n<div>KDL::Vector right_shoulder(xn_pos_r_shoulder.position.X, xn_pos_r_shoulder.position.Y, xn_pos_r_shoulder.position.Z);<\/div>\n<div><\/div>\n<div>\/\/ Get left shoulder xyz position<\/div>\n<div>XnSkeletonJointPosition xn_pos_l_shoulder;<\/div>\n<div>UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_LEFT_SHOULDER, xn_pos_l_shoulder);<\/div>\n<div>KDL::Vector left_shoulder(xn_pos_l_shoulder.position.X, xn_pos_l_shoulder.position.Y, xn_pos_l_shoulder.position.Z);<\/div>\n<div><\/div>\n<div>\/\/ Get left shoulder rpy rotation<\/div>\n<div>XnSkeletonJointOrientation xn_orient_l_shoulder;<\/div>\n<div>UserGenerator.GetSkeletonCap().GetSkeletonJointOrientation(user, XN_SKEL_LEFT_SHOULDER, xn_orient_l_shoulder);<\/div>\n<div>m = xn_orient_l_shoulder.orientation.elements;<\/div>\n<div>KDL::Rotation left_shoulder_rotation(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);<\/div>\n<div><\/div>\n<div>\/\/Get left elbow xyz position&#8217;<\/div>\n<div>XnSkeletonJointPosition xn_pos_l_elbow;<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_LEFT_ELBOW, xn_pos_l_elbow);<\/div>\n<div>KDL::Vector left_elbow(xn_pos_l_elbow.position.X, xn_pos_l_elbow.position.Y, xn_pos_l_elbow.position.Z);<\/div>\n<div><\/div>\n<div>\/\/ Get left hand xyz position<\/div>\n<div>XnSkeletonJointPosition xn_pos_l_hand;<\/div>\n<div>UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(user, XN_SKEL_LEFT_HAND, xn_pos_l_hand);<\/div>\n<div>KDL::Vector left_hand(xn_pos_l_hand.position.X, xn_pos_l_hand.position.Y, xn_pos_l_hand.position.Z);<\/div>\n<div><\/div>\n<div>\/\/ We need this inverse rotation to correct all of the other joints&#8217; XYZ and RPY into a torso relative space.<\/div>\n<div>KDL::Rotation torso_rotation_inverse = torso_rotation.Inverse();<\/div>\n<div><\/div>\n<div>\/\/ Right shoulder position &#8211; remove torso rotation and translation<\/div>\n<div>right_shoulder = right_shoulder &#8211; torso;<\/div>\n<div>right_shoulder = torso_rotation_inverse * right_shoulder;<\/div>\n<div><\/div>\n<div>\/\/ Left shoulder rotation &#8211; remove torso rotation and extract angles<\/div>\n<div>left_shoulder_rotation = left_shoulder_rotation * torso_rotation_inverse;<\/div>\n<div>double left_shoulder_roll, left_shoulder_pitch, left_shoulder_yaw;<\/div>\n<div>left_shoulder_rotation.GetRPY(left_shoulder_roll, left_shoulder_pitch, left_shoulder_yaw);<\/div>\n<div><\/div>\n<div>\/\/ Left shoulder position &#8211; remove torso rotation and translation<\/div>\n<div>left_shoulder = left_shoulder &#8211; torso;<\/div>\n<div>left_shoulder = torso_rotation_inverse * left_shoulder;<\/div>\n<div><\/div>\n<div>\/\/ Left elbow position &#8211; remove torso rotation and translation<\/div>\n<div>left_elbow = left_elbow &#8211; torso;<\/div>\n<div>left_elbow = torso_rotation_inverse * left_elbow;<\/div>\n<div><\/div>\n<div>\/\/ Left hand position &#8211; remove torso rotation and translation<\/div>\n<div>left_hand = left_hand &#8211; torso;<\/div>\n<div>left_hand = torso_rotation_inverse * left_hand;<\/div>\n<div><\/div>\n<div>\/\/ 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.<\/div>\n<div>\/\/ These coordinates are now ready to process to create useful joint angles to send to a robot.<\/div>\n<div><\/div>\n<div>\/\/ 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.<\/div>\n<div>\/\/ These first two vectors have the shoulder as the origin. Useful for calculating left shoulder pitch and roll<\/div>\n<div><\/div>\n<div>KDL::Vector left_shoulder_right_shoulder = right_shoulder &#8211; left_shoulder;<\/div>\n<div>left_shoulder_right_shoulder.Normalize();<\/div>\n<div><\/div>\n<div>KDL::Vector left_shoulder_elbow = left_elbow &#8211; left_shoulder;<\/div>\n<div>left_shoulder_elbow.Normalize();<\/div>\n<div><\/div>\n<div>\/\/ These last two vectors have the elbow as the origin. Useful for calculating the elbow angle.<\/div>\n<div><\/div>\n<div>KDL::Vector left_elbow_shoulder = left_shoulder &#8211; left_elbow;<\/div>\n<div>left_elbow_shoulder.Normalize();<\/div>\n<div><\/div>\n<div>KDL::Vector left_elbow_hand = left_hand &#8211; left_elbow;<\/div>\n<div>left_elbow_hand.Normalize();<\/div>\n<div><\/div>\n<div>static double robot_left_shoulder_angle_roll = 0;<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 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)<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 {<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Calculate the angle between two vectors. By comparing the left elbow, left shoulder, and right shoulder positions, we can get the inner angle.<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 robot_left_shoulder_angle_roll = acos(KDL.dot(left_shoulder_elbow, left_shoulder_right_shoulder));<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Shift the angle to consider arms down as zero position<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 robot_left_shoulder_angle_roll = robot_left_shoulder_angle_roll &#8211; HALFPI;<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 }<\/div>\n<div><\/div>\n<div>static double robot_left_shoulder_angle_pitch = 0;<\/div>\n<div>\/\/ static: if a confidence check fails, previous iteration&#8217;s value is used.<\/div>\n<div><\/div>\n<div>if (xn_pos_l_shoulder.fConfidence &gt;= 0.9 &amp;&amp; xn_pos_l_elbow.fConfidence &gt;= 0.9)<\/div>\n<div>{<\/div>\n<div>\u00a0 \u00a0 \/\/ Remember, Y from the Kinect coordinate system is actually Z on the robot.<\/div>\n<div>\u00a0 \u00a0 \/\/ This considers a triangle where the hypotenuse is your arm.<\/div>\n<div>\u00a0 \u00a0 \/\/ 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.<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 robot_left_shoulder_angle_pitch = asin(left_shoulder_elbow.y());<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 \/\/ Shift the angle to consider arms down as zero position<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 robot_left_shoulder_angle_pitch = robot_left_shoulder_angle_pitch + HALFPI;<\/div>\n<div>}<\/div>\n<div><\/div>\n<div>\/\/ left shoulder yaw<\/div>\n<div>static double left_shoulder_angle_yaw = 0;<\/div>\n<div>if (xn_pos_l_shoulder.fConfidence &gt;= 0.9)<\/div>\n<div>{<\/div>\n<div>\u00a0 \u00a0 \/\/ In this case, we can take the rotation directly from the Kinect data.<\/div>\n<div>\u00a0 \u00a0 \/\/ However, this method isn&#8217;t very reliable.<\/div>\n<div>\u00a0 \u00a0 \/\/ The rotational information for joints frmo NITE is very unreliable.<\/div>\n<div>\u00a0 \u00a0 \/\/ In certain positions of the user&#8217;s arms, this method will fail.<\/div>\n<div>\u00a0 \u00a0 \/\/ I suggest that you try to make a better trigonometric solution.<\/div>\n<div>\u00a0 \u00a0 \/\/ Remember, robot yaw = kinect roll because robot Z = kinect Y<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 left_shoulder_angle_yaw = left_shoulder_roll;<\/div>\n<div>}<\/div>\n<div><\/div>\n<div>static double robot_left_elbow_angle = 0;<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 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)<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 {<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ calculate the angle between two vectors.<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ by comparing the left shoulder, left elbow, and left hand positions, we can get the inner angle<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 robot_left_elbow_angle = acos(KDL.dot(left_elbow_hand, left_elbow_shoulder));<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Shift the angle to consider arms down as zero position<\/div>\n<div><\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 robot_left_elbow_angle = left_elbow_angle &#8211; PI;<\/div>\n<div>\u00a0 \u00a0 \u00a0 \u00a0 }<\/div>\n<div><\/div>\n<div>}<\/div>\n<div>}<\/div>\n<div><\/div>\n<div>Reference library used for program was KDL and can be found here: https:\/\/github.com\/orocos\/orocos_kinematics_dynamics\/blob\/master\/orocos_kdl\/src\/frames.hpp<\/div>\n<div><\/div>\n<div>Below is photos of the robot program and Kinect program running:<\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-34\" src=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/program-300x213.png\" alt=\"program\" width=\"300\" height=\"213\" srcset=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/program-300x213.png 300w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/program-768x547.png 768w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/program-842x599.png 842w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/program.png 1023w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/> <img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-35\" src=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/robot-progrm-300x215.png\" alt=\"robot progrm\" width=\"300\" height=\"215\" srcset=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/robot-progrm-300x215.png 300w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/robot-progrm-768x550.png 768w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/robot-progrm-842x602.png 842w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/robot-progrm.png 1023w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/> <img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-36\" src=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/action-library-300x214.png\" alt=\"action library\" width=\"300\" height=\"214\" srcset=\"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/action-library-300x214.png 300w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/action-library-768x548.png 768w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/action-library-842x601.png 842w, https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-content\/uploads\/sites\/18\/2016\/05\/action-library.png 1023w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Below is most of the written work for the robot as well as the code and links to the Kinect libraries we used for reference. Code: 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 [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-40","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-json\/wp\/v2\/pages\/40","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-json\/wp\/v2\/comments?post=40"}],"version-history":[{"count":1,"href":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-json\/wp\/v2\/pages\/40\/revisions"}],"predecessor-version":[{"id":42,"href":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-json\/wp\/v2\/pages\/40\/revisions\/42"}],"wp:attachment":[{"href":"https:\/\/ece454designprojects.scranton.edu\/kinectrobot\/wp-json\/wp\/v2\/media?parent=40"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}