// SPDX-License-Identifier: LGPL-2.1-or-later /*************************************************************************** * Copyright (c) 2002 Jürgen Riegel * * * * 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 "kdl_cp/chainfksolverpos_recursive.hpp" #include "kdl_cp/chainiksolverpos_nr_jl.hpp" #include "kdl_cp/chainiksolvervel_pinv.hpp" #include #include #include #include #include #include "Robot6Axis.h" #include "RobotAlgos.h" namespace Robot { // clang-format off // 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 }; // clang-format on TYPESYSTEM_SOURCE(Robot::Robot6Axis, Base::Persistence) Robot6Axis::Robot6Axis() : Actual(KDL::JntArray(6)) , Min(KDL::JntArray(6)) , Max(KDL::JntArray(6)) { // set to default kuka 500 setKinematic(KukaIR500); } void Robot6Axis::setKinematic(const AxisDefinition KinDef[6]) { KDL::Chain temp; for (int i = 0; i < 6; i++) { temp.addSegment( KDL::Segment( KDL::Joint(KDL::Joint::RotZ), KDL::Frame::DH( KinDef[i].a, Base::toRadians(KinDef[i].alpha), KinDef[i].d, Base::toRadians(KinDef[i].theta) ) ) ); RotDir[i] = KinDef[i].rotDir; Max(i) = Base::toRadians(KinDef[i].maxAngle); Min(i) = Base::toRadians(KinDef[i].minAngle); Velocity[i] = KinDef[i].velocity; } // for now and testing Kinematic = temp; // get the actual TCP out of the axis calcTcp(); } double Robot6Axis::getMaxAngle(int Axis) { return Base::toDegrees(Max(Axis)); } double Robot6Axis::getMinAngle(int Axis) { return Base::toDegrees(Min(Axis)); } void split(std::string const& string, const char delimiter, std::vector& 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 == delimiter) { 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]; Base::FileInfo fi(FileName); Base::ifstream in(fi); if (!in) { return; } std::vector destination; AxisDefinition temp[6]; // over read the header in.getline(buf, 119, '\n'); // read 6 Axis for (auto& i : temp) { in.getline(buf, 79, '\n'); destination.clear(); split(std::string(buf), ',', destination); if (destination.size() < 8) { continue; } // transfer the values in kinematic structure i.a = atof(destination[0].c_str()); i.alpha = atof(destination[1].c_str()); i.d = atof(destination[2].c_str()); i.theta = atof(destination[3].c_str()); i.rotDir = atof(destination[4].c_str()); i.maxAngle = atof(destination[5].c_str()); i.minAngle = atof(destination[6].c_str()); i.velocity = atof(destination[7].c_str()); } setKinematic(temp); } unsigned int Robot6Axis::getMemSize() const { return 0; } void Robot6Axis::Save(Base::Writer& writer) const { for (unsigned int i = 0; i < 6; i++) { Base::Placement Tip = toPlacement(Kinematic.getSegment(i).getFrameToTip()); writer.Stream() << writer.ind() << "(Max(i)) << "\" " << "minAngle=\"" << Base::toDegrees(Min(i)) << "\" " << "AxisVelocity=\"" << Velocity[i] << "\" " << "Pos=\"" << Actual(i) << "\"/>" << std::endl; } } void Robot6Axis::Restore(Base::XMLReader& reader) { KDL::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.getAttribute("Px"), reader.getAttribute("Py"), reader.getAttribute("Pz") ), Base::Rotation( reader.getAttribute("Q0"), reader.getAttribute("Q1"), reader.getAttribute("Q2"), reader.getAttribute("Q3") ) ); Temp.addSegment(KDL::Segment(KDL::Joint(KDL::Joint::RotZ), toFrame(Tip))); if (reader.hasAttribute("rotDir")) { Velocity[i] = reader.getAttribute("rotDir"); } else { Velocity[i] = 1.0; } // read the axis constraints Min(i) = Base::toRadians(reader.getAttribute("maxAngle")); Max(i) = Base::toRadians(reader.getAttribute("minAngle")); if (reader.hasAttribute("AxisVelocity")) { Velocity[i] = reader.getAttribute("AxisVelocity"); } else { Velocity[i] = 156.0; } Actual(i) = reader.getAttribute("Pos"); } Kinematic = Temp; calcTcp(); } bool Robot6Axis::setTo(const Base::Placement& To) { // Creation of the solvers: KDL::ChainFkSolverPos_recursive fksolver1(Kinematic); // Forward position solver KDL::ChainIkSolverVel_pinv iksolver1v(Kinematic); // Inverse velocity solver KDL::ChainIkSolverPos_NR_JL iksolver1( Kinematic, Min, Max, fksolver1, iksolver1v, 100, 1e-6 ); // Maximum 100 iterations, stop at accuracy 1e-6 // Creation of jntarrays: KDL::JntArray result(Kinematic.getNrOfJoints()); // Set destination frame KDL::Frame F_dest = KDL::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(Actual, F_dest, result) < 0) { return false; } else { Actual = result; Tcp = F_dest; return true; } } Base::Placement Robot6Axis::getTcp() { 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() { // Create solver based on kinematic chain KDL::ChainFkSolverPos_recursive fksolver = KDL::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(Actual, cartpos); if (kinematics_status >= 0) { Tcp = cartpos; return true; } else { return false; } } bool Robot6Axis::setAxis(int Axis, double Value) { Actual(Axis) = RotDir[Axis] * Base::toRadians(Value); return calcTcp(); } double Robot6Axis::getAxis(int Axis) { return RotDir[Axis] * Base::toDegrees(Actual(Axis)); } } /* namespace Robot */