00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "Kuka361nAxesAccelerationController.hpp"
00019 #include <rtt/Logger.hpp>
00020 #include <assert.h>
00021 #include <ocl/ComponentLoader.hpp>
00022
00023 ORO_LIST_COMPONENT_TYPE( OCL::Kuka361nAxesAccelerationController )
00024
00025 #define KUKA361_KM { 0.2781*94.14706, 0.2863*103.23529, 0.2887*51.44118, 0.07*175, 0.07*150, 0.07*131.64395 }
00026
00027 #include "math.h"
00028
00029
00030 namespace OCL
00031 {
00032 using namespace RTT;
00033 using namespace std;
00034
00035 Kuka361nAxesAccelerationController::Kuka361nAxesAccelerationController(const string& name)
00036 : TaskContext(name,PreOperational),
00037 num_axes(6),
00038 q(num_axes),
00039 qdot(num_axes),
00040 qdot_des(num_axes),
00041 qddot_con(num_axes),
00042 driveValue(num_axes),
00043 q_meas_Port("nAxesSensorPosition"),
00044 qdot_meas_Port("nAxesSensorVelocity"),
00045 qdot_des_Port("nAxesDesiredVelocity"),
00046 q_con_Port("nAxesOutputAcceleration"),
00047 saturationPort("saturationPort",false),
00048 drives("nAxesOutputTorque"),
00049 torque_meas_Port("nAxesSensorTorque"),
00050 torque_meas_local(num_axes),
00051 dqm("dqm", "SSIGN parameter for kuka361InvDynnf"),
00052 UseDesVel("UseDesVel", "Use desired velocity for the coulomb friction term in Dynamic model"),
00053 torque_offset("torque_offset", "correction for torque offset in dynamic model"),
00054 torque_scale("torque_scale", "correction for torque scale in dynamic model"),
00055 Ts("Ts","Timestep to use",0.01),
00056 saturated(false),
00057 ReportedSaturation(false),
00058 Km(6),
00059 time_data(1),
00060 q_data(6),
00061 qdot_data(6),
00062 qddot_data(6),
00063 tau_meas_data(6),
00064 tau_model_data(6)
00065 {
00066
00067
00068
00069 this->ports()->addPort(&drives);
00070 this->ports()->addPort(&torque_meas_Port);
00071 this->ports()->addPort(&q_meas_Port);
00072 this->ports()->addPort(&qdot_meas_Port);
00073 this->ports()->addPort(&qdot_des_Port);
00074 this->ports()->addPort(&q_con_Port);
00075 this->ports()->addPort(&saturationPort);
00076
00077
00078 this->properties()->addProperty(&dqm);
00079 this->properties()->addProperty(&UseDesVel);
00080 this->properties()->addProperty(&torque_scale);
00081 this->properties()->addProperty(&torque_offset);
00082 this->properties()->addProperty(&Ts);
00083
00084
00085 this->commands()->addCommand(command( "Calibrate_move", &Kuka361nAxesAccelerationController::startCalibration,
00086 &Kuka361nAxesAccelerationController::finishedCalibration, this),
00087 "Calibrate scale and offset for dynamic model",
00088 "duration", "duration of calibration",
00089 "vmin", "minimum calibration velocity",
00090 "vmax", "maximum calibration velocity");
00091
00092
00093 this->methods()->addMethod( method( "Calibrate_calc", &Kuka361nAxesAccelerationController::Calculate, this),
00094 "Calculate model offsets and scales");
00095 this->methods()->addMethod( method( "Start_Monitoring", &Kuka361nAxesAccelerationController::startMonitoring, this),
00096 "start monitoring robot for trajectory optimization");
00097 this->methods()->addMethod( method( "Stop_Monitoring", &Kuka361nAxesAccelerationController::stopMonitoring, this),
00098 "stop monitoring robot for trajectory optimization");
00099
00100 double KM[6] = KUKA361_KM;
00101 for(unsigned int i = 0;i<6;i++){
00102 Km[i] = KM[i];
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 }
00116
00117 bool Kuka361nAxesAccelerationController::configureHook()
00118 {
00119 kuka361INVDYN = new kuka361InvDynnf(dqm.value());
00120 return true;
00121 }
00122
00123 void Kuka361nAxesAccelerationController::cleanupHook()
00124 {
00125 delete kuka361INVDYN;
00126 }
00127
00128
00129 Kuka361nAxesAccelerationController::~Kuka361nAxesAccelerationController(){};
00130
00131 bool Kuka361nAxesAccelerationController::startHook()
00132 {
00133
00134 if (!q_meas_Port.connected())
00135 Logger::log()<<Logger::Warning<<"(Kuka361nAxesAccelerationController) Port "<<q_meas_Port.getName()<<" not connected"<<Logger::endl;
00136 if (!qdot_meas_Port.connected())
00137 Logger::log()<<Logger::Warning<<"(Kuka361nAxesAccelerationController) Port "<<qdot_meas_Port.getName()<<" not connected"<<Logger::endl;
00138 if (!qdot_des_Port.connected())
00139 Logger::log()<<Logger::Warning<<"(Kuka361nAxesAccelerationController) Port "<<qdot_des_Port.getName()<<" not connected"<<Logger::endl;
00140 if (!q_con_Port.connected())
00141 Logger::log()<<Logger::Warning<<"(Kuka361nAxesAccelerationController) Port "<<q_con_Port.getName()<<" not connected"<<Logger::endl;
00142
00143
00144 isCalibrating = false;
00145 isMonitoring = false;
00146 saturated = false;
00147 ReportedSaturation = false;
00148 return true;
00149 }
00150
00151 void Kuka361nAxesAccelerationController::updateHook()
00152 {
00153
00154 q = q_meas_Port.Get();
00155 qdot = qdot_meas_Port.Get();
00156 torque_meas_local = torque_meas_Port.Get();
00157
00158 qddot_con = q_con_Port.Get();
00159
00160
00161 qdot_des = qdot_des_Port.Get();
00162
00163
00164 if(UseDesVel.value()){
00165 driveValue=kuka361INVDYN->invdyn361(q,qdot,qdot_des,qddot_con,torque_scale.value(),torque_offset.value());
00166 }else{
00167 driveValue=kuka361INVDYN->invdyn361(q,qdot,qdot,qddot_con,torque_scale.value(),torque_offset.value());
00168 }
00169
00170
00171 for (unsigned int i=0;i<num_axes;i++) {
00172 if(driveValue[i] < -11.0*Km[i]) {
00173 driveValue[i] = -11.0*Km[i];
00174 saturated = true;
00175 saturationPort.Set(true);
00176 }
00177 else if(driveValue[i] > 11.0*Km[i]) {
00178 driveValue[i] = 11.0*Km[i];
00179 saturated = true;
00180 saturationPort.Set(true);
00181 }
00182 else saturationPort.Set(false);
00183 }
00184
00185
00186 if(saturated && !ReportedSaturation) {
00187 log(Warning)<<"Drive Has been saturated!"<<endlog();
00188 ReportedSaturation=true;
00189 }
00190
00191
00192 if (isCalibrating && TimeService::Instance()->secondsSince(time_begin) > time_sleep)
00193 {
00194 for(unsigned int axis=0;axis<num_axes;axis++){
00195 q_data[axis][samplenumber]=q[axis];
00196 tau_meas_data[axis][samplenumber] = torque_meas_local[axis];
00197 }
00198 time_data[samplenumber] = TimeService::Instance()->secondsSince(time_begin);
00199 for(unsigned int axis=0;axis<num_axes;axis++){
00200 qdot_data[axis][samplenumber]=qdot[axis];
00201 }
00202
00203 samplenumber++;
00204 if (samplenumber == num_samples) isCalibrating = false;
00205 }
00206
00207 if (isMonitoring && TimeService::Instance()->secondsSince(time_begin) > time_sleep)
00208 {
00209 for(unsigned int axis=0;axis<num_axes;axis++){
00210 q_data[axis][samplenumber]=q[axis];
00211 tau_meas_data[axis][samplenumber] = torque_meas_local[axis];
00212 }
00213 time_data[samplenumber] = TimeService::Instance()->secondsSince(time_begin);
00214 for(unsigned int axis=0;axis<num_axes;axis++){
00215 qdot_data[axis][samplenumber]=qdot[axis];
00216 }
00217
00218 samplenumber++;
00219 if (samplenumber >= time_data.size()) {
00220 for(unsigned int axis=0;axis<num_axes;axis++){
00221 q_data[axis].resize(2*q_data[axis].size());
00222 tau_meas_data[axis].resize(2*tau_meas_data[axis].size());
00223 qdot_data[axis].resize(2*qdot_data[axis].size());
00224 }
00225 time_data.resize(2*time_data.size());
00226 }
00227 }
00228
00229
00230
00231 drives.Set(driveValue);
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 }
00249
00250 void Kuka361nAxesAccelerationController::stopHook()
00251 {
00252 for (unsigned int i=0; i<num_axes; i++){
00253 drives.Set(vector<double>(num_axes,0.0));
00254 }
00255 }
00256
00257
00258 bool Kuka361nAxesAccelerationController::startCalibration(double duration, double vmin, double vmax)
00259 {
00260 log(Warning)<<"(Kuka361nAxesAccelerationController) start ModelCalibration"<<endlog();
00261
00262
00263 if (isCalibrating)
00264 return false;
00265
00266
00267 else{
00268
00269 _Calibrate = getPeer("nAxesGeneratorSin")->commands()->getCommand<bool(double,double,double)>("Calibrate");
00270 assert( _Calibrate.ready() );
00271 _Calibrate(duration, vmin, vmax);
00272
00273
00274 time_sleep = 1.;
00275 time_begin = TimeService::Instance()->getTicks();
00276 num_samples = (int)(duration/Ts.rvalue() - 2*time_sleep/Ts.rvalue());
00277
00278 time_data.resize(num_samples);
00279 for(unsigned int axis=0;axis<num_axes;axis++){
00280 q_data[axis].resize(num_samples);
00281 qdot_data[axis].resize(num_samples);
00282 qddot_data[axis].resize(num_samples-1);
00283 tau_meas_data[axis].resize(num_samples);
00284 tau_model_data[axis].resize(num_samples-1);
00285 }
00286
00287 samplenumber = 0;
00288 isCalibrating = true;
00289 return true;
00290 }
00291 }
00292
00293 bool Kuka361nAxesAccelerationController::finishedCalibration() const
00294 {
00295 return !isCalibrating;
00296 }
00297
00298 void Kuka361nAxesAccelerationController::startMonitoring()
00299 {
00300 if (!isMonitoring){
00301 log(Warning)<<"(Kuka361nAxesAccelerationController) start Monitoring"<<endlog();
00302
00303 time_sleep = 0.1;
00304 time_begin = TimeService::Instance()->getTicks();
00305 initDataVecSize = (int)(20/Ts.rvalue());
00306
00307 time_data.resize(initDataVecSize,0);
00308 for(unsigned int axis=0;axis<num_axes;axis++){
00309 q_data[axis].resize(initDataVecSize);
00310 qdot_data[axis].resize(initDataVecSize);
00311 tau_meas_data[axis].resize(initDataVecSize);
00312 }
00313
00314 samplenumber = 0;
00315 isMonitoring = true;
00316 getPeer("Reporting")->start();
00317 }
00318 }
00319
00320 void Kuka361nAxesAccelerationController::stopMonitoring()
00321 {
00322 log(Warning)<<"(Kuka361nAxesAccelerationController) stop Monitoring"<<endlog();
00323
00324 isMonitoring = false;
00325 getPeer("Reporting")->stop();
00326
00327 unsigned int sample=0;
00328 while (time_data[sample] != 0 ){
00329 sample++;
00330 }
00331 dataVecSize = sample-50;
00332 num_samples = dataVecSize;
00333
00334 time_data.resize(dataVecSize);
00335 for(unsigned int axis=0;axis<num_axes;axis++){
00336 q_data[axis].resize(dataVecSize);
00337 qdot_data[axis].resize(dataVecSize);
00338 tau_meas_data[axis].resize(dataVecSize);
00339 qddot_data[axis].resize(dataVecSize-1);
00340 tau_model_data[axis].resize(dataVecSize-1);
00341 }
00342 }
00343
00344
00345 void Kuka361nAxesAccelerationController::Calculate(){
00346
00347 log(Warning)<<"calculation Started"<<endlog();
00348
00349
00350 for(unsigned int axis=0;axis<num_axes;axis++){
00351 for(unsigned int sample=0;sample<num_samples-1;sample++){
00352 qddot_data[axis][samplenumber] = (qdot_data[axis][sample+1] - qdot_data[axis][sample])/(time_data[sample+1]-time_data[sample]);
00353 }
00354 }
00355
00356
00357 for(unsigned int axis=0;axis<num_axes;axis++){
00358 qdot_data[axis] = Filter(qdot_data[axis]);
00359 qddot_data[axis] = Filter(qddot_data[axis]);
00360 tau_meas_data[axis] = Filter(tau_meas_data[axis]);
00361 }
00362
00363
00364 vector<double> q_sample(6);
00365 vector<double> qdot_sample(6);
00366 vector<double> qddot_sample(6);
00367 vector<double> tau_model_sample(6);
00368 vector<double> q_zero(6,0);
00369 vector<double> q_ones(6,1);
00370
00371 for(unsigned int sample=0;sample<num_samples-1;sample++){
00372 for(unsigned int axis=0;axis<num_axes;axis++){
00373 q_sample[axis] = q_data[axis][sample];
00374 qdot_sample[axis] = qdot_data[axis][sample];
00375 qddot_sample[axis] = qddot_data[axis][sample];
00376 }
00377 tau_model_sample = kuka361INVDYN->invdyn361(q_sample,qdot_sample,qdot_sample,qddot_sample,q_ones,q_zero);
00378 for(unsigned int axis=0;axis<num_axes;axis++){
00379 tau_model_data[axis][sample] = tau_model_sample[axis];
00380 }
00381 }
00382
00383 log(Debug)<<"tau_meas_data 1: "<<tau_meas_data[0][1000]<<" "<<tau_meas_data[0][5000]<<" "<<tau_meas_data[0][8000]<<endlog();
00384 log(Debug)<<"tau_model_data 1: "<<tau_model_data[0][1000]<<" "<<tau_model_data[0][5000]<<" "<<tau_model_data[0][8000]<<endlog();
00385 log(Debug)<<"tau_meas_data 3: "<<tau_meas_data[2][1000]<<" "<<tau_meas_data[2][5000]<<" "<<tau_meas_data[2][8000]<<endlog();
00386 log(Debug)<<"tau_model_data 3: "<<tau_model_data[2][1000]<<" "<<tau_model_data[2][5000]<<" "<<tau_model_data[2][8000]<<endlog();
00387 log(Debug)<<"tau_meas_data 4: "<<tau_meas_data[3][1000]<<" "<<tau_meas_data[3][5000]<<" "<<tau_meas_data[3][8000]<<endlog();
00388 log(Debug)<<"tau_model_data 4: "<<tau_model_data[3][1000]<<" "<<tau_model_data[3][5000]<<" "<<tau_model_data[3][8000]<<endlog();
00389
00390 vector<double> offsets(6,0);
00391 for (unsigned int axis=0; axis<num_axes; axis++){
00392 for (unsigned int sample=0; sample<num_samples-1; sample++){
00393 offsets[axis] += (tau_meas_data[axis][sample] - tau_model_data[axis][sample])/(num_samples-1);
00394 }
00395 }
00396 vector<double> scales(6,0);
00397 for (unsigned int axis=3; axis<num_axes; axis++){
00398 for (unsigned int sample=0; sample<num_samples-1; sample++){
00399 scales[axis] += (tau_meas_data[axis][sample] / tau_model_data[axis][sample])/(num_samples-1);
00400 }
00401 }
00402 scales[0]=scales[1]=scales[2]=1;
00403
00404 torque_offset.value() = offsets;
00405 torque_scale.value() = scales;
00406
00407 log(Warning)<<"calculation Finished"<<endlog();
00408 }
00409
00410 vector<double> Kuka361nAxesAccelerationController::Filter(vector<double>& x){
00411 vector<double> a(6);
00412 a[0] = 1.;
00413 a[1] = -4.1873000478644;
00414 a[2] = 7.069722752792469;
00415 a[3] = -6.009958148187328;
00416 a[4] = 2.5704293025241;
00417 a[5] = -0.44220918239962;
00418
00419 vector<double> b(6);
00420 b[0] = 0.000021396152038;
00421 b[1] = 0.000106980760191;
00422 b[2] = 0.000213961520382;
00423 b[3] = 0.000213961520382;
00424 b[4] = 0.000106980760191;
00425 b[5] = 0.000021396152038;
00426
00427 vector<double> y(x.size());
00428 y[0] = b[0]*x[0];
00429 y[1] = b[0]*x[1] + b[1]*x[0] - a[1]*y[0];
00430 y[2] = b[0]*x[2] + b[1]*x[1] + b[2]*x[0] - a[1]*y[1] - a[2]*y[0];
00431 y[3] = b[0]*x[3] + b[1]*x[2] + b[2]*x[1] + b[3]*x[0] - a[1]*y[2] - a[2]*y[1] - a[3]*y[0];
00432 y[4] = b[0]*x[4] + b[1]*x[3] + b[2]*x[2] + b[3]*x[1] + b[4]*x[0] - a[1]*y[3] - a[2]*y[2] - a[3]*y[1] - a[4]*y[0];
00433
00434 for (unsigned int i=5; i<x.size(); i++){
00435 y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] + b[3]*x[i-3] + b[4]*x[i-4] + b[5]*x[i-5] - a[1]*y[i-1] - a[2]*y[i-2] - a[3]*y[i-3] - a[4]*y[i-4] - a[5]*y[i-5];
00436 }
00437
00438 return y;
00439 }
00440
00441 }
00442
00443
00444
00445