genericArmCtrl.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 
00018 #include <cob_trajectory_controller/genericArmCtrl.h>
00019 #include <fstream>
00020 #include <cob_trajectory_controller/RefValJS_PTP_Trajectory.h>
00021 #include <cob_trajectory_controller/RefValJS_PTP.h>
00022 
00023 
00024 /********************************************************************
00025  *          Some macros for error checking and handling             *
00026  ********************************************************************/
00027 
00028 
00029 
00030 #define STD_CHECK_PROCEDURE()                                                                                   \
00031 if ( isMoving )                                                                                                         \
00032 {                                                                                                                                               \
00033         ROS_WARN("Manipulator still in motion, call stop first!");              \
00034         return false;                                                                                                           \
00035 }                                                                                                                                               \
00036 if (m_pRefVals != NULL) {                                                                                               \
00037         delete m_pRefVals;                                                                                                      \
00038         m_pRefVals = NULL;                                                                                                      \
00039 }
00040 
00041 
00042 #define START_CTRL_JOB(info)                                                                                    \
00043 if ( m_cThread.startJob(m_pRefVals) == false ) {                                                \
00044         m_ErrorMsg.assign("Internal Error: Unable to start movement, other control Job still active."); \
00045         return false;                                                                                                           \
00046 } else {                                                                                                                                \s                                                                                              \
00047         return true;                                                                                                            \
00048 }
00049 
00050 
00051 
00052 
00053 /********************************************************************
00054  *                  Initialisierungsfunktionen                      *
00055  ********************************************************************/
00056 
00057 
00058 genericArmCtrl::genericArmCtrl(int DOF, double PTPvel, double PTPacc, double maxError)
00059 {
00060 
00061         m_DOF = DOF;
00062 
00063         m_pRefVals = NULL;
00064 
00065         isMoving = false;
00066 
00067         //TODO: make configurable
00068         SetPTPvel(PTPvel);
00069         SetPTPacc(PTPacc);
00070 
00071         //m_P = 2.5;
00072         m_P = 4.0;
00073         m_Vorsteuer = 0.9;
00074         m_AllowedError = maxError;//0.5;//0.25; // rad
00075         m_CurrentError = 0.0; // rad
00076         m_TargetError = 0.02; // rad;
00077         overlap_time = 0.4;
00078         m_ExtraTime = 3;        // s
00079 
00080 }
00081 
00082 
00083 genericArmCtrl::~genericArmCtrl()
00084 {
00085         if (m_pRefVals != NULL)
00086                 delete m_pRefVals;
00087 }
00088 
00089 /********************************************************************
00090  *                      Parameter Abfragen                          *
00091  ********************************************************************/
00092 
00093 std::vector<double> genericArmCtrl::GetPTPvel() const
00094         { return m_vel_js; }
00095 
00096 std::vector<double> genericArmCtrl::GetPTPacc() const
00097         { return m_acc_js; }
00098 
00099 
00100 
00101 
00102 /********************************************************************
00103  *                       Parameter Setzen                           *
00104  ********************************************************************/
00105 
00106 void genericArmCtrl::SetPTPvel(double vel)
00107 {
00108         m_vel_js.resize(m_DOF);
00109         for (int i = 0; i < m_DOF; i++)
00110                 m_vel_js.at(i) = vel;
00111 }
00112 
00113 void genericArmCtrl::SetPTPacc(double acc)
00114 {
00115         m_acc_js.resize(m_DOF);
00116         for (int i = 0; i < m_DOF; i++)
00117                 m_acc_js.at(i) = acc;
00118 }
00119 
00120 /********************************************************************
00121  *                   PTP (Joint Space) Motion:                      *
00122  ********************************************************************/
00123 
00125 bool genericArmCtrl::moveThetas(std::vector<double> conf_goal, std::vector<double> conf_current)
00126 {
00127         /* Prüfen ob Arm noch in Bewegung & Prüfen ob alte Sollwerte gelöscht werden müssen: */
00128         STD_CHECK_PROCEDURE()
00129 
00130         /* Sollwerte generieren: */
00131         double vel = 10000;
00132         for     (unsigned int i = 0; i<m_vel_js.size(); i++)
00133         {
00134                 if(m_vel_js.at(i) < vel)
00135                         vel = m_vel_js.at(i);
00136         }
00137         double acc = 10000;
00138         for     (unsigned int i = 0; i<m_acc_js.size(); i++)
00139         {
00140                 if(m_acc_js.at(i) < acc)
00141                         acc = m_acc_js.at(i);
00142         }
00143 
00144                                         ;
00145         m_pRefVals = new RefValJS_PTP(conf_current, conf_goal, vel, acc);
00146         startTime_.SetNow();
00147         isMoving = true;
00148         TotalTime_ = m_pRefVals->getTotalTime();
00149         ROS_INFO("Starting control of trajectory: %f s long", TotalTime_);
00150 
00151         return true; //TODO when to return false?
00152 }
00153 
00154 bool genericArmCtrl::moveTrajectory(trajectory_msgs::JointTrajectory pfad, std::vector<double> conf_current)
00155 {
00156         /* Prüfen, ob erster Punkt nah genug an momentaner Position ist: */
00157         if (pfad.points.size() == 2)
00158         {
00159                 return moveThetas(pfad.points[1].positions, conf_current);
00160         }
00161         for(unsigned int i = 0; i < pfad.points.front().positions.size(); i++ )
00162         {
00163                 if((pfad.points.front().positions.at(i) - conf_current.at(i)) > 0.25)
00164                 {
00165                         ROS_ERROR("Cannot start trajectory motion, manipulator not in trajectory start position.");
00166                         return false;
00167                 }
00168         }
00169 
00170         /* Prüfen ob Arm noch in Bewegung & Prüfen ob alte Sollwerte gelöscht werden müssen: */
00171         STD_CHECK_PROCEDURE()
00172 
00173         /* Sollwerte generieren: */
00174         double vel = m_vel_js.at(0);
00175         for     (unsigned int i = 0; i<m_vel_js.size(); i++)
00176         {
00177                 if(m_vel_js.at(i) < vel)
00178                         vel = m_vel_js.at(i);
00179         }
00180         double acc = m_acc_js.at(0);
00181         for     (unsigned int i = 0; i<m_acc_js.size(); i++)
00182         {
00183                 if(m_acc_js.at(i) < acc)
00184                         acc = m_acc_js.at(i);
00185         }
00186         m_pRefVals = new RefValJS_PTP_Trajectory(pfad, vel, acc, true);
00187 
00188         /* Regeljob starten: */
00189         startTime_.SetNow();
00190         isMoving = true;
00191         TotalTime_ = m_pRefVals->getTotalTime();
00192         ROS_INFO("Starting control of trajectory: %f s long", TotalTime_);
00193 
00194         //START_CTRL_JOB(Trajectory)
00195         return true;
00196 }
00197 
00198 //bool genericArmCtrl::movePos(AbsPos position)
00199 //{
00200 //      /* Prüfen ob Arm noch in Bewegung & Prüfen ob alte Sollwerte gelöscht werden müssen: */
00201 //      STD_CHECK_PROCEDURE()
00202 //
00203 //      Jointd start = getCurrentAngles();
00204 //
00205 //      // attempt to move along straight line:
00206 //      RefValJS_CartesianStraight* rv = new RefValJS_CartesianStraight(m_pKin, start);
00207 //      m_pRefVals = rv;
00208 //      if ( rv->calculate(position, m_vel_cartesian, m_acc_cartesian) == false )
00209 //      {
00210 //              m_ErrorMsg.assign("MovePos: Target Position not reachable.");
00211 //              #ifdef GENERIC_ARM_CTRL_LOG
00212 //              m_log << m_ErrorMsg << "\n";
00213 //              #endif
00214 //              return false;
00215 //      }
00216 //
00217 //      /* Regeljob starten: */
00218 //      START_CTRL_JOB(Cartesian)
00219 //}
00220 
00221 bool genericArmCtrl::step(std::vector<double> current_pos, std::vector<double> & desired_vel)
00222 {
00223         if(isMoving)
00224         {
00225                 TimeStamp timeNow_;
00226                 timeNow_.SetNow();
00227 
00228                 if ( m_pRefVals == NULL )
00229                                 return false;
00230                 double t = timeNow_ - startTime_;
00231                 std::vector<double> m_qsoll = m_pRefVals->r_t( t );
00232                 std::vector<double> m_vsoll = m_pRefVals->dr_dt(t);
00233 
00234                 if(t < TotalTime_)
00235                 {
00236                         if(t < overlap_time)
00237                         {
00238                                 last_q = m_pRefVals->r_t( 0.0 );
00239                                 last_q1 = m_pRefVals->r_t( 0.0 );
00240                                 last_q2 = m_pRefVals->r_t( 0.0 );
00241                                 last_q3 = m_pRefVals->r_t( 0.0 );
00242                         }
00243                         else
00244                         {
00245                                 last_q = m_pRefVals->r_t( t - overlap_time );
00246                                 last_q1 = m_pRefVals->r_t( t - (3.0*overlap_time/4.0) );
00247                                 last_q2 = m_pRefVals->r_t( t - (overlap_time/2.0) );
00248                                 last_q3 = m_pRefVals->r_t( t - (overlap_time/4.0) );
00249                         }
00250                 }
00251 
00252                 double len = 0;
00253                 for(int i = 0; i < m_DOF; i++)
00254                 {
00255                          len +=  (m_qsoll.at(i) - current_pos.at(i)) * (m_qsoll.at(i) - current_pos.at(i));
00256                 }
00257                 m_CurrentError = sqrt(len);
00258                 if ( m_pRefVals != NULL && t < TotalTime_ + m_ExtraTime && (m_CurrentError > m_TargetError || t < TotalTime_) )
00259                 {
00260                                 if ( m_CurrentError >= m_AllowedError )
00261                                 {
00262                                         ROS_ERROR("Current control error exceeds limit: %f >= %f", m_CurrentError, m_AllowedError);
00263                                         //TODO: make generic to avoid out of bound exception
00264                                         //ROS_ERROR("Current Soll: %f %f %f %f %f %f %f ", m_qsoll.at(0), m_qsoll.at(1), m_qsoll.at(2), m_qsoll.at(3), m_qsoll.at(4), m_qsoll.at(5), m_qsoll.at(6));
00265                                         //ROS_ERROR("Current Ist: %f %f %f %f %f %f %f ", current_pos.at(0), current_pos.at(1), current_pos.at(2), current_pos.at(3), current_pos.at(4), current_pos.at(5), current_pos.at(6));
00266                                         isMoving = false;
00267                                         return false;
00268                                 }
00269                                 desired_vel.resize(m_DOF);
00270                                 /* Vorsteuerung + P-Lageregler: */
00271                                 for(int i = 0; i < m_DOF; i++)
00272                                 {
00273                                         desired_vel.at(i) = m_vsoll.at(i) * m_Vorsteuer + ( m_qsoll.at(i) - current_pos.at(i) ) * m_P;
00274                                 }
00275 
00276                                 return true;
00277                 }
00278                 else /* entweder sind keine Sollwerte vorhanden, oder Zeit ist abgelaufen */
00279                 {
00280                         ROS_INFO("Probably finished trajectory");
00281                         isMoving = false;
00282                         desired_vel.resize(m_DOF);
00283                         for(int i = 0; i < m_DOF; i++)
00284                         {
00285                                 desired_vel.at(i) = 0.0;
00286                         }
00287                         return true;
00288                 }
00289         }
00290         return false;
00291 }
00292 
00293 
00294 
00295 


cob_trajectory_controller
Author(s): Alexander Bubeck
autogenerated on Thu Jun 6 2019 21:19:22