296 lines
10 KiB
C++
296 lines
10 KiB
C++
/***************************************************************************
|
|
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
#include "PreCompiled.h"
|
|
|
|
#ifndef _PreComp_
|
|
#endif
|
|
|
|
#include <Base/Writer.h>
|
|
#include <Base/Reader.h>
|
|
|
|
#include "kdl_cp/chain.hpp"
|
|
#include "kdl_cp/chainfksolver.hpp"
|
|
#include "kdl_cp/chainfksolverpos_recursive.hpp"
|
|
#include "kdl_cp/frames_io.hpp"
|
|
#include "kdl_cp/chainiksolver.hpp"
|
|
#include "kdl_cp/chainiksolvervel_pinv.hpp"
|
|
#include "kdl_cp/chainjnttojacsolver.hpp"
|
|
#include "kdl_cp/chainiksolverpos_nr.hpp"
|
|
#include "kdl_cp/chainiksolverpos_nr_jl.hpp"
|
|
|
|
#include "Robot6Axis.h"
|
|
#include "RobotAlgos.h"
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846 /* pi */
|
|
#endif
|
|
|
|
#ifndef M_PI_2
|
|
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
|
#endif
|
|
|
|
using namespace Robot;
|
|
using namespace Base;
|
|
using namespace KDL;
|
|
|
|
// some default roboter
|
|
|
|
AxisDefinition KukaIR500[6] = {
|
|
// a ,alpha ,d ,theta ,rotDir ,maxAngle ,minAngle ,AxisVelocity
|
|
{500 ,-90 ,1045 ,0 , -1 ,+185 ,-185 ,156 }, // Axis 1
|
|
{1300 ,0 ,0 ,0 , 1 ,+35 ,-155 ,156 }, // Axis 2
|
|
{55 ,+90 ,0 ,-90 , 1 ,+154 ,-130 ,156 }, // Axis 3
|
|
{0 ,-90 ,-1025,0 , 1 ,+350 ,-350 ,330 }, // Axis 4
|
|
{0 ,+90 ,0 ,0 , 1 ,+130 ,-130 ,330 }, // Axis 5
|
|
{0 ,+180 ,-300 ,0 , 1 ,+350 ,-350 ,615 } // Axis 6
|
|
};
|
|
|
|
|
|
TYPESYSTEM_SOURCE(Robot::Robot6Axis , Base::Persistence);
|
|
|
|
Robot6Axis::Robot6Axis()
|
|
{
|
|
// create joint array for the min and max angle values of each joint
|
|
Min = JntArray(6);
|
|
Max = JntArray(6);
|
|
|
|
// Create joint array
|
|
Actuall = JntArray(6);
|
|
|
|
// set to default kuka 500
|
|
setKinematic(KukaIR500);
|
|
}
|
|
|
|
Robot6Axis::~Robot6Axis()
|
|
{
|
|
}
|
|
|
|
|
|
void Robot6Axis::setKinematic(const AxisDefinition KinDef[6])
|
|
{
|
|
Chain temp;
|
|
|
|
|
|
for(int i=0 ; i<6 ;i++){
|
|
temp.addSegment(Segment(Joint(Joint::RotZ),Frame::DH(KinDef[i].a ,KinDef[i].alpha * (M_PI/180) ,KinDef[i].d ,KinDef[i].theta * (M_PI/180) )));
|
|
RotDir [i] = KinDef[i].rotDir;
|
|
Max(i) = KinDef[i].maxAngle * (M_PI/180);
|
|
Min(i) = KinDef[i].minAngle * (M_PI/180);
|
|
Velocity[i] = KinDef[i].velocity;
|
|
}
|
|
|
|
// for now and testing
|
|
Kinematic = temp;
|
|
|
|
// get the actuall TCP out of tha axis
|
|
calcTcp();
|
|
}
|
|
|
|
double Robot6Axis::getMaxAngle(int Axis)
|
|
{
|
|
return Max(Axis) * (180.0/M_PI);
|
|
}
|
|
|
|
double Robot6Axis::getMinAngle(int Axis)
|
|
{
|
|
return Min(Axis) * (180.0/M_PI);
|
|
}
|
|
|
|
void split(std::string const& string, const char delemiter, std::vector<std::string>& destination)
|
|
{
|
|
std::string::size_type last_position(0);
|
|
std::string::size_type position(0);
|
|
|
|
for (std::string::const_iterator it(string.begin()); it != string.end(); ++it, ++position)
|
|
{
|
|
if (*it == delemiter )
|
|
{
|
|
destination.push_back(string.substr(last_position, position - last_position ));
|
|
last_position = position + 1;
|
|
}
|
|
}
|
|
destination.push_back(string.substr(last_position, position - last_position ));
|
|
}
|
|
|
|
void Robot6Axis::readKinematic(const char * FileName)
|
|
{
|
|
char buf[120];
|
|
std::ifstream in(FileName);
|
|
if(!in)return;
|
|
std::vector<std::string> destination;
|
|
AxisDefinition temp[6];
|
|
|
|
// over read the header
|
|
in.getline(buf,119,'\n');
|
|
// read 6 Axis
|
|
for( int i = 0; i<6; i++){
|
|
in.getline(buf,79,'\n');
|
|
destination.clear();
|
|
split(std::string(buf),',',destination);
|
|
if(destination.size() < 8) continue;
|
|
// transfer the values in kinematic structure
|
|
temp[i].a = atof(destination[0].c_str());
|
|
temp[i].alpha = atof(destination[1].c_str());
|
|
temp[i].d = atof(destination[2].c_str());
|
|
temp[i].theta = atof(destination[3].c_str());
|
|
temp[i].rotDir = atof(destination[4].c_str());
|
|
temp[i].maxAngle = atof(destination[5].c_str());
|
|
temp[i].minAngle = atof(destination[6].c_str());
|
|
temp[i].velocity = atof(destination[7].c_str());
|
|
}
|
|
|
|
setKinematic(temp);
|
|
|
|
}
|
|
|
|
unsigned int Robot6Axis::getMemSize (void) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void Robot6Axis::Save (Writer &writer) const
|
|
{
|
|
for(unsigned int i=0;i<6;i++){
|
|
Base::Placement Tip = toPlacement(Kinematic.getSegment(i).getFrameToTip());
|
|
writer.Stream() << writer.ind() << "<Axis "
|
|
<< "Px=\"" << Tip.getPosition().x << "\" "
|
|
<< "Py=\"" << Tip.getPosition().y << "\" "
|
|
<< "Pz=\"" << Tip.getPosition().z << "\" "
|
|
<< "Q0=\"" << Tip.getRotation()[0] << "\" "
|
|
<< "Q1=\"" << Tip.getRotation()[1] << "\" "
|
|
<< "Q2=\"" << Tip.getRotation()[2] << "\" "
|
|
<< "Q3=\"" << Tip.getRotation()[3] << "\" "
|
|
<< "rotDir=\"" << RotDir[i] << "\" "
|
|
<< "maxAngle=\"" << Max(i)*(180.0/M_PI) << "\" "
|
|
<< "minAngle=\"" << Min(i)*(180.0/M_PI) << "\" "
|
|
<< "AxisVelocity=\""<< Velocity[i] << "\" "
|
|
<< "Pos=\"" << Actuall(i) << "\"/>"
|
|
|
|
<< std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
void Robot6Axis::Restore(XMLReader &reader)
|
|
{
|
|
Chain Temp;
|
|
Base::Placement Tip;
|
|
|
|
for(unsigned int i=0;i<6;i++){
|
|
// read my Element
|
|
reader.readElement("Axis");
|
|
// get the value of the placement
|
|
Tip = Base::Placement(Base::Vector3d(reader.getAttributeAsFloat("Px"),
|
|
reader.getAttributeAsFloat("Py"),
|
|
reader.getAttributeAsFloat("Pz")),
|
|
Base::Rotation(reader.getAttributeAsFloat("Q0"),
|
|
reader.getAttributeAsFloat("Q1"),
|
|
reader.getAttributeAsFloat("Q2"),
|
|
reader.getAttributeAsFloat("Q3")));
|
|
Temp.addSegment(Segment(Joint(Joint::RotZ),toFrame(Tip)));
|
|
|
|
|
|
if(reader.hasAttribute("rotDir"))
|
|
Velocity[i] = reader.getAttributeAsFloat("rotDir");
|
|
else
|
|
Velocity[i] = 1.0;
|
|
// read the axis constraints
|
|
Min(i) = reader.getAttributeAsFloat("maxAngle")* (M_PI/180);
|
|
Max(i) = reader.getAttributeAsFloat("minAngle")* (M_PI/180);
|
|
if(reader.hasAttribute("AxisVelocity"))
|
|
Velocity[i] = reader.getAttributeAsFloat("AxisVelocity");
|
|
else
|
|
Velocity[i] = 156.0;
|
|
Actuall(i) = reader.getAttributeAsFloat("Pos");
|
|
}
|
|
Kinematic = Temp;
|
|
|
|
calcTcp();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Robot6Axis::setTo(const Placement &To)
|
|
{
|
|
//Creation of the solvers:
|
|
ChainFkSolverPos_recursive fksolver1(Kinematic);//Forward position solver
|
|
ChainIkSolverVel_pinv iksolver1v(Kinematic);//Inverse velocity solver
|
|
ChainIkSolverPos_NR_JL iksolver1(Kinematic,Min,Max,fksolver1,iksolver1v,100,1e-6);//Maximum 100 iterations, stop at accuracy 1e-6
|
|
|
|
//Creation of jntarrays:
|
|
JntArray result(Kinematic.getNrOfJoints());
|
|
|
|
//Set destination frame
|
|
Frame F_dest = Frame(KDL::Rotation::Quaternion(To.getRotation()[0],To.getRotation()[1],To.getRotation()[2],To.getRotation()[3]),KDL::Vector(To.getPosition()[0],To.getPosition()[1],To.getPosition()[2]));
|
|
|
|
// solve
|
|
if(iksolver1.CartToJnt(Actuall,F_dest,result) < 0)
|
|
return false;
|
|
else{
|
|
Actuall = result;
|
|
Tcp = F_dest;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
Base::Placement Robot6Axis::getTcp(void)
|
|
{
|
|
double x,y,z,w;
|
|
Tcp.M.GetQuaternion(x,y,z,w);
|
|
return Base::Placement(Base::Vector3d(Tcp.p[0],Tcp.p[1],Tcp.p[2]),Base::Rotation(x,y,z,w));
|
|
}
|
|
|
|
bool Robot6Axis::calcTcp(void)
|
|
{
|
|
// Create solver based on kinematic chain
|
|
ChainFkSolverPos_recursive fksolver = ChainFkSolverPos_recursive(Kinematic);
|
|
|
|
// Create the frame that will contain the results
|
|
KDL::Frame cartpos;
|
|
|
|
// Calculate forward position kinematics
|
|
int kinematics_status;
|
|
kinematics_status = fksolver.JntToCart(Actuall,cartpos);
|
|
if(kinematics_status>=0){
|
|
Tcp = cartpos;
|
|
return true;
|
|
}else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Robot6Axis::setAxis(int Axis,double Value)
|
|
{
|
|
Actuall(Axis) = RotDir[Axis] * Value * (M_PI/180); // degree to radiants
|
|
|
|
return calcTcp();
|
|
}
|
|
|
|
double Robot6Axis::getAxis(int Axis)
|
|
{
|
|
return RotDir[Axis] * (Actuall(Axis)/(M_PI/180)); // radian to degree
|
|
}
|
|
|