IKResult PathPlanner::checkForValidConfigurations(IKResult configs){ IKResult result; matrix<double> jointPosition(4, 4); int value = 0; double maxWrist1Angle = 0 * PI / 180; double minWrist1Angle = -180 * PI / 180; double maxWrist2Angle = 90 * (PI / 180); double minWrist2Angle = -maxWrist2Angle; for (int i = 0; i < configs.solutions.size(); i++) { value = 0; if (minWrist1Angle <= configs.solutions[i].getWrist1Angle() && configs.solutions[i].getWrist1Angle() <= maxWrist1Angle /*&& minWrist2Angle <= configs.solutions[i].getWrist2Angle() && configs.solutions[i].getWrist2Angle() <= maxWrist2Angle*/) { for (int j = 0; j < 6; j++) { jointPosition = direct_kinematics_.getPositionOfJoint(j, configs.solutions[i]); //If the z coordinate of the joint is above the table if (jointPosition(2, 3) > 0.05) { value++; } } if (value == 6){ result.solutions.push_back(configs.solutions[i]); result.configuration.push_back(configs.configuration[i]); } } } return result; }
vector<double> CNR_7DOFAnalyticInverseKinematicsComp::GetJointPosition() { vector<double> jointPosition(7); // user code here MSLVector EE(m_Position.x, m_Position.y, m_Position.z); //앤드이펙터 포지션 double cr, cp , cy; double sr, sp , sy; cr = cos(DEG2RAD(m_Position.roll)); sr = sin(DEG2RAD(m_Position.roll)); //roll값 적용 cp = cos(DEG2RAD(m_Position.pitch)); sp = sin(DEG2RAD(m_Position.pitch)); //pitch값적용 if(m_Position.yaw == 0){//yaw값이 0이면 해가 안구해져서 이렇게 처리 cy = cos(1e-011); sy = sin(1e-011); //yaw값 적용 } else { cy = cos(DEG2RAD(m_Position.yaw)); sy = sin(DEG2RAD(m_Position.yaw)); //yaw값 적용 } double uplen = atof(parameter.GetValue("UpperArmLength").c_str()); //상완길이 파라미터로부터 설정해야함 double lowlen = atof(parameter.GetValue("LowerArmLength").c_str()); //하완길이 파라미터로부터 설정해야함 double handlen = atof(parameter.GetValue("ToolLength").c_str()); //손목길이 파라미터로부터 설정해야함 double ax_o,ay_o,az_o,ox_o,oy_o,oz_o,nx_o,ny_o,nz_o;//원래의 프레임 방향인자 nx_o = cy*cp; ox_o = cy*sp*sr-sy*cr; ax_o = cy*sp*cr+sy*sr; ny_o = sy*cp; oy_o = sy*sp*sr+cy*cr; ay_o = sy*sp*cr-cy*sr; nz_o = -sp; oz_o = cp*sr; az_o = cp*cr; double px_o, py_o,pz_o; // 원래의 손목위치; px_o = EE[0] - handlen * ax_o; //손의 길이만큼 목표위치를 빼서 손목의 위치를 계산 py_o = EE[1] - handlen * ay_o; pz_o = EE[2] - handlen * az_o; MSLVector W(3); W[0] = py_o; //손목의 위치를 알고리즘에게 맞게 변환해서 입력 W[1] = -pz_o; W[2] = -px_o; if(W[0] == 0 && W[1] == 0) W[0] += 1e-011;//x,y가 둘다 0이면 해가 안구해져서 이렇게 처리 double nx,ny,nz,ox,oy,oz,ax,ay,az; //회전축 n,o,a를 알고리즘 방향기준에 맞게 변환 nx = ny_o; ox = oy_o; ax = ay_o; ny = -nz_o; oy = -oz_o; ay = -az_o; nz = -nx_o; oz = -ox_o; az = -ax_o; double wlen = W.length(); //손목까지의 거리 MSLVector P(0.0, 0.0, 100.0); //첫번째 관절벡터 double len1 = uplen; //상완길이 double len2 = lowlen; //하완길이 MSLVector SCP, C; SCP = (P*W)/(W*W)*W; //scp는 shoulder 점에서 p벡터의 w벡터에 대한 수선벡터의 베이스까지향하는 벡터이다. (scp+ (p벡터의 w벡터에 대한 수선벡터) = p벡터) C = P - SCP; double v,omega,dtemp; double rx, ry, rz, so,co; omega = DEG2RAD(atof(parameter.GetValue("RedundantValue").c_str())); //여자유도 변수 적용 v = 1-cos(omega); dtemp = sqrt(W[0]*W[0] + W[1]*W[1] +W[2]*W[2]); rx = W[0]/dtemp; ry = W[1]/dtemp; rz = W[2]/dtemp; so = sin(omega); co = cos(omega); MSLMatrix R(3,3); R[0][0] = rx * rx * v + co; R[0][1] = rx * ry * v - rz * so; R[0][2] = rx *rz*v + ry * so; R[1][0] = rx * ry * v + rz * so; R[1][1] = ry * ry * v + co; R[1][2] = ry * rz * v - rx * so; R[2][0] = rx * rz * v - ry * so; R[2][1] = ry * rz * v + rx * so; R[2][2] = rz * rz * v + co; C = R * C; //c벡터를 손목 회전벡터로 오메가각도만큼 회전 C = C.norm() ; //c를 노말라이징 double he; he = 0.5 * (wlen + uplen + lowlen); he = sqrt(he*(he - wlen)*(he - lowlen)*(he - uplen)); double clen = 2.0 * he / wlen; C = clen * C; //W벡터 중간정도에서 엘보까지 가는 벡터 완성 MSLVector SE; //어깨에서 엘보까지 벡터 SE = (W/wlen)*sqrt(uplen*uplen - clen*clen) + C; MSLVector EW; //엘보에서 손목까지 벡터 EW = W - SE; double th1, th2, th3, th4, th5, th6, th7; double c1,s1,c2,s2,c3,s3,c4,s4,c5,s5,c6,s6; th2 = acos(SE[1]/uplen); c2 = cos(th2); s2 = sin(th2); double ss,cc; ss = -SE[2]/(uplen*sin(th2)); cc = -SE[0]/(uplen*sin(th2)); th1 = atan2(ss,cc); c1 = cos(th1); s1 = sin(th1); th4 = acos( (SE*EW)/((SE.length())*(EW.length())) ); c4 = cos(th4); s4 = sin(th4); double AA,BB,CC; AA = -EW[0]/lowlen - c1*s2*c4; BB = -EW[2]/lowlen - s1*s2*c4; ss = (c1*BB - s1*AA)/s4; cc = (-EW[1]/lowlen + c2*c4)/(-s2*s4); th3 = atan2(ss,cc); c3 = cos(th3); s3 = sin(th3); MSLVector RHZ(ax, ay, az); th6 = acos( (EW*RHZ)/lowlen); c6 = cos(th6); s6 = sin(th6); AA = -ax -(-(c1*c2*c3+s1*s3)*s4+c1*s2*c4)*c6; BB = -ay -(-s2*c3*s4-c2*c4)*c6; CC = (-c1*c2*s3+s1*c3)*(s2*c3*c4-c2*s4) - (-s2*s3)*((c1*c2*c3+s1*s3)*c4+c1*s2*s4); cc = ( (-s2*s3) *(AA) - (-c1*c2*s3+s1*c3) *(BB) )/((CC)*s6 ); ss = -( (s2*c3*c4-c2*s4) *(AA)- ((c1*c2*c3+s1*s3)*c4+c1*s2*s4) *(BB)) /((CC)*s6); th5 = atan2(ss,cc); c5 = cos(th5); s5 = sin(th5); AA = -((c1*c2*c3+s1*s3)*c4+c1*s2*s4)*s5+(-c1*c2*s3+s1*c3)*c5; BB = -((s1*c2*c3-c1*s3)*c4+s1*s2*s4)*s5+(-s1*c2*s3-c1*c3)*c5; ss = (oz*AA - ox*BB)/(oz*nx - ox*nz ); cc = (nx*BB - nz*AA)/(oz*nx - ox*nz ); th7 = atan2(ss,cc); jointPosition[0] = ASV_DEG(RAD2DEG(fmod(th1+M_PI_2, 2.*M_PI))); jointPosition[1] = ASV_DEG(RAD2DEG(fmod(th2, 2.*M_PI))); jointPosition[2] = ASV_DEG(RAD2DEG(fmod(th3, 2.*M_PI))); jointPosition[3] = ASV_DEG(RAD2DEG(fmod(th4, 2.*M_PI))); jointPosition[4] = ASV_DEG(RAD2DEG(fmod(th5, 2.*M_PI))); jointPosition[5] = ASV_DEG(RAD2DEG(fmod(th6, 2.*M_PI))); jointPosition[6] = ASV_DEG(RAD2DEG(fmod(th7, 2.*M_PI))); return jointPosition; }
TEST(TestSuite, oneDofRevoluteX) { const char* ffJointName = "base_footprint_joint"; jrl::dynamics::urdf::Parser parser; CjrlHumanoidDynamicRobot* robot = parser.parse (TEST_MODEL_DIRECTORY "/one_dof_revolute_x.urdf", ffJointName); CjrlJoint* root = robot->rootJoint (); ASSERT_TRUE (root); ASSERT_EQ (1, root->countChildJoints()); ASSERT_EQ (ffJointName, root->getName()); CjrlJoint* joint = root->childJoint (0); ASSERT_TRUE (joint); ASSERT_EQ ("joint1", joint->getName()); // Create robot configuration. const int ndofs = 7; vectorN q (ndofs); vectorN dq (ndofs); vectorN ddq (ndofs); for (unsigned i = 0; i < ndofs; ++i) q (i) = dq (i) = ddq (i) = 0.; // Check configuration at zero. std::cout << q << std::endl; ASSERT_TRUE (robot->currentConfiguration(q)); ASSERT_TRUE (robot->currentVelocity(dq)); ASSERT_TRUE (robot->currentAcceleration(ddq)); ASSERT_TRUE (robot->computeForwardKinematics()); matrix4d jointPosition; jointPosition.setIdentity (); for (unsigned i = 0; i < 4; ++i) for (unsigned j = 0; j < 4; ++j) ASSERT_EQ(jointPosition (i, j), root->currentTransformation () (i, j)); jointPosition.setIdentity (); jointPosition (1, 3) = 1.; // std::cout << "current value:" << std::endl; // std::cout << joint->currentTransformation () << std::endl; // std::cout << "expected value:" << std::endl; // std::cout << jointPosition << std::endl; for (unsigned i = 0; i < 4; ++i) for (unsigned j = 0; j < 4; ++j) ASSERT_NEAR (jointPosition (i, j), joint->currentTransformation () (i, j), 1e-9); // Check configuration at pi/2. q (6) = M_PI / 2.; std::cout << q << std::endl; ASSERT_TRUE (robot->currentConfiguration(q)); ASSERT_TRUE (robot->currentVelocity(dq)); ASSERT_TRUE (robot->currentAcceleration(ddq)); ASSERT_TRUE (robot->computeForwardKinematics()); jointPosition.setIdentity (); jointPosition (1, 1) = 0.; jointPosition (1, 2) = -1.; jointPosition (2, 1) = 1.; jointPosition (2, 2) = 0.; jointPosition (1, 3) = 1.; std::cout << "current value:" << std::endl; std::cout << joint->currentTransformation () << std::endl; std::cout << "expected value:" << std::endl; std::cout << jointPosition << std::endl; for (unsigned i = 0; i < 4; ++i) for (unsigned j = 0; j < 4; ++j) ASSERT_NEAR (jointPosition (i, j), joint->currentTransformation () (i, j), 1e-9); }