ROS OpenRAVE 常用逆解库 ikfast (应用于UR机械臂)

2023-05-16

ArmKine.cpp


#include "armKine.h"

#include <math.h>
#include <stdio.h>
#include <corecrt_math_defines.h>

#define UR5_PARAMS
#define IKFAST_MAIN

namespace ur_kinematics {

	namespace {
		const double ZERO_THRESH = 0.00000001;
		int SIGN(double x) {
			return (x > 0) - (x < 0);
		}
		const double PI = M_PI;

		//#define UR10_PARAMS
#ifdef UR10_PARAMS
		const double d1 = 0.1273;
		const double a2 = -0.612;
		const double a3 = -0.5723;
		const double d4 = 0.163941;
		const double d5 = 0.1157;
		const double d6 = 0.0922;
#endif

		//#define UR5_PARAMS
#ifdef UR5_PARAMS
		const double d1 = 0.089159;
		const double a2 = -0.42500;
		const double a3 = -0.39225;
		const double d4 = 0.10915;
		const double d5 = 0.09465;
		const double d6 = 0.0823;
#endif

		//#define UR3_PARAMS
#ifdef UR3_PARAMS
		const double d1 = 0.1519;
		const double a2 = -0.24365;
		const double a3 = -0.21325;
		const double d4 = 0.11235;
		const double d5 = 0.08535;
		const double d6 = 0.0819;
#endif
	}

	void forward(const double* q, double* T) {
		double s1 = sin(*q), c1 = cos(*q); q++;
		double q23 = *q, q234 = *q, s2 = sin(*q), c2 = cos(*q); q++;
		double s3 = sin(*q), c3 = cos(*q); q23 += *q; q234 += *q; q++;
		double s4 = sin(*q), c4 = cos(*q); q234 += *q; q++;
		double s5 = sin(*q), c5 = cos(*q); q++;
		double s6 = sin(*q), c6 = cos(*q);
		double s23 = sin(q23), c23 = cos(q23);
		double s234 = sin(q234), c234 = cos(q234);
		*T = c234 * c1*s5 - c5 * s1; T++;
		*T = c6 * (s1*s5 + c234 * c1*c5) - s234 * c1*s6; T++;
		*T = -s6 * (s1*s5 + c234 * c1*c5) - s234 * c1*c6; T++;
		*T = d6 * c234*c1*s5 - a3 * c23*c1 - a2 * c1*c2 - d6 * c5*s1 - d5 * s234*c1 - d4 * s1; T++;
		*T = c1 * c5 + c234 * s1*s5; T++;
		*T = -c6 * (c1*s5 - c234 * c5*s1) - s234 * s1*s6; T++;
		*T = s6 * (c1*s5 - c234 * c5*s1) - s234 * c6*s1; T++;
		*T = d6 * (c1*c5 + c234 * s1*s5) + d4 * c1 - a3 * c23*s1 - a2 * c2*s1 - d5 * s234*s1; T++;
		*T = -s234 * s5; T++;
		*T = -c234 * s6 - s234 * c5*c6; T++;
		*T = s234 * c5*s6 - c234 * c6; T++;
		*T = d1 + a3 * s23 + a2 * s2 - d5 * (c23*c4 - s23 * s4) - d6 * s5*(c23*s4 + s23 * c4); T++;
		*T = 0.0; T++; *T = 0.0; T++; *T = 0.0; T++; *T = 1.0;
	}

	void forward_all(const double* q, double* T1, double* T2, double* T3,
		double* T4, double* T5, double* T6) {
		double s1 = sin(*q), c1 = cos(*q); q++; // q1
		double q23 = *q, q234 = *q, s2 = sin(*q), c2 = cos(*q); q++; // q2
		double s3 = sin(*q), c3 = cos(*q); q23 += *q; q234 += *q; q++; // q3
		q234 += *q; q++; // q4
		double s5 = sin(*q), c5 = cos(*q); q++; // q5
		double s6 = sin(*q), c6 = cos(*q); // q6
		double s23 = sin(q23), c23 = cos(q23);
		double s234 = sin(q234), c234 = cos(q234);

		if (T1 != NULL) {
			*T1 = c1; T1++;
			*T1 = 0; T1++;
			*T1 = s1; T1++;
			*T1 = 0; T1++;
			*T1 = s1; T1++;
			*T1 = 0; T1++;
			*T1 = -c1; T1++;
			*T1 = 0; T1++;
			*T1 = 0; T1++;
			*T1 = 1; T1++;
			*T1 = 0; T1++;
			*T1 = d1; T1++;
			*T1 = 0; T1++;
			*T1 = 0; T1++;
			*T1 = 0; T1++;
			*T1 = 1; T1++;
		}

		if (T2 != NULL) {
			*T2 = c1 * c2; T2++;
			*T2 = -c1 * s2; T2++;
			*T2 = s1; T2++;
			*T2 = a2 * c1*c2; T2++;
			*T2 = c2 * s1; T2++;
			*T2 = -s1 * s2; T2++;
			*T2 = -c1; T2++;
			*T2 = a2 * c2*s1; T2++;
			*T2 = s2; T2++;
			*T2 = c2; T2++;
			*T2 = 0; T2++;
			*T2 = d1 + a2 * s2; T2++;
			*T2 = 0; T2++;
			*T2 = 0; T2++;
			*T2 = 0; T2++;
			*T2 = 1; T2++;
		}

		if (T3 != NULL) {
			*T3 = c23 * c1; T3++;
			*T3 = -s23 * c1; T3++;
			*T3 = s1; T3++;
			*T3 = c1 * (a3*c23 + a2 * c2); T3++;
			*T3 = c23 * s1; T3++;
			*T3 = -s23 * s1; T3++;
			*T3 = -c1; T3++;
			*T3 = s1 * (a3*c23 + a2 * c2); T3++;
			*T3 = s23; T3++;
			*T3 = c23; T3++;
			*T3 = 0; T3++;
			*T3 = d1 + a3 * s23 + a2 * s2; T3++;
			*T3 = 0; T3++;
			*T3 = 0; T3++;
			*T3 = 0; T3++;
			*T3 = 1; T3++;
		}

		if (T4 != NULL) {
			*T4 = c234 * c1; T4++;
			*T4 = s1; T4++;
			*T4 = s234 * c1; T4++;
			*T4 = c1 * (a3*c23 + a2 * c2) + d4 * s1; T4++;
			*T4 = c234 * s1; T4++;
			*T4 = -c1; T4++;
			*T4 = s234 * s1; T4++;
			*T4 = s1 * (a3*c23 + a2 * c2) - d4 * c1; T4++;
			*T4 = s234; T4++;
			*T4 = 0; T4++;
			*T4 = -c234; T4++;
			*T4 = d1 + a3 * s23 + a2 * s2; T4++;
			*T4 = 0; T4++;
			*T4 = 0; T4++;
			*T4 = 0; T4++;
			*T4 = 1; T4++;
		}

		if (T5 != NULL) {
			*T5 = s1 * s5 + c234 * c1*c5; T5++;
			*T5 = -s234 * c1; T5++;
			*T5 = c5 * s1 - c234 * c1*s5; T5++;
			*T5 = c1 * (a3*c23 + a2 * c2) + d4 * s1 + d5 * s234*c1; T5++;
			*T5 = c234 * c5*s1 - c1 * s5; T5++;
			*T5 = -s234 * s1; T5++;
			*T5 = -c1 * c5 - c234 * s1*s5; T5++;
			*T5 = s1 * (a3*c23 + a2 * c2) - d4 * c1 + d5 * s234*s1; T5++;
			*T5 = s234 * c5; T5++;
			*T5 = c234; T5++;
			*T5 = -s234 * s5; T5++;
			*T5 = d1 + a3 * s23 + a2 * s2 - d5 * c234; T5++;
			*T5 = 0; T5++;
			*T5 = 0; T5++;
			*T5 = 0; T5++;
			*T5 = 1; T5++;
		}

		if (T6 != NULL) {
			*T6 = c6 * (s1*s5 + c234 * c1*c5) - s234 * c1*s6; T6++;
			*T6 = -s6 * (s1*s5 + c234 * c1*c5) - s234 * c1*c6; T6++;
			*T6 = c5 * s1 - c234 * c1*s5; T6++;
			*T6 = d6 * (c5*s1 - c234 * c1*s5) + c1 * (a3*c23 + a2 * c2) + d4 * s1 + d5 * s234*c1; T6++;
			*T6 = -c6 * (c1*s5 - c234 * c5*s1) - s234 * s1*s6; T6++;
			*T6 = s6 * (c1*s5 - c234 * c5*s1) - s234 * c6*s1; T6++;
			*T6 = -c1 * c5 - c234 * s1*s5; T6++;
			*T6 = s1 * (a3*c23 + a2 * c2) - d4 * c1 - d6 * (c1*c5 + c234 * s1*s5) + d5 * s234*s1; T6++;
			*T6 = c234 * s6 + s234 * c5*c6; T6++;
			*T6 = c234 * c6 - s234 * c5*s6; T6++;
			*T6 = -s234 * s5; T6++;
			*T6 = d1 + a3 * s23 + a2 * s2 - d5 * c234 - d6 * s234*s5; T6++;
			*T6 = 0; T6++;
			*T6 = 0; T6++;
			*T6 = 0; T6++;
			*T6 = 1; T6++;
		}
	}

	int inverse(const double* T, double* q_sols, double q6_des) {
		int num_sols = 0;
		double T02 = -*T; T++; double T00 = *T; T++; double T01 = *T; T++; double T03 = -*T; T++;
		double T12 = -*T; T++; double T10 = *T; T++; double T11 = *T; T++; double T13 = -*T; T++;
		double T22 = *T; T++; double T20 = -*T; T++; double T21 = -*T; T++; double T23 = *T;

		// shoulder rotate joint (q1) //
		double q1[2];
		{
			double A = d6 * T12 - T13;
			double B = d6 * T02 - T03;
			double R = A * A + B * B;
			if (fabs(A) < ZERO_THRESH) {
				double div;
				if (fabs(fabs(d4) - fabs(B)) < ZERO_THRESH)
					div = -SIGN(d4)*SIGN(B);
				else
					div = -d4 / B;
				double arcsin = asin(div);
				if (fabs(arcsin) < ZERO_THRESH)
					arcsin = 0.0;
				if (arcsin < 0.0)
					q1[0] = arcsin + 2.0*PI;
				else
					q1[0] = arcsin;
				q1[1] = PI - arcsin;
			}
			else if (fabs(B) < ZERO_THRESH) {
				double div;
				if (fabs(fabs(d4) - fabs(A)) < ZERO_THRESH)
					div = SIGN(d4)*SIGN(A);
				else
					div = d4 / A;
				double arccos = acos(div);
				q1[0] = arccos;
				q1[1] = 2.0*PI - arccos;
			}
			else if (d4*d4 > R) {
				return num_sols;
			}
			else {
				double arccos = acos(d4 / sqrt(R));
				double arctan = atan2(-B, A);
				double pos = arccos + arctan;
				double neg = -arccos + arctan;
				if (fabs(pos) < ZERO_THRESH)
					pos = 0.0;
				if (fabs(neg) < ZERO_THRESH)
					neg = 0.0;
				if (pos >= 0.0)
					q1[0] = pos;
				else
					q1[0] = 2.0*PI + pos;
				if (neg >= 0.0)
					q1[1] = neg;
				else
					q1[1] = 2.0*PI + neg;
			}
		}


		// wrist 2 joint (q5) //
		double q5[2][2];
		{
			for (int i = 0; i < 2; i++) {
				double numer = (T03*sin(q1[i]) - T13 * cos(q1[i]) - d4);
				double div;
				if (fabs(fabs(numer) - fabs(d6)) < ZERO_THRESH)
					div = SIGN(numer) * SIGN(d6);
				else
					div = numer / d6;
				double arccos = acos(div);
				q5[i][0] = arccos;
				q5[i][1] = 2.0*PI - arccos;
			}
		}


		{
			for (int i = 0; i < 2; i++) {
				for (int j = 0; j < 2; j++) {
					double c1 = cos(q1[i]), s1 = sin(q1[i]);
					double c5 = cos(q5[i][j]), s5 = sin(q5[i][j]);
					double q6;
					// wrist 3 joint (q6) //
					if (fabs(s5) < ZERO_THRESH)
						q6 = q6_des;
					else {
						q6 = atan2(SIGN(s5)*-(T01*s1 - T11 * c1),
							SIGN(s5)*(T00*s1 - T10 * c1));
						if (fabs(q6) < ZERO_THRESH)
							q6 = 0.0;
						if (q6 < 0.0)
							q6 += 2.0*PI;
					}


					double q2[2], q3[2], q4[2];
					// RRR joints(q2, q3, q4)
						double c6 = cos(q6), s6 = sin(q6);
					double x04x = -s5 * (T02*c1 + T12 * s1) - c5 * (s6*(T01*c1 + T11 * s1) - c6 * (T00*c1 + T10 * s1));
					double x04y = c5 * (T20*c6 - T21 * s6) - T22 * s5;
					double p13x = d5 * (s6*(T00*c1 + T10 * s1) + c6 * (T01*c1 + T11 * s1)) - d6 * (T02*c1 + T12 * s1) +
						T03 * c1 + T13 * s1;
					double p13y = T23 - d1 - d6 * T22 + d5 * (T21*c6 + T20 * s6);

					double c3 = (p13x*p13x + p13y * p13y - a2 * a2 - a3 * a3) / (2.0*a2*a3);
					if (fabs(fabs(c3) - 1.0) < ZERO_THRESH)
						c3 = SIGN(c3);
					else if (fabs(c3) > 1.0) {
						// TODO NO SOLUTION
						continue;
					}
					double arccos = acos(c3);
					q3[0] = arccos;
					q3[1] = 2.0*PI - arccos;
					double denom = a2 * a2 + a3 * a3 + 2 * a2*a3*c3;
					double s3 = sin(arccos);
					double A = (a2 + a3 * c3), B = a3 * s3;
					q2[0] = atan2((A*p13y - B * p13x) / denom, (A*p13x + B * p13y) / denom);
					q2[1] = atan2((A*p13y + B * p13x) / denom, (A*p13x - B * p13y) / denom);
					double c23_0 = cos(q2[0] + q3[0]);
					double s23_0 = sin(q2[0] + q3[0]);
					double c23_1 = cos(q2[1] + q3[1]);
					double s23_1 = sin(q2[1] + q3[1]);
					q4[0] = atan2(c23_0*x04y - s23_0 * x04x, x04x*c23_0 + x04y * s23_0);
					q4[1] = atan2(c23_1*x04y - s23_1 * x04x, x04x*c23_1 + x04y * s23_1);

					for (int k = 0; k < 2; k++) {
						if (fabs(q2[k]) < ZERO_THRESH)
							q2[k] = 0.0;
						else if (q2[k] < 0.0) q2[k] += 2.0*PI;
						if (fabs(q4[k]) < ZERO_THRESH)
							q4[k] = 0.0;
						else if (q4[k] < 0.0) q4[k] += 2.0*PI;
						q_sols[num_sols * 6 + 0] = q1[i];    q_sols[num_sols * 6 + 1] = q2[k];
						q_sols[num_sols * 6 + 2] = q3[k];    q_sols[num_sols * 6 + 3] = q4[k];
						q_sols[num_sols * 6 + 4] = q5[i][j]; q_sols[num_sols * 6 + 5] = q6;
						num_sols++;
					}

				}
			}
		}
		return num_sols;
	}
};

#define IKFAST_HAS_LIBRARY
#include "ikfast.h"
using namespace ikfast;

// check if the included ikfast version matches what this file was compiled with
#define IKFAST_COMPILE_ASSERT(x) extern int __dummy[(int)x]
IKFAST_COMPILE_ASSERT(IKFAST_VERSION == 0x10000048);

#ifdef IKFAST_NAMESPACE
namespace IKFAST_NAMESPACE {
#endif

	void to_mat44(double * mat4_4, const IkReal* eetrans, const IkReal* eerot)
	{
		for (int i = 0; i < 3; ++i) {
			mat4_4[i * 4 + 0] = eerot[i * 3 + 0];
			mat4_4[i * 4 + 1] = eerot[i * 3 + 1];
			mat4_4[i * 4 + 2] = eerot[i * 3 + 2];
			mat4_4[i * 4 + 3] = eetrans[i];
		}
		mat4_4[3 * 4 + 0] = 0;
		mat4_4[3 * 4 + 1] = 0;
		mat4_4[3 * 4 + 2] = 0;
		mat4_4[3 * 4 + 3] = 1;
	}

	void from_mat44(const double * mat4_4, IkReal* eetrans, IkReal* eerot)
	{
		for (int i = 0; i < 3; ++i) {
			eerot[i * 3 + 0] = mat4_4[i * 4 + 0];
			eerot[i * 3 + 1] = mat4_4[i * 4 + 1];
			eerot[i * 3 + 2] = mat4_4[i * 4 + 2];
			eetrans[i] = mat4_4[i * 4 + 3];
		}
	}


	IKFAST_API bool ComputeIk(const IkReal* eetrans, const IkReal* eerot, const IkReal* pfree, IkSolutionListBase<IkReal>& solutions) {
		if (!pfree) return false;

		int n = GetNumJoints();
		double q_sols[8 * 6];
		double T[16];

		to_mat44(T, eetrans, eerot);

		int num_sols = ur_kinematics::inverse(T, q_sols, pfree[0]);

		std::vector<int> vfree(0);

		for (int i = 0; i < num_sols; ++i) {
			std::vector<IkSingleDOFSolutionBase<IkReal> > vinfos(n);
			for (int j = 0; j < n; ++j) vinfos[j].foffset = q_sols[i*n + j];
			solutions.AddSolution(vinfos, vfree);
		}
		return num_sols > 0;
	}

	IKFAST_API void ComputeFk(const IkReal* j, IkReal* eetrans, IkReal* eerot)
	{
		double T[16];
		ur_kinematics::forward(j, T);
		from_mat44(T, eetrans, eerot);
	}

	IKFAST_API int GetNumFreeParameters() { return 1; }
	IKFAST_API int* GetFreeParameters() { static int freeparams[] = { 5 }; return freeparams; }
	IKFAST_API int GetNumJoints() { return 6; }

	IKFAST_API int GetIkRealSize() { return sizeof(IkReal); }

#ifdef IKFAST_NAMESPACE
} // end namespace
#endif

#ifndef IKFAST_NO_MAIN

using namespace std;
using namespace ur_kinematics;

int main(int argc, char* argv[])
{
	double q[6] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0 };
	double* T = new double[16];
	forward(q, T);
	for (int i = 0; i < 4; i++) {
		for (int j = i * 4; j < (i + 1) * 4; j++)
			printf("%1.3f ", T[j]);
		printf("\n");
	}
	double q_sols[8 * 6];
	int num_sols;
	num_sols = inverse(T, q_sols);
	for (int i = 0; i < num_sols; i++)
		printf("%1.6f %1.6f %1.6f %1.6f %1.6f %1.6f\n",
			q_sols[i * 6 + 0], q_sols[i * 6 + 1], q_sols[i * 6 + 2], q_sols[i * 6 + 3], q_sols[i * 6 + 4], q_sols[i * 6 + 5]);
	for (int i = 0; i <= 4; i++)
		printf("%f ", PI / 2.0*i);
	printf("\n");
	return 0;
}
#endif

ikfast.h

#pragma once
// -*- coding: utf-8 -*-
// Copyright (C) 2012-2014 Rosen Diankov <rosen.diankov@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/** \brief  Header file for all ikfast c++ files/shared objects.

	The ikfast inverse kinematics compiler is part of OpenRAVE.

	The file is divided into two sections:
	- <b>Common</b> - the abstract classes section that all ikfast share regardless of their settings
	- <b>Library Specific</b> - the library-specific definitions, which depends on the precision/settings that the
   library was compiled with

	The defines are as follows, they are also used for the ikfast C++ class:

   - IKFAST_HEADER_COMMON - common classes
   - IKFAST_HAS_LIBRARY - if defined, will include library-specific functions. by default this is off
   - IKFAST_CLIBRARY - Define this linking statically or dynamically to get correct visibility.
   - IKFAST_NO_MAIN - Remove the ``main`` function, usually used with IKFAST_CLIBRARY
   - IKFAST_ASSERT - Define in order to get a custom assert called when NaNs, divides by zero, and other invalid
   conditions are detected.
   - IKFAST_REAL - Use to force a custom real number type for IkReal.
   - IKFAST_NAMESPACE - Enclose all functions and classes in this namespace, the ``main`` function is excluded.

 */
#include <vector>
#include <list>
#include <stdexcept>
#include <cmath>

#ifndef IKFAST_HEADER_COMMON
#define IKFAST_HEADER_COMMON

 /// should be the same as ikfast.__version__
 /// if 0x10000000 bit is set, then the iksolver assumes 6D transforms are done without the manipulator offset taken into
 /// account (allows to reuse IK when manipulator offset changes)
#define IKFAST_VERSION 0x10000048

namespace ikfast
{
	/// \brief holds the solution for a single dof
	template < typename T >
	class IkSingleDOFSolutionBase
	{
	public:
		IkSingleDOFSolutionBase() : fmul(0), foffset(0), freeind(-1), maxsolutions(1)
		{
			indices[0] = indices[1] = indices[2] = indices[3] = indices[4] = -1;
		}
		T fmul, foffset;             ///< joint value is fmul*sol[freeind]+foffset
		signed char freeind;         ///< if >= 0, mimics another joint
		unsigned char jointtype;     ///< joint type, 0x01 is revolute, 0x11 is slider
		unsigned char maxsolutions;  ///< max possible indices, 0 if controlled by free index or a free joint itself
		unsigned char indices[5];  ///< unique index of the solution used to keep track on what part it came from. sometimes a
								   ///solution can be repeated for different indices. store at least another repeated root
	};

	/// \brief The discrete solutions are returned in this structure.
	///
	/// Sometimes the joint axes of the robot can align allowing an infinite number of solutions.
	/// Stores all these solutions in the form of free variables that the user has to set when querying the solution. Its
	/// prototype is:
	template < typename T >
	class IkSolutionBase
	{
	public:
		virtual ~IkSolutionBase()
		{
		}
		/// \brief gets a concrete solution
		///
		/// \param[out] solution the result
		/// \param[in] freevalues values for the free parameters \se GetFree
		virtual void GetSolution(T* solution, const T* freevalues) const = 0;

		/// \brief std::vector version of \ref GetSolution
		virtual void GetSolution(std::vector< T >& solution, const std::vector< T >& freevalues) const
		{
			solution.resize(GetDOF());
			GetSolution(&solution.at(0), freevalues.size() > 0 ? &freevalues.at(0) : NULL);
		}

		/// \brief Gets the indices of the configuration space that have to be preset before a full solution can be returned
		///
		/// 0 always points to the first value accepted by the ik function.
		/// \return vector of indices indicating the free parameters
		virtual const std::vector< int >& GetFree() const = 0;

		/// \brief the dof of the solution
		virtual const int GetDOF() const = 0;
	};

	/// \brief manages all the solutions
	template < typename T >
	class IkSolutionListBase
	{
	public:
		virtual ~IkSolutionListBase()
		{
		}

		/// \brief add one solution and return its index for later retrieval
		///
		/// \param vinfos Solution data for each degree of freedom of the manipulator
		/// \param vfree If the solution represents an infinite space, holds free parameters of the solution that users can
		/// freely set. The indices are of the configuration that the IK solver accepts rather than the entire robot, ie 0
		/// points to the first value accepted.
		virtual size_t AddSolution(const std::vector< IkSingleDOFSolutionBase< T > >& vinfos,
			const std::vector< int >& vfree) = 0;

		/// \brief returns the solution pointer
		virtual const IkSolutionBase< T >& GetSolution(size_t index) const = 0;

		/// \brief returns the number of solutions stored
		virtual size_t GetNumSolutions() const = 0;

		/// \brief clears all current solutions, note that any memory addresses returned from \ref GetSolution will be
		/// invalidated.
		virtual void Clear() = 0;
	};

	/// \brief holds function pointers for all the exported functions of ikfast
	template < typename T >
	class IkFastFunctions
	{
	public:
		IkFastFunctions()
			: _ComputeIk(NULL)
			, _ComputeIk2(NULL)
			, _ComputeFk(NULL)
			, _GetNumFreeParameters(NULL)
			, _GetFreeParameters(NULL)
			, _GetNumJoints(NULL)
			, _GetIkRealSize(NULL)
			, _GetIkFastVersion(NULL)
			, _GetIkType(NULL)
			, _GetKinematicsHash(NULL)
		{
		}
		virtual ~IkFastFunctions()
		{
		}
		typedef bool(*ComputeIkFn)(const T*, const T*, const T*, IkSolutionListBase< T >&);
		ComputeIkFn _ComputeIk;
		typedef bool(*ComputeIk2Fn)(const T*, const T*, const T*, IkSolutionListBase< T >&, void*);
		ComputeIk2Fn _ComputeIk2;
		typedef void(*ComputeFkFn)(const T*, T*, T*);
		ComputeFkFn _ComputeFk;
		typedef int(*GetNumFreeParametersFn)();
		GetNumFreeParametersFn _GetNumFreeParameters;
		typedef int* (*GetFreeParametersFn)();
		GetFreeParametersFn _GetFreeParameters;
		typedef int(*GetNumJointsFn)();
		GetNumJointsFn _GetNumJoints;
		typedef int(*GetIkRealSizeFn)();
		GetIkRealSizeFn _GetIkRealSize;
		typedef const char* (*GetIkFastVersionFn)();
		GetIkFastVersionFn _GetIkFastVersion;
		typedef int(*GetIkTypeFn)();
		GetIkTypeFn _GetIkType;
		typedef const char* (*GetKinematicsHashFn)();
		GetKinematicsHashFn _GetKinematicsHash;
	};

	// Implementations of the abstract classes, user doesn't need to use them

	/// \brief Default implementation of \ref IkSolutionBase
	template < typename T >
	class IkSolution : public IkSolutionBase< T >
	{
	public:
		IkSolution(const std::vector< IkSingleDOFSolutionBase< T > >& vinfos, const std::vector< int >& vfree)
		{
			_vbasesol = vinfos;
			_vfree = vfree;
		}

		virtual void GetSolution(T* solution, const T* freevalues) const
		{
			for (std::size_t i = 0; i < _vbasesol.size(); ++i)
			{
				if (_vbasesol[i].freeind < 0)
					solution[i] = _vbasesol[i].foffset;
				else
				{
					solution[i] = freevalues[_vbasesol[i].freeind] * _vbasesol[i].fmul + _vbasesol[i].foffset;
					if (solution[i] > T(3.14159265358979))
					{
						solution[i] -= T(6.28318530717959);
					}
					else if (solution[i] < T(-3.14159265358979))
					{
						solution[i] += T(6.28318530717959);
					}
				}
			}
		}

		virtual void GetSolution(std::vector< T >& solution, const std::vector< T >& freevalues) const
		{
			solution.resize(GetDOF());
			GetSolution(&solution.at(0), freevalues.size() > 0 ? &freevalues.at(0) : NULL);
		}

		virtual const std::vector< int >& GetFree() const
		{
			return _vfree;
		}
		virtual const int GetDOF() const
		{
			return static_cast<int>(_vbasesol.size());
		}

		virtual void Validate() const
		{
			for (size_t i = 0; i < _vbasesol.size(); ++i)
			{
				if (_vbasesol[i].maxsolutions == (unsigned char)-1)
				{
					throw std::runtime_error("max solutions for joint not initialized");
				}
				if (_vbasesol[i].maxsolutions > 0)
				{
					if (_vbasesol[i].indices[0] >= _vbasesol[i].maxsolutions)
					{
						throw std::runtime_error("index >= max solutions for joint");
					}
					if (_vbasesol[i].indices[1] != (unsigned char)-1 && _vbasesol[i].indices[1] >= _vbasesol[i].maxsolutions)
					{
						throw std::runtime_error("2nd index >= max solutions for joint");
					}
				}
				if (!std::isfinite(_vbasesol[i].foffset))
				{
					throw std::runtime_error("foffset was not finite");
				}
			}
		}

		virtual void GetSolutionIndices(std::vector< unsigned int >& v) const
		{
			v.resize(0);
			v.push_back(0);
			for (int i = (int)_vbasesol.size() - 1; i >= 0; --i)
			{
				if (_vbasesol[i].maxsolutions != (unsigned char)-1 && _vbasesol[i].maxsolutions > 1)
				{
					for (size_t j = 0; j < v.size(); ++j)
					{
						v[j] *= _vbasesol[i].maxsolutions;
					}
					size_t orgsize = v.size();
					if (_vbasesol[i].indices[1] != (unsigned char)-1)
					{
						for (size_t j = 0; j < orgsize; ++j)
						{
							v.push_back(v[j] + _vbasesol[i].indices[1]);
						}
					}
					if (_vbasesol[i].indices[0] != (unsigned char)-1)
					{
						for (size_t j = 0; j < orgsize; ++j)
						{
							v[j] += _vbasesol[i].indices[0];
						}
					}
				}
			}
		}

		std::vector< IkSingleDOFSolutionBase< T > > _vbasesol;  ///< solution and their offsets if joints are mimiced
		std::vector< int > _vfree;
	};

	/// \brief Default implementation of \ref IkSolutionListBase
	template < typename T >
	class IkSolutionList : public IkSolutionListBase< T >
	{
	public:
		virtual size_t AddSolution(const std::vector< IkSingleDOFSolutionBase< T > >& vinfos, const std::vector< int >& vfree)
		{
			size_t index = _listsolutions.size();
			_listsolutions.push_back(IkSolution< T >(vinfos, vfree));
			return index;
		}

		virtual const IkSolutionBase< T >& GetSolution(size_t index) const
		{
			if (index >= _listsolutions.size())
			{
				throw std::runtime_error("GetSolution index is invalid");
			}
			typename std::list< IkSolution< T > >::const_iterator it = _listsolutions.begin();
			std::advance(it, index);
			return *it;
		}

		virtual size_t GetNumSolutions() const
		{
			return _listsolutions.size();
		}

		virtual void Clear()
		{
			_listsolutions.clear();
		}

	protected:
		std::list< IkSolution< T > > _listsolutions;
	};
}

#endif  // OPENRAVE_IKFAST_HEADER

// The following code is dependent on the C++ library linking with.
#ifdef IKFAST_HAS_LIBRARY

// defined when creating a shared object/dll
#ifdef IKFAST_CLIBRARY
#ifdef _MSC_VER
#define IKFAST_API extern "C" __declspec(dllexport)
#else
#define IKFAST_API extern "C"
#endif
#else
#define IKFAST_API
#endif

#ifdef IKFAST_NAMESPACE
namespace IKFAST_NAMESPACE
{
#endif

#ifdef IKFAST_REAL
	typedef IKFAST_REAL IkReal;
#else
	typedef double IkReal;
#endif

	/** \brief Computes all IK solutions given a end effector coordinates and the free joints.

	   - ``eetrans`` - 3 translation values. For iktype **TranslationXYOrientation3D**, the z-axis is the orientation.
	   - ``eerot``
	   - For **Transform6D** it is 9 values for the 3x3 rotation matrix.
	   - For **Direction3D**, **Ray4D**, and **TranslationDirection5D**, the first 3 values represent the target direction.
	   - For **TranslationXAxisAngle4D**, **TranslationYAxisAngle4D**, and **TranslationZAxisAngle4D** the first value
	   represents the angle.
	   - For **TranslationLocalGlobal6D**, the diagonal elements ([0],[4],[8]) are the local translation inside the end
	   effector coordinate system.
	 */
	IKFAST_API bool ComputeIk(const IkReal* eetrans, const IkReal* eerot, const IkReal* pfree,
		ikfast::IkSolutionListBase< IkReal >& solutions);

	/** \brief Similar to ComputeIk except takes OpenRAVE boost::shared_ptr<RobotBase::Manipulator>*
	 */
	IKFAST_API bool ComputeIk2(const IkReal* eetrans, const IkReal* eerot, const IkReal* pfree,
		ikfast::IkSolutionListBase< IkReal >& solutions, void* pOpenRAVEManip);

	/// \brief Computes the end effector coordinates given the joint values. This function is used to double check ik.
	IKFAST_API void ComputeFk(const IkReal* joints, IkReal* eetrans, IkReal* eerot);

	/// \brief returns the number of free parameters users has to set apriori
	IKFAST_API int GetNumFreeParameters();

	/// \brief the indices of the free parameters indexed by the chain joints
	IKFAST_API int* GetFreeParameters();

	/// \brief the total number of indices of the chain
	IKFAST_API int GetNumJoints();

	/// \brief the size in bytes of the configured number type
	IKFAST_API int GetIkRealSize();

	/// \brief the ikfast version used to generate this file
	IKFAST_API const char* GetIkFastVersion();

	/// \brief the ik type ID
	IKFAST_API int GetIkType();

	/// \brief a hash of all the chain values used for double checking that the correct IK is used.
	IKFAST_API const char* GetKinematicsHash();

#ifdef IKFAST_NAMESPACE
}
#endif

#endif  // IKFAST_HAS_LIBRARY

armKine.h

#pragma once

#ifndef UR_KIN_H
#define UR_KIN_H

// These kinematics find the tranfrom from the base link to the end effector.
// Though the raw D-H parameters specify a transform from the 0th link to the 6th link,
// offset transforms are specified in this formulation.
// To work with the raw D-H kinematics, use the inverses of the transforms below.

// Transform from base link to 0th link
// -1,  0,  0,  0
//  0, -1,  0,  0
//  0,  0,  1,  0
//  0,  0,  0,  1

// Transform from 6th link to end effector
//  0, -1,  0,  0
//  0,  0, -1,  0
//  1,  0,  0,  0
//  0,  0,  0,  1

namespace ur_kinematics {
	// @param q       The 6 joint values 
	// @param T       The 4x4 end effector pose in row-major ordering
	void forward(const double* q, double* T);

	// @param q       The 6 joint values 
	// @param Ti      The 4x4 link i pose in row-major ordering. If NULL, nothing is stored.
	void forward_all(const double* q, double* T1, double* T2, double* T3,
		double* T4, double* T5, double* T6);

	// @param T       The 4x4 end effector pose in row-major ordering
	// @param q_sols  An 8x6 array of doubles returned, all angles should be in [0,2*PI)
	// @param q6_des  An optional parameter which designates what the q6 value should take
	//                in case of an infinite solution on that joint.
	// @return        Number of solutions found (maximum of 8)
	int inverse(const double* T, double* q_sols, double q6_des = 0.0);
};

#endif //UR_KIN_H

结果得到:

和RoboDK验证(区别应该来自于参数精度,实际UR参数应该从系统calibration文件中获取) 

【参考】【UR六轴机械臂运动学逆解算法C++(MoveIT!)_机械臂逆解 c++_RealMadrid1920的博客-CSDN博客】

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS OpenRAVE 常用逆解库 ikfast (应用于UR机械臂) 的相关文章

  • 运行Mapreduce,运行一半卡着不动了

    64 root 64 master mr inverted test bash run sh rmr DEPRECATED Please use rm r instead 19 01 17 23 22 23 INFO fs TrashPol
  • 51单片机 | LCD1602 液晶显示实验

    文章目录 一 LCD1602 介绍1 LCD1602 简介2 LCD1602 常用指令3 LCD1602 使用 二 硬件设计三 软件设计1 LCD1602 驱动函数2 主函数 四 实验现象 在前面章节 xff0c 我们已经学习过几种显示装置
  • Ubuntu18.04下自定义meauconfig

    一 前言 本文记录ubutu18 04下自定义meauconfig的安装使用 二 安装 参考链接 xff1a https nuttx apache org docs latest quickstart install html 或者可以看这
  • 服务器搭建及数据库部署

    服务器搭建 参考文章 快速搭建一个自己的服务器详解 xff08 java环境 xff09 因为上学期做非关系数据库课程实验时使用过PolarDB云数据库 xff0c 进行过阿里云的学生认证 xff0c 所以此次云服务器也就选择了Ali的开发
  • MATLAB 2018b 安装 mexopencv (VS 2017 编译)

    MATLAB 2018b 安装 mexopencv VS 2017 编译 之前电脑上装的是MATLAB 2016b 没办法识别VS 2017 虽然官方说有补丁解决这个问题 但还是下了最新的2018b 2018b 识别VS 2017 是没问题
  • Mybatis搞五下(分页、缓存)

    Mybatis搞五下 xff08 分页 缓存 xff09 上篇博客我们讲了动态SQL xff0c 一一多多和延迟加载问题 xff0c 这篇我们讲点轻松的东西 xff0c 关于分页插件pageHelper和Mybatis面试常问的缓存问题 M
  • 03、postman前置脚本

    postman前置脚本是指在Pre requests Script中编写的js脚本 xff0c 一个请求在发送之前 xff0c 会先去执行Pre Request Script xff08 前置脚本 xff09 中的代码 xff0c 可以是为
  • Python3爬取淘宝网商品数据!

    分析淘宝网 这次选择的是淘宝网热卖而不是淘宝网 xff0c 二者虽然名字有不同 xff0c 但是数据还是一样的 xff0c 区别就在于前者把后者的所有店铺和商品的海量数据按照销售量 好评度 信誉度综合测评 重新计算 重新排序展现给买家的一个
  • Python实现淘宝准点抢单!双十一秒杀神器啊!还不来学?

    一 ChromeDriver的安装 若想使用Selenium成功调用Chrome浏览器完成相应的操作 xff0c 需要通过ChromeDriver来驱动 我们在下载之前先来确认下我们使用的Chrome浏览器版本 只需要红框内几位相同即可 根
  • 【点云系列】 场景识别类导读

    文章目录 1 背景知识2 定义3 传统方法4 基于深度学习的方法5 其他参考 xff1a 终于可以简单写一下这一块的导读了 xff0c 拖了一个多周了 希望可以帮助到大家 xff1b xff09 1 背景知识 点云检索 xff08 poin
  • 异常检测综述(Anomaly Detection: A Survey)

    Anomaly Detection A Survey 异常检测综述 xff1a 异常检测是一个重要的问题 xff0c 已经在不同的研究领域和应用领域进行了研究 许多异常检测技术是专门为某些应用领域开发的 xff0c 而其他技术则更为通用 本
  • 基于Prometheus和k8s搭建监控系统

    文章目录 1 实验环境2 Prometheus介绍 xff1f 3 Prometheus特点3 1 样本 4 Prometheus组件介绍5 Prometheus和zabbix对比分析6 Prometheus的几种部署模式6 1 基本高可用
  • STM32F4 | 窗口门狗(WWDG)实验

    文章目录 一 STM32F4 窗口看门狗简介二 硬件设计三 软件设计四 实验现象五 STM32CubeMX 配置 WWDG 在本章中 xff0c 我们将使用窗口看门狗的 中断功能来喂狗 xff0c 通过 DS0 和 DS1 提示程序的运行状
  • deepin15.11系统下使用源码包(tar.xz)安装MySQL 8.0+(补充)

    1 下载MySQL的安装包 1 1 进入官网 xff0c 找到下载 官网地址 mysql官网 1 2 找到下载入口 1 3 选择这个 1 4找到适合自己电脑系统版本 2 安装 配置MySQL和创建mysql用户 注意 最好使用root安装和
  • 基于docker部署prometheus

    1 prometheus架构 Prometheus Server 收集指标和存储时间序列数据 xff0c 并提供查询接口 ClientLibrary 客户端库 Push Gateway 短期存储指标数据 主要用于临时性的任务 Exporte
  • Prometheus监控实战系列二十:监控Kubernetes集群(下)

    本文承接上篇 xff0c 在本篇中我们会讲解Prometheus如何应用基于Kubernetes的服务发现功能 xff0c 检索目标信息并进行监控 在监控策略上 xff0c 我们将混合使用白盒监控与黑盒监控两种模式 xff0c 建立起包括基
  • RT-Thread 简介及架构

    RT Thread xff0c 全称是 Real Time Thread xff0c 顾名思义 xff0c 它是一个嵌入式实时多线程操作系统 xff0c 基本属性之一是支持多任务 xff0c 允许多个任务同时运行并不意味着处理器在同一时刻真
  • 进程的结构

    什么是进程 UNIX标准 xff08 特别是IEEE Std 1003 1 2004年版 xff09 把进程定义为 一个其中运行着一个或多个线程的地址空间和这些线程所需要的系统资源 目前 xff0c 可以把进程看作正在运行的程序 像Linu
  • 【代码小坑】梯度回传为0

    记录一下训练过程中遇到的问题 xff0c 由于这个问题我花了很长时间才解决 xff0c 所以值得记录 先给出结论 xff1a tensor转换成numpy后会丢失梯度 xff0c 导致回传出现问题 由于原代码不容易理解 xff0c 简单用个
  • (超详细)零基础如何学习操作系统---操作系统书籍推荐

    直接先给出路线书籍 编码 隐匿在计算机软硬件背后的语言 汇编语言 x86从实模式到保护模式 操作系统导论 操作系统真象还原 查漏补缺 1 编码 隐匿在计算机软硬件背后的语言 对于完全不懂计算机的朋友 xff0c 这本书可以让你对计算机有一个

随机推荐

  • 多种形式ICP问题的ceres实例应用

    一家之言 xff0c 仅作分享 xff0c 如有不合理或需要改进的地方 xff0c 欢迎各位讨论 ICP方法主要解决空间点云3D 3D的运动估计问题 xff0c 已知 xff1a t 1 t 1 t 1 和
  • git配置以及git-cola使用教程

    git安装 打开终端 xff0c 输入sudo apt get install git git配置 配置用户名 git config global user name 34 user name 34 配置邮箱 git config glob
  • C++ 手撸简易服务器

    本文使用上一期写的反射类 xff0c 另外我发现 lt WinSock2 h gt 这个头文件里有RegisterClass 这个结构 xff0c 还有typedef RegisterClass RegisterClassW这句话 这都能重
  • STM32CubeMX实战教程(一)——软件入门

    软件入门 前言新建工程界面简介MCU外设配置时钟树工程设置工具生成代码代码分析main cgpio cstm32f4xx it c 程序下载现象 结语 前言 STM32Cube 是一个全面的软件平台 xff0c 包括了ST产品的每个系列 平
  • STM32F4 | 定时器中断实验

    文章目录 一 STM32F429 通用定时器简介二 硬件设计三 软件设计四 实验现象五 STM32CubeMX 配置定时器更新中断功能 这一章介绍如何使用 STM32F429 的通用定时器 xff0c STM32F429 的定时器功能十分强
  • 相机标定和ORBSLAM2/VINS测试

    目录 一 相机标定1 1 标定目的1 2 常见模型介绍1 2 1 相机模型1 2 2 畸变模型 1 3 双目标定1 3 1 常见标定工具及对应使用场景1 3 2 Kalibr标定1 3 3 opencv双目标定1 3 4 basalt标定
  • matlab安装教程

    MATLAB xff08 矩阵实验室 xff09 是MATrix LABoratory的缩写 xff0c 是一款由美国The MathWorks公司出品的商业数学软件 MATLAB是一种用于算法开发 数据可视化 数据分析以及数值计算的高级技
  • 软件工程结构化分析

    需求分析的概念 需求分析是软件定义时期的最后一个阶段 xff0c 它的基本任务是准确的回答 系统必须做什么 这个问题 也就是对目标系统提出完整 准确 清晰 具体的要求 在需求分析阶段结束之前 xff0c 系统分析员应该写出软件需求规格说明书
  • 树莓派忘记密码 vnc登陆显示‘No configured security type is supported by 3.3 viewer’的问题解决办法

    树莓派忘记密码以及部署VNC 1 修改密码 需求你的树莓派有屏幕 xff0c 没有屏幕的可以百度其他解决方案了一把键盘 树莓派吃灰了很久 xff0c 最近由于有新的需求 xff0c 就拿出来玩耍一下 首先是第一个问题 xff0c 如何查看i
  • imx6ull 正点原子设备树适配韦东山的开发板 (一)顺利启动,配置led,button

    设备树在公司经常用到 有时候很多驱动编写也就是替换设备树 所以拿韦老师的板子练手设备树 这次尝试直接拿正点的设备书改成韦老师的板子能用 对比 正点原子的设备树结构图 韦东山的设备树结构图 从因为蓝色的是开发板厂商对开发板自己的优化 所以我们
  • 一文了解目标检测边界框概率分布

    一文了解目标检测边界框概率分布 概率建模 众所周知 xff0c CNN的有监督学习通常是建立在给定训练数据集之上的 xff0c 数据集的标签 也称为GT xff0c 决定了人类期望模型学习的样子 它通过损失函数 优化器等与CNN模型相连 因
  • Kalibr安装教程

    系统 xff1a Ubuntu18 04 首先 xff0c 需要安装好gcc g 43 43 cmake ros xff0c 如果没有 xff0c 可使用如下命令一键安装 sudo apt get install gcc g 43 span
  • 程序员:每一份不忘初心的情怀, 都是对技术的追求

    1 真正的情怀 xff0c 是从不矫情 这几年 情怀 大约快成了贬义 创业讲情怀 xff0c 产品讲情怀 xff0c 好像没点情怀都不好意思出门见人 我们曾经充满热情 xff0c 是一位开源软件倡导者 xff0c 我们崇尚全栈工程师才有未来
  • HTML代码简写方法

    原文链接 xff1a HTML代码简写方法 大写的E代表一个HTML标签 1 E 代表HTML标签 2 E id 代表id属性 3 E class 代表class属性 4 E attr 61 foo 代表某一个特定属性 5 E foo 代表
  • Git远程分支

    远程分支 远程分支是位于远程仓库的分支 xff0c 我们通常会用远程分支来更新本地分支 xff0c 然后在本地进行修改 xff0c 最后将修改的结果同步到远程分支上 除此之外 xff0c 我们还需要搞清楚远程跟踪分支和跟踪分支的概念 远程跟
  • STM32F4 | PWM输出实验

    文章目录 一 PWM 简介二 硬件设计三 软件设计四 实验现象五 STM32CubeMX 配置定时器 PWM 输出功能 上一章 xff0c 我们介绍了 STM32F429 的通用定时器 TIM3 xff0c 用该定时器的中断来控制 DS1
  • 基于大疆RM3508电机的串级PID(角度环+速度环)

    1 前言 最近参加ROBOCON xff0c 我负责编写传球机器人 xff0c 由于传球机构需要一个电机转固定角度来带动球 xff0c 所以便用大疆3508电机通过串级PID来实现 xff0c 不得不说3508电机还是真的强 xff0c 先
  • ROS三种通信方式之服务通信

    一 服务通信的理论模型 服务通信也是ROS中一种极其常用的通信模式 xff0c 服务通信是基于请求响应模式的 xff0c 是一种应答机制 也即 一个节点A向另一个节点B发送请求 xff0c B接收处理请求并产生响应结果返回给A 就像是服务器
  • 滑模控制理论(SMC)

    滑模控制理论 Sliding Mode Control SMC 滑膜控制理论是一种建立在现代控制理论基础上的控制理论 xff0c 其核心为李雅普诺夫函数 xff0c 滑膜控制的核心是建立一个滑模面 xff0c 将被控系统拉倒滑模面上来 xf
  • ROS OpenRAVE 常用逆解库 ikfast (应用于UR机械臂)

    ArmKine cpp include 34 armKine h 34 include lt math h gt include lt stdio h gt include lt corecrt math defines h gt defi