Download src/Mod/Robot/App/Trajectory.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 11.7 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Robot/App/Trajectory.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Robot/App/Trajectory.cpp
-
curl -L -o Trajectory.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Robot/App/Trajectory.cpp
11.7 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> * | |
| * * | |
| * 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 * | |
| * * | |
| ***************************************************************************/ | |
| using namespace Robot; | |
| using namespace Base; | |
| TYPESYSTEM_SOURCE(Robot::Trajectory, Base::Persistence) | |
| Trajectory::Trajectory() = default; | |
| Trajectory::Trajectory(const Trajectory& Trac) | |
| : vpcWaypoints(Trac.vpcWaypoints.size()) | |
| , pcTrajectory(nullptr) | |
| { | |
| operator=(Trac); | |
| } | |
| Trajectory::~Trajectory() | |
| { | |
| for (auto it : vpcWaypoints) { | |
| delete it; | |
| } | |
| delete pcTrajectory; | |
| } | |
| Trajectory& Trajectory::operator=(const Trajectory& Trac) | |
| { | |
| if (this == &Trac) { | |
| return *this; | |
| } | |
| for (auto it : vpcWaypoints) { | |
| delete it; | |
| } | |
| vpcWaypoints.clear(); | |
| vpcWaypoints.resize(Trac.vpcWaypoints.size()); | |
| int i = 0; | |
| for (std::vector<Waypoint*>::const_iterator it = Trac.vpcWaypoints.begin(); | |
| it != Trac.vpcWaypoints.end(); | |
| ++it, i++) { | |
| vpcWaypoints[i] = new Waypoint(**it); | |
| } | |
| generateTrajectory(); | |
| return *this; | |
| } | |
| double Trajectory::getLength(int n) const | |
| { | |
| if (pcTrajectory) { | |
| if (n < 0) { | |
| return pcTrajectory->GetPath()->PathLength(); | |
| } | |
| else { | |
| return pcTrajectory->Get(n)->GetPath()->PathLength(); | |
| } | |
| } | |
| else { | |
| return 0; | |
| } | |
| } | |
| double Trajectory::getDuration(int n) const | |
| { | |
| if (pcTrajectory) { | |
| if (n < 0) { | |
| return pcTrajectory->Duration(); | |
| } | |
| else { | |
| return pcTrajectory->Get(n)->Duration(); | |
| } | |
| } | |
| else { | |
| return 0; | |
| } | |
| } | |
| Placement Trajectory::getPosition(double time) const | |
| { | |
| if (pcTrajectory) { | |
| return Placement(toPlacement(pcTrajectory->Pos(time))); | |
| } | |
| return {}; | |
| } | |
| double Trajectory::getVelocity(double time) const | |
| { | |
| if (pcTrajectory) { | |
| KDL::Vector vec = pcTrajectory->Vel(time).vel; | |
| Base::Vector3d vec2(vec[0], vec[1], vec[2]); | |
| return vec2.Length(); | |
| } | |
| else { | |
| return 0; | |
| } | |
| } | |
| void Trajectory::deleteLast(unsigned int n) | |
| { | |
| for (unsigned int i = 0; i <= n; i++) { | |
| delete (*vpcWaypoints.rbegin()); | |
| vpcWaypoints.pop_back(); | |
| } | |
| } | |
| void Trajectory::generateTrajectory() | |
| { | |
| if (vpcWaypoints.empty()) { | |
| return; | |
| } | |
| // delete the old and create a new one | |
| if (pcTrajectory) { | |
| delete (pcTrajectory); | |
| } | |
| pcTrajectory = new KDL::Trajectory_Composite(); | |
| // pointer to the pieces while iterating | |
| std::unique_ptr<KDL::Trajectory_Segment> pcTrak; | |
| std::unique_ptr<KDL::VelocityProfile> pcVelPrf; | |
| std::unique_ptr<KDL::Path_RoundedComposite> pcRoundComp; | |
| KDL::Frame Last; | |
| try { | |
| // handle the first waypoint special | |
| bool first = true; | |
| for (std::vector<Waypoint*>::const_iterator it = vpcWaypoints.begin(); | |
| it != vpcWaypoints.end(); | |
| ++it) { | |
| if (first) { | |
| Last = toFrame((*it)->EndPos); | |
| first = false; | |
| } | |
| else { | |
| // destinct the type of movement | |
| switch ((*it)->Type) { | |
| case Waypoint::LINE: | |
| case Waypoint::PTP: { | |
| KDL::Frame Next = toFrame((*it)->EndPos); | |
| // continues the movement until no continuous waypoint or the end | |
| bool Cont = (*it)->Cont && !(it == --vpcWaypoints.end()); | |
| // start of a continue block | |
| if (Cont && !pcRoundComp) { | |
| pcRoundComp = std::make_unique<KDL::Path_RoundedComposite>( | |
| 3, | |
| 3, | |
| new KDL::RotationalInterpolation_SingleAxis() | |
| ); | |
| // the velocity of the first waypoint is used | |
| pcVelPrf = std::make_unique<KDL::VelocityProfile_Trap>( | |
| (*it)->Velocity, | |
| (*it)->Acceleration | |
| ); | |
| pcRoundComp->Add(Last); | |
| pcRoundComp->Add(Next); | |
| // continue a continues block | |
| } | |
| else if (Cont && pcRoundComp) { | |
| pcRoundComp->Add(Next); | |
| // end a continuous block | |
| } | |
| else if (!Cont && pcRoundComp) { | |
| // add the last one | |
| pcRoundComp->Add(Next); | |
| pcRoundComp->Finish(); | |
| pcVelPrf->SetProfile(0, pcRoundComp->PathLength()); | |
| pcTrak = std::make_unique<KDL::Trajectory_Segment>( | |
| pcRoundComp.release(), | |
| pcVelPrf.release() | |
| ); | |
| // normal block | |
| } | |
| else if (!Cont && !pcRoundComp) { | |
| KDL::Path* pcPath; | |
| pcPath = new KDL::Path_Line( | |
| Last, | |
| Next, | |
| new KDL::RotationalInterpolation_SingleAxis(), | |
| 1.0, | |
| true | |
| ); | |
| pcVelPrf = std::make_unique<KDL::VelocityProfile_Trap>( | |
| (*it)->Velocity, | |
| (*it)->Acceleration | |
| ); | |
| pcVelPrf->SetProfile(0, pcPath->PathLength()); | |
| pcTrak = std::make_unique<KDL::Trajectory_Segment>( | |
| pcPath, | |
| pcVelPrf.release() | |
| ); | |
| } | |
| Last = Next; | |
| break; | |
| } | |
| case Waypoint::WAIT: | |
| break; | |
| default: | |
| break; | |
| } | |
| // add the segment if no continuous block is running | |
| if (!pcRoundComp && pcTrak) { | |
| pcTrajectory->Add(pcTrak.release()); | |
| } | |
| } | |
| } | |
| } | |
| catch (KDL::Error& e) { | |
| throw Base::RuntimeError(e.Description()); | |
| } | |
| } | |
| std::string Trajectory::getUniqueWaypointName(const char* Name) const | |
| { | |
| if (!Name || *Name == '\0') { | |
| return {}; | |
| } | |
| // check for first character whether it's a digit | |
| std::string CleanName = Name; | |
| if (!CleanName.empty() && CleanName[0] >= 48 && CleanName[0] <= 57) { | |
| CleanName[0] = '_'; | |
| } | |
| // strip illegal chars | |
| for (char& it : CleanName) { | |
| if (!((it >= 48 && it <= 57) || // number | |
| (it >= 65 && it <= 90) || // uppercase letter | |
| (it >= 97 && it <= 122))) { // lowercase letter | |
| it = '_'; // it's neither number nor letter | |
| } | |
| } | |
| // name in use? | |
| std::vector<Robot::Waypoint*>::const_iterator it; | |
| for (it = vpcWaypoints.begin(); it != vpcWaypoints.end(); ++it) { | |
| if ((*it)->Name == CleanName) { | |
| break; | |
| } | |
| } | |
| if (it == vpcWaypoints.end()) { | |
| // if not, name is OK | |
| return CleanName; | |
| } | |
| else { | |
| // find highest suffix | |
| int nSuff = 0; | |
| for (it = vpcWaypoints.begin(); it != vpcWaypoints.end(); ++it) { | |
| const std::string& ObjName = (*it)->Name; | |
| if (ObjName.substr(0, CleanName.length()) == CleanName) { // same prefix | |
| std::string clSuffix(ObjName.substr(CleanName.length())); | |
| if (!clSuffix.empty()) { | |
| std::string::size_type nPos = clSuffix.find_first_not_of("0123456789"); | |
| if (nPos == std::string::npos) { | |
| nSuff = std::max<int>(nSuff, std::atol(clSuffix.c_str())); | |
| } | |
| } | |
| } | |
| } | |
| std::stringstream str; | |
| str << CleanName << (nSuff + 1); | |
| return str.str(); | |
| } | |
| } | |
| void Trajectory::addWaypoint(const Waypoint& WPnt) | |
| { | |
| std::string UniqueName = getUniqueWaypointName(WPnt.Name.c_str()); | |
| Waypoint* tmp = new Waypoint(WPnt); | |
| tmp->Name = UniqueName; | |
| vpcWaypoints.push_back(tmp); | |
| } | |
| unsigned int Trajectory::getMemSize() const | |
| { | |
| return 0; | |
| } | |
| void Trajectory::Save(Writer& writer) const | |
| { | |
| writer.Stream() << writer.ind() << "<Trajectory count=\"" << getSize() << "\">" << std::endl; | |
| writer.incInd(); | |
| for (unsigned int i = 0; i < getSize(); i++) { | |
| vpcWaypoints[i]->Save(writer); | |
| } | |
| writer.decInd(); | |
| writer.Stream() << writer.ind() << "</Trajectory>" << std::endl; | |
| } | |
| void Trajectory::Restore(XMLReader& reader) | |
| { | |
| vpcWaypoints.clear(); | |
| // read my element | |
| reader.readElement("Trajectory"); | |
| // get the value of my Attribute | |
| int count = reader.getAttribute<long>("count"); | |
| vpcWaypoints.resize(count); | |
| for (int i = 0; i < count; i++) { | |
| Waypoint* tmp = new Waypoint(); | |
| tmp->Restore(reader); | |
| vpcWaypoints[i] = tmp; | |
| } | |
| generateTrajectory(); | |
| } | |