实验一 机械臂正逆运动学
一、实验目的
1、巩固正逆运动学基础概念。
2、了解正逆运动学在机械臂控制中的实际用途。
二、实验内容
1、机械臂模型DH参数的计算。
2、机械臂正运动学的计算。
3、机械臂逆运动学的计算。
三、实验步骤
1、正运动学实验验证,编写程序计算以下三组关节角度对应的末端位姿,并通过位置控制使机器人运动到相应位置,将实际末端位置与你的计算值比较,求出绝对误差。
第一组:[0.927, -0.687, -0.396, 0, 1.083, 0.927]
第二组:[0.322, -0.855, -0.021, 0, 0.877, 0.322]
第三组:[-0.322, -0.636, -0.011, 0, 0.647, -0.322]
2、逆运动学实验验证,编写程序计算以下三组末端位姿对应的关节角度,并通过位置控制使机器人运动到你计算出的位置,将实际末端位置与所给的值比较,求绝对误差。
第一组:[0.2, 0.2, 0.2007,1.57, -1.57, 0]
第二组:[0.15 ,0.2, 0.2007, 0, 0, 0]
第三组:[0.3 ,0, 0.122, 1.57, 0, 0]
四、评定标准
1、实验结果的准确性
五、注意事项
1、本实验中姿态欧拉角与ROS中一致,全部采用弧度制,坐标全部以米为单位。
2、真实机器人实验中,如果机器人发生碰撞,一定要先扶住机械臂,再按下急停按钮,否则机械臂会倒下。
3、按下急停按钮后需要手动将机械臂复原到门位置,并重置控制内部机械臂位置。
4、真实机械臂实验过程中,按下急停按钮后复位的过程中最好按照原本的运动方向复位,不要让第一关节一直向着一个方向旋转以免造成线路缠绕。
5、机械臂启动时的位置被称为初始门位置(如下图),其末端位姿为[0.2289, 0, 0.454, 1.57, 0, 0],机械臂各个关节的正方向如图所示。
代码,部分行从助教例程中直接复制,因此部分代码为无用代码,以及代码写了两次,懒得去其进行精简,所以很长。ubuntu带到win的注释乱码,也懒得修改了
正运动学
#include
#include
#include
#include
#include
#include
#include "vector"
#include "std_msgs/Float32.h"
#include "std_msgs/Float64MultiArray.h"
#include "controller_manager_msgs/SwitchController.h"
#include "controller_manager_msgs/ListControllers.h"
#include "ikfast.h"
#include "probot_anno_manipulator_ikfast_moveit_plugin.cpp"
using namespace ikfast_kinematics_plugin;
void PrintMatrix(Eigen::Matrix<double,4,4> t){
for(int i=0;i<4;i++){
cout<<setw(15)<<"| ";
for(int j=0;j<4;j++){
cout<<setw(15)<<t(i,j);
}
cout<<setw(15)<<" |"<<endl;
}
cout<<endl;
}
int main(int argc, char** argv){
bool ret;
//鑺傜偣鍒濆鍖?
ros::init(argc,argv,"forward_kinematics");
//鍒涘缓鑺傜偣鍙ユ焺瀵硅薄
ros::NodeHandle node_handle;
ros::AsyncSpinner spinner(1);
ROS_INFO_STREAM("start");
ros::Publisher pos_pub=node_handle.advertise<std_msgs::Float64MultiArray>("/probot_anno/arm_pos_controller/command",100);
ikfast_kinematics_plugin::IKFastKinematicsPlugin ik;
ret = ik.IKFastKinematicsPlugin::initialize("robot_description","manipulator","base_link","link_6",0.001);
std_msgs::Float64MultiArray init_pos;
init_pos.data.push_back(0);
init_pos.data.push_back(0);
init_pos.data.push_back(0);
init_pos.data.push_back(0);
init_pos.data.push_back(0);
init_pos.data.push_back(0);
sleep(1);
double theta[6];
//杈撳叆鍚勫叧鑺傚叧鑺傝
for(int i = 0;i<6;i++){
cout<<"鍏宠妭瑙?<: ";
cin>>theta[i];
}
theta[6] = 0;
theta[7] = 0;
init_pos.data.at(0) = theta[0];
init_pos.data.at(1) = theta[1];
init_pos.data.at(2) = theta[2];
init_pos.data.at(3) = theta[3];
init_pos.data.at(4) = theta[4];
init_pos.data.at(5) = theta[5];
//瀹氫箟DH鍙傛暟
const double DH[8][3]={ 0,0,0.284,
M_PI/2,0,0,
0,0.225,0,
M_PI/2,0,0.2289,
-M_PI/2,0,0,
M_PI/2,0,0,
0,0,0.055,
-M_PI/2,0,0};
Eigen::Matrix<double,4,4> T[8];
//璁$畻鍙樻崲鐭╅樀
for(int i=0;i<8;i++){
T[i] << cos(theta[i]),-sin(theta[i]),0,DH[i][1],
sin(theta[i])*cos(DH[i][0]),cos(theta[i])*cos(DH[i][0]),-sin(DH[i][0]),-sin(DH[i][0])*DH[i][2],
sin(theta[i])*sin(DH[i][0]),cos(theta[i])*sin(DH[i][0]),cos(DH[i][0]),cos(DH[i][0])*DH[i][2],
0,0,0,1;
}
T[1] << cos(theta[1]+M_PI/2),-sin(theta[1]+M_PI/2),0,DH[1][1],
sin(theta[1]+M_PI/2)*cos(DH[1][0]),cos(theta[1]+M_PI/2)*cos(DH[1][0]),-sin(DH[1][0]),-sin(DH[1][0])*DH[1][2],
sin(theta[1]+M_PI/2)*sin(DH[1][0]),cos(theta[1]+M_PI/2)*sin(DH[1][0]),cos(DH[1][0]),cos(DH[1][0])*DH[1][2],
0,0,0,1;
T[4]<< cos(theta[4]-M_PI/2),-sin(theta[4]-M_PI/2),0,DH[4][1],
sin(theta[4]-M_PI/2)*cos(DH[4][0]),cos(theta[4]-M_PI/2)*cos(DH[4][0]),-sin(DH[4][0]),-sin(DH[4][0])*DH[4][2],
sin(theta[4]-M_PI/2)*sin(DH[4][0]),cos(theta[4]-M_PI/2)*sin(DH[4][0]),cos(DH[4][0]),cos(DH[4][0])*DH[4][2],
0,0,0,1;
//璁$畻鏈浣嶅Э鍙樻崲鐭╅樀
Eigen::Matrix<double,4,4> result;
result << 1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1;
for(int i = 0;i<8;i++){
result = result * T[i];
//PrintMatrix(result);
}
//寰楀埌鏁版嵁
double pos_x = result(0,3);
double pos_y = result(1,3);
double pos_z = result(2,3);
double rot_x = atan2(result(2,1),result(2,2));
double rot_y = atan2(-result(2,0),sqrt(result(1,0)*result(1,0)+result(0,0)*result(0,0)));
double rot_z = atan2(result(1,0),result(0,0));
//杈撳嚭浣嶅Э
cout<<"pos_x:"<<pos_x<<endl;
cout<<"pos_y:"<<pos_y<<endl;
cout<<"pos_z:"<<pos_z<<endl;
cout<<"rot_x:"<<rot_x<<endl;
cout<<"rot_y:"<<rot_y<<endl;
cout<<"rot_z:"<<rot_z<<endl;
pos_pub.publish(init_pos);
ROS_INFO_STREAM("published");
}
逆运动学
#include
#include
#include
#include
#include
#include
#include "vector"
#include "std_msgs/Float32.h"
#include "std_msgs/Float64MultiArray.h"
#include "controller_manager_msgs/SwitchController.h"
#include "controller_manager_msgs/ListControllers.h"
#include "ikfast.h"
#include "probot_anno_manipulator_ikfast_moveit_plugin.cpp"
using namespace ikfast_kinematics_plugin;
//瀹氫箟涓€浜涘嚱鏁颁究浜庢暡鍏紡
//骞虫柟
double squa(double t){
return t*t;
}
//cos姹傚拰
double cosp(double theta1, double theta2){
return (cos(theta1)*cos(theta2)-sin(theta1)*sin(theta2));
}
//sin姹傚拰
double sinp(double theta1, double theta2){
return (sin(theta1)*cos(theta2) + sin(theta2)*cos(theta1));
}
double judge(double theta){
if(theta > -0.01 && theta < 0.01){
return 0;
}
else return theta;
}
int main(int argc, char**argv){
bool ret;
ros::init(argc,argv,"inverse_kinematics");
ros::NodeHandle node_handle;
ROS_INFO_STREAM("start");
ros::Publisher pos_pub=node_handle.advertise<std_msgs::Float64MultiArray>("/probot_anno/arm_pos_controller/command",100);
ikfast_kinematics_plugin::IKFastKinematicsPlugin ik;
ret = ik.IKFastKinematicsPlugin::initialize("robot_description","manipulator","base_link","link_6",0.001);
double theta[6];
double CarCoor[6];
//杈撳叆绗涘崱灏斿潗鏍?
cout << "pos_x:";
cin >> CarCoor[0];
cout << "pos_y:";
cin >> CarCoor[1];
cout << "pos_z:";
cin >> CarCoor[2];
cout << "rot_x:";
cin >> CarCoor[3];
cout << "rot_y:";
cin >> CarCoor[4];
cout << "rot_z:";
cin >> CarCoor[5];
//瀹氫箟涓€浜涘彉閲忎究浜庢暡鍏紡
double px = CarCoor[0];
double py = CarCoor[1];
double pz = CarCoor[2];
double gamma = CarCoor[3];
double beta = CarCoor[4];
double alpha = CarCoor[5];
//璁$畻鍏舵鍙樻崲鐭╅樀
Eigen::Matrix<double,3,3> R;
R << cos(alpha)*cos(beta),cos(alpha)*sin(beta)*sin(gamma)-sin(alpha)*cos(gamma),cos(alpha)*sin(beta)*cos(gamma)+sin(alpha)*sin(gamma),
sin(alpha)*cos(beta),sin(alpha)*sin(beta)*sin(gamma)+cos(alpha)*cos(gamma),sin(alpha)*sin(beta)*cos(gamma)-cos(alpha)*sin(gamma),
-sin(beta),cos(beta)*sin(gamma),cos(beta)*cos(gamma);
Eigen::Matrix<double,4,4>T0;
T0 << R(0,0), R(0,1), R(0,2), CarCoor[0],
R(1,0), R(1,1),R(1,2), CarCoor[1],
R(2,0), R(2,1), R(2,2), CarCoor[2],
0,0,0,1;
//灏嗗潗鏍囩郴浠庣鍏釜鍧愭爣绯昏浆鎹㈠洖瀹氫箟鐨勭鍏釜鍧愭爣绯?
Eigen::Matrix<double,4,4>Tw1,Tw2;
Tw1 << 1,0,0,0,
0,1,0,0,
0,0,1,-0.055,
0,0,0,1;
Tw2 << 1,0,0,0,
0,0,-1,0,
0,1,0,0,
0,0,0,1;
//閫氳繃绗叚涓潗鏍囩郴涓嬬殑鍧愭爣閲嶆柊璁$畻浣嶅Э绛?
T0 = T0 * Tw2 * Tw1;
for(int i = 0;i<3;i++){
CarCoor[i] = T0(i,3);
}
CarCoor[3] = atan2(T0(2,1),T0(2,2));
CarCoor[4] = atan2(-T0(2,0),sqrt(squa(T0(1,0))+squa(T0(0,0))));
CarCoor[5] = atan2(T0(1,0),T0(0,0));
px = CarCoor[0];
py = CarCoor[1];
pz = CarCoor[2];
gamma = CarCoor[3];
beta = CarCoor[4];
alpha = CarCoor[5];
R << cos(alpha)*cos(beta),cos(alpha)*sin(beta)*sin(gamma)-sin(alpha)*cos(gamma),cos(alpha)*sin(beta)*cos(gamma)+sin(alpha)*sin(gamma),
sin(alpha)*cos(beta),sin(alpha)*sin(beta)*sin(gamma)+cos(alpha)*cos(gamma),sin(alpha)*sin(beta)*cos(gamma)-cos(alpha)*sin(gamma),
-sin(beta),cos(beta)*sin(gamma),cos(beta)*cos(gamma);
//DH鍙傛暟琛?
//\alpha_{i-1},a_{i-1},\theta_i,d_i
const double DH[8][4]={0,0,0,0.284,
M_PI/2,0,M_PI/2,0,
0,0.225,0,0,
M_PI/2,0,0,0.2289,
-M_PI/2,0,-M_PI/2,0,
M_PI/2,0,0,0,
0,0,0,0.055,
-M_PI/2,0,0,0};
//鎶奃H琛ㄩ噷涓€浜涗細鐢?
double d1 = DH[0][3];
double d4 = DH[3][3];
double a3 = DH[2][1];
//璁$畻\theta_1
theta[0] = judge(atan2(py,px));
//杩樻槸濂芥暡鍏紡
double s1 = sin(theta[0]);
double c1 = cos(theta[0]);
//璁$畻\theta_2
double K = (squa(d4) - squa(px/c1) - squa(pz - d1) - squa(a3))/(2*a3);
theta[1] = atan2(pz-d1, px/c1) - atan2( -K , sqrt(squa(px/c1) + squa(pz - d1) - squa(K)));
double s2 = sin(theta[1]);
double c2 = cos(theta[1]);
//璁$畻\theta_3
double s23 = (pz - c2 * a3 - d1)/d4;
double c23 = ((px/c1)+s2 * a3) / d4;
theta[2] = judge(atan2(s23, c23) - theta[1]);
double s3 = sin(theta[2]);
double c3 = cos(theta[2]);
c23 = cosp(theta[1],theta[2]);
s23 = sinp(theta[1],theta[2]);
//璁$畻寰楀埌^4_6T,鏉ヨ绠楀悗涓夎锛孯1涓篰1_0R,绫绘帹
Eigen::Matrix<double,3,3> R1,R2,R3,result;
R1 << c1, s1, 0,
-s1, c1, 0,
0, 0, 1;
R2 << -s2, 0, c2,
-c2, 0, -s2,
0, -1, 0;
R3 << c3, s3, 0,
-s3, c3, 0,
0, 0, 1;
result = R3 * R2 * R1 * R;
//璁$畻\theta_5
theta[4] = judge(atan2(-result(1,2), sqrt(squa(result(1,0))+squa(result(1,1)))));
double s5 = sin(theta[4]);
double c5 = cos(theta[4]);
//璁$畻\theta_4
theta[3] = judge( atan2(-result(2,2)/c5, -result(0,2)/c5));
double s4 = sin(theta[3]);
double c4 = cos(theta[3]);
//璁$畻\theta_6
theta[5] = judge(atan2(result(1,1)/c5,-result(1,0)/c5));
//鎶婅绠楀緱鍒扮殑鍏宠妭瑙掓墦鍑烘潵搴峰悍
for(int i =0;i<6;i++){
cout<<"theta"<<i+1<<": "<<theta[i]<<endl;
}
std_msgs::Float64MultiArray init_pos;
init_pos.data.push_back(0);
init_pos.data.push_back(0);
init_pos.data.push_back(0);
init_pos.data.push_back(0);
init_pos.data.push_back(0);
init_pos.data.push_back(0);
sleep(1);
init_pos.data.at(0) = theta[0];
init_pos.data.at(1) = theta[1];
init_pos.data.at(2) = theta[2];
init_pos.data.at(3) = theta[3];
init_pos.data.at(4) = theta[4];
init_pos.data.at(5) = theta[5];
pos_pub.publish(init_pos);
ROS_INFO_STREAM("published");
}