User Tools

Site Tools


dasl_tutorial_hdt_arm_1_move_home_desired_position

DASL Tutorial HDT ARM #1 “How to move from Home to desired (x,y,z) position” in C/C++

The purpose of this tutorial is to teach a beginner how to control the HDT arm to move from one position to another position that is input by the user shown here: HDT Arm Movement Tutorial #1.

Authors

Pre-requisites

  • C++ (some knowledge is necessary)
  • ROS (some knowledge is helpful)
  • Basic Linux terminal navigation
  • How to Move A HDT MK2 Arm: hdt_setup

Tutorial completion time

<1 hr

Expectations

  • The coding file is changed between this tutorial and the next, so referenced lines numbers may change slightly, to counteract this, we made the following pdf document for an exact reference, so you should download the following document mk2_ik_getting_offset.cpp_final_.pdf which directly matches the code needed for this tutorial.
  • Since the coding file is changed between this tutorial and the next, you may have to undo the changes made to the coding file shown as the document referenced above and make them match.

Note for safe working conditions

Please do not crash the HDT arm into anything, so keep the workspace clear of any obstacles. If this cannot be avoided, or other unsafe conditions arise, press 'Ctrl+C' as an e-stop, on the keyboard.

How to control the HDT arm

First, you should turn on the power source, found underneath the HDT workspace.

This will take you to the proper file location:

$  cd /catkin_ws/src/mk2_controller/launch
$  roslaunch min_proj.launch // while in the above directory

Running this launch file allows you to move to a desired position. When you run this launch file named min_proj.launch, it will run Rviz to visualize the current state of the robot, as well as the main C++ script to control the arm. The launch file leads to the terminal control of the robot.

Let’s check the cpp file. The cpp file name is: mk2_ik_getting_offset.cpp

110     while(nh_.ok())
111     {
112     
113     
114     if(homePose_flag)
115     {
116          tf::poseEigenToMsg(end_effector_state, actual_end_effector_);
117          msg.header.stamp = ros::Time::now();
118          msg.name = joint_names;
119          msg.position = initial_joint_values;
120          
121          msg.velocity = vel;
122          joint_pub_.publish(msg);
123     }

Note that any two positions equal to zero sets the 'homePose_Flag' to go to the home position, e.g. (X,Y,Z) = (0, 0, 0.5) → homePose_Flag == true.

The if statement above checks if the robot is in its home position, we can send a new position.

124      //finding setfromik, changing jointstategroup
125      else
126      {
127           tf::poseMsgToEigen(actual_end_effector_, new_end_effector_state);
128          
129           bool found_ik = kinematic_state->setFromIK(joint_state_group,
130                new_end_effector_state, 10, 0.1);
131          
132           if (found_ik) //sets up the motion
133           {
134                kinematic_state->copyJointGroupPositions(joint_state_group, joint_values);
135               
136                msg.header.stamp = ros::Time::now();
137                msg.name = joint_names;
138                msg.position = joint_values;
139                msg.velocity = vel;
140                joint_pub_.publish(msg);
141               
142               
143               
144                std::cout << "\n Each joint target: \n";
145                std::cout << "joint: ";
146                std::copy(joint_values.begin(), joint_values.end(), std::ostream_iterator<double>(std::cout, "\n joint: "));
147                std::cout << "\n";
148           }
149           else
150           {
151                ROS_INFO("Did not find IK solution");
152           }
153      }

The sentence ‘tf::poseMsgToEigen’ got a new effect at the end of coding. In the case that the HDT arm is not in the home position, this 'else' statement sets the position for a found solution. Now, as seen in the image below, the robot then is in idle, waiting for an X, Y, and Z coordinate, since the while loop condition to repeatedly run is 'nh_.ok()' ('Ctrl+C' is not entered, or other failsafe conditions not met). Since we have 'std::cin' stuck in a while loop, the program waits for the user to input the coordinate positions and then repeats until the user uses 'Ctrl+C' to end the program.

After putting in the X, Y, and Z coordinate, the next iteration of the while loop will then enter the else case (no longer in home position). Continually, another ‘if’ function came. It divides whether you got ‘found IK’ from a new effect or not. If the robot continues, it is because 'found_ik' is true, if it is not true, then an IK solution is not found, and the arm cannot continue.

Typing position structure / Adjusting wrist angle.

154      std::cout << "Hi I`m Min \n"; // terminal begin output
155      float ad_x = 0.295; // x initial value
156      // Y&Z is opposite direction
157      float ad_y = -0.249; // y initial value
158      float ad_z = -0.5; // z initial value
159      // float joint_8 = -0.5;
// 160-164 spaced lines
165      homePose_flag = false;
166      std::cin >> ad_x; // user input position in x ,y(line 167),z(line 168)
167      std::cin >> ad_y; 
168      std::cin >> ad_z; 
169      
170      
171      std::cout << " final point: " << ad_x << "," << ad_y << "," << ad_z << "\n"; // print out input values

Below the sentence means that if you enter x=0, the robot goes to homepose_flag(=home). Then, the robot receives the position, it will go to the position using the line ’actual_end_effector_.position.(x,y,z).'

173      if(ad_x == 0)
174      {
175           homePose_flag = true;
176           ROS_INFO("If you entered z < 0.28, plz enter z > 0.28"); // safety z
// skip 177-251 (comments)
252           ad_x += (-0.2); // x offset
253           ad_y += (0);
254           ad_z += (0);
255           //'joint_6' += (0);
256           //change Y&Z axis direction
257           ad_y = (-ad_y);
258           ad_z = (-ad_z);
259           //'joint_6' = (-'joint_6');
260           //std::cout<< x_ad;
261           
262           
263           actual_end_effector_.position.x = ad_x; // set input values to 
264           actual_end_effector_.position.y = ad_y;
265           actual_end_effector_.position.z = ad_z;

Also, we can adjust wrist angle. This used the concept of Quaternion, see the video for some background: https://www.youtube.com/watch?v=zjMuIxRvygQ

267           actual_end_effector_.orientation.x = 0.0; // end-effector x-position
268           actual_end_effector_.orientation.y = -0.7071068; // end-effector y-position
269           actual_end_effector_.orientation.z = 0.0; // end-effector z-position
270           actual_end_effector_.orientation.w = 0.7071068; // end-effector w-orientation

For better understanding of the above program lines, 267-270, consider a cylinder that has position x,y,z, and can rotate, w. One can think of the end of the robot arm, the end-effector control, as the cylinder that has positions and rotation.

Then consider an inertial plane as shown in the picture below, that is, an airplane “pitching” by the Y-axis is going to collide with the Z-axis. Or simply, in the context of a robot arm, any rotation about a joint that is too great may lead to the robot arm colliding with another part of the arm. So, to prevent this from happening we can use quaternion.

If you want to change the angle, you can use a quaternion calculator: https://www.andre-gaschler.com/rotationconverter/. Though it is not covered in depth here, you can change the orientation of the “end-effector” with this calculator and set the previous coding 'actual_end_effector_.orientation.x', for example, according to the calculator values. Now, the coding makes operating wrist parallel with table. On the other hand, if putting 0,0,0,0 on quaternion values, it makes operating wrist vertical with table: the cylinder's zy-plane will be parallel with the workspace plane.

You can see the wrist head perpendicular/vertical to the table. If you want to give another function to use, you can change the hands tool. The current setup is good for a downward facing pick and place task using a granular jamming gripper for example. Specifically, this is the xz-plane parallel with the workspace plane.

How to make a coding update

First, choose an update file. Coming from the 'launch' directory, choose the 'mk2_controller' directory using:

To shift back to the previous directory. And then, using following command in the command line

$  make

When you clicked make, you updated the coding to robot. If the 'make' failed, perhaps there is an error in the current configuration. Ignoring any warnings, if the prompt shows a 100% build, then it is ready to use.

Note that you must 'make' the project again with each change that you have, or else you are using an old version of the program

dasl_tutorial_hdt_arm_1_move_home_desired_position.txt · Last modified: 2023/12/18 13:05 by jdowd