|
Fast Research Interface Library
Manual and Documentation
|
00001 // ---------------------- Doxygen info ---------------------- 00051 // ---------------------------------------------------------- 00052 // For a convenient reading of this file's source code, 00053 // please use a tab width of four characters. 00054 // ---------------------------------------------------------- 00055 00056 00057 #include <DataLogging.h> 00058 #include <FastResearchInterface.h> 00059 #include <OSAbstraction.h> 00060 #include <stdio.h> 00061 #include <stdlib.h> 00062 #include <time.h> 00063 #include <errno.h> 00064 #include <string.h> 00065 00066 00067 00068 #define NUMBER_OF_ELEMENTS_PER_ENTRY 58 00069 #define OUTPUT_FILE_STRING_LENGTH 1024 00070 #define TIME_STRING_LENGTH 128 00071 00072 #ifndef PI 00073 #define PI 3.1415926535897932384626433832795 00074 #endif 00075 00076 #ifndef RAD 00077 #define RAD(A) ((A) * PI / 180.0 ) 00078 #endif 00079 00080 #ifndef DEG 00081 #define DEG(A) ((A) * 180.0 / PI ) 00082 #endif 00083 00084 00085 // **************************************************************** 00086 // Constructor 00087 // 00088 DataLogging::DataLogging( const char *RobotName 00089 , const char *LoggingPath 00090 , const char *LoggingFileName 00091 , const unsigned int &MaxNumberOfEntries) 00092 { 00093 unsigned int i = 0; 00094 00095 this->MachineName = (char*)RobotName; 00096 this->OutputPath = (char*)LoggingPath; 00097 this->OutputFileName = (char*)LoggingFileName; 00098 this->MaximumNumberOfEntries = MaxNumberOfEntries; 00099 this->CurrentObjectState = DataLogging::WriteToFileCalled; 00100 this->OutputFileHandler = NULL; 00101 this->OutputCounter = 0; 00102 this->CurrentControlScheme = 0; 00103 00104 this->LoggingMemory = new float*[NUMBER_OF_ELEMENTS_PER_ENTRY]; 00105 00106 for (i = 0; i < NUMBER_OF_ELEMENTS_PER_ENTRY; i++) 00107 { 00108 this->LoggingMemory[i] = new float[MaxNumberOfEntries]; 00109 00110 memset( this->LoggingMemory[i] 00111 , 0x0 00112 , this->MaximumNumberOfEntries * sizeof(float) ); 00113 } 00114 00115 this->CompleteOutputFileString = new char[OUTPUT_FILE_STRING_LENGTH]; 00116 00117 memset( this->CompleteOutputFileString 00118 , 0x0 00119 , OUTPUT_FILE_STRING_LENGTH * sizeof(char)); 00120 00121 } 00122 00123 00124 // **************************************************************** 00125 // Destructor 00126 // 00127 DataLogging::~DataLogging(void) 00128 { 00129 unsigned int i = 0; 00130 00131 if (this->CurrentObjectState == DataLogging::PrepareLoggingCalled) 00132 { 00133 this->WriteToFile(); 00134 } 00135 00136 for (i = 0; i < NUMBER_OF_ELEMENTS_PER_ENTRY; i++) 00137 { 00138 delete[] LoggingMemory[i]; 00139 } 00140 00141 delete[] LoggingMemory; 00142 delete[] this->CompleteOutputFileString; 00143 } 00144 00145 00146 // **************************************************************** 00147 // PrepareLogging() 00148 // 00149 int DataLogging::PrepareLogging( const unsigned int &ControlScheme 00150 , const char *FileIdentifier) 00151 { 00152 char TimeString[TIME_STRING_LENGTH]; 00153 00154 unsigned int i = 0; 00155 00156 time_t CurrentDayTime; 00157 00158 memset( TimeString 00159 , 0x0 00160 , TIME_STRING_LENGTH * sizeof(char)); 00161 00162 this->CurrentControlScheme = ControlScheme; 00163 00164 if (this->CurrentObjectState == DataLogging::PrepareLoggingCalled) 00165 { 00166 this->WriteToFile(); 00167 } 00168 00169 GetSystemTimeInSeconds(true); 00170 00171 00172 00173 //REMOVE 00174 00175 //------------------------ 00176 00177 #ifdef _NTO_ 00178 00179 struct _clockperiod ClockResolution; 00180 00181 ClockResolution.nsec = 10000; //ns 00182 ClockResolution.fract = 0; 00183 00184 ClockPeriod(CLOCK_REALTIME, &ClockResolution, NULL, 0); 00185 //------------------------ 00186 00187 #endif 00188 00189 memset( this->CompleteOutputFileString 00190 , 0x0 00191 , OUTPUT_FILE_STRING_LENGTH * sizeof(char)); 00192 00193 for (i = 0; i < NUMBER_OF_ELEMENTS_PER_ENTRY; i++) 00194 { 00195 memset( this->LoggingMemory[i] 00196 , 0x0 00197 , this->MaximumNumberOfEntries * sizeof(float) ); 00198 } 00199 00200 CurrentDayTime = time(NULL); 00201 strftime(TimeString, TIME_STRING_LENGTH, "%y%m%d-%H%M%S", localtime(&CurrentDayTime)); 00202 if (FileIdentifier == NULL) 00203 { 00204 sprintf(this->CompleteOutputFileString, "%s%s-%s-%s", this->OutputPath, TimeString, this->MachineName, this->OutputFileName); 00205 } 00206 else 00207 { 00208 sprintf(this->CompleteOutputFileString, "%s%s-%s-%s-%s", this->OutputPath, TimeString, FileIdentifier, this->MachineName, this->OutputFileName); 00209 } 00210 00211 if ( (this->OutputFileHandler = fopen(this->CompleteOutputFileString, "w") ) == NULL) 00212 { 00213 return(EBADF); 00214 } 00215 else 00216 { 00217 fprintf(this->OutputFileHandler, "Logging file of the KUKA Fast Research Interface: %s\n", this->CompleteOutputFileString); 00218 fprintf(this->OutputFileHandler, "This file contains all important control values and importable to Matlab and MS Excel.\n"); 00219 fprintf(this->OutputFileHandler, "%s\n", ctime( &CurrentDayTime)); 00220 fprintf(this->OutputFileHandler, "Robot name: %s\n", this->MachineName); 00221 00222 switch (this->CurrentControlScheme) 00223 { 00224 case FastResearchInterface::JOINT_POSITION_CONTROL: 00225 fprintf(this->OutputFileHandler, "Active control scheme: joint position control\n\n"); 00226 fprintf(this->OutputFileHandler, "Counter KRCTime LocalTime ActFJ1 ActFJ2 ActFJ3 ActFJ4 ActFJ5 ActFJ6 ActFJ7 UDesJ1 UDesJ2 UDesJ3 UDesJ4 UDesJ5 UDesJ6 UDesJ7 ActJ1 ActJ2 ActJ3 ActJ4 ActJ5 ActJ6 ActJ7 KDesJ1 KDesJ2 KDesJ3 KDesJ4 KDesJ5 KDesJ6 KDesJ7\n"); 00227 break; 00228 case FastResearchInterface::CART_IMPEDANCE_CONTROL: 00229 fprintf(this->OutputFileHandler, "Active control scheme: Cartesian impedance control\n\n"); 00230 fprintf(this->OutputFileHandler, "Counter KRCTime LocalTime DesKx DesKy DesKz DesKa DesKb DesKc DesDx DesDy DesDz DesDa DesDb DesDc UDesFx UDesFy UDesFz UDesFa UDesFb UDesFc\n"); 00231 break; 00232 case FastResearchInterface::JOINT_IMPEDANCE_CONTROL: 00233 fprintf(this->OutputFileHandler, "Active control scheme: joint impedance control\n\n"); 00234 fprintf(this->OutputFileHandler, "Counter KRCTime LocalTime ActFJ1 ActFJ2 ActFJ3 ActFJ4 ActFJ5 ActFJ6 ActFJ7 UDesPJ1 UDesPJ2 UDesPJ3 UDesPJ4 UDesPJ5 UDesPJ6 UDesPJ7 ActPJ1 ActPJ2 ActPJ3 ActPJ4 ActPJ5 ActPJ6 ActPJ7 KDesPJ1 KDesPJ2 KDesPJ3 KDesPJ4 KDesPJ5 KDesPJ6 KDesPJ7 DesKJ1 DesKJ2 DesKJ3 DesKJ4 DesKJ5 DesKJ6 DesKJ7 DesDJ1 DesDJ2 DesDJ3 DesDJ4 DesDJ5 DesDJ6 DesDJ7 UDesFJ1 UDesFJ2 UDesFJ3 UDesFJ4 UDesFJ5 UDesFJ6 UDesFJ7 KOffPJ1 KOffPJ2 KOffPJ3 KOffPJ4 KOffPJ5 KOffPJ6 KOffPJ7\n"); 00235 break; 00236 default: 00237 return(EINVAL); 00238 } 00239 } 00240 00241 fflush(this->OutputFileHandler); 00242 00243 this->CurrentObjectState = DataLogging::PrepareLoggingCalled; 00244 this->OutputCounter = 0; 00245 00246 return(EOK); 00247 } 00248 00249 00250 // **************************************************************** 00251 // AddEntry() 00252 // 00253 void DataLogging::AddEntry( const tFriMsrData &ReceivedFRIData 00254 , const tFriCmdData &SentFRIData ) 00255 { 00256 unsigned int i = 0; 00257 00258 this->LoggingMemory[ 0][this->OutputCounter % this->MaximumNumberOfEntries] = ReceivedFRIData.intf.timestamp; 00259 this->LoggingMemory[ 1][this->OutputCounter % this->MaximumNumberOfEntries] = GetSystemTimeInSeconds(); 00260 00261 if (this->CurrentControlScheme == FastResearchInterface::JOINT_POSITION_CONTROL) 00262 { 00263 for (i = 0; i < LBR_MNJ; i++) 00264 { 00265 this->LoggingMemory[ 2 + i][this->OutputCounter % this->MaximumNumberOfEntries] = ReceivedFRIData.data.msrJntTrq [i] ; 00266 this->LoggingMemory[ 2 + 1 * LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = DEG( SentFRIData.cmd.jntPos [i]); 00267 this->LoggingMemory[ 2 + 2 * LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = DEG( ReceivedFRIData.data.msrJntPos [i]); 00268 this->LoggingMemory[ 2 + 3 * LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = DEG( ReceivedFRIData.data.cmdJntPos [i]); 00269 } 00270 } 00271 00272 if (this->CurrentControlScheme == FastResearchInterface::CART_IMPEDANCE_CONTROL) 00273 { 00274 for (i = 0; i < FRI_CART_VEC; i++) 00275 { 00277 this->LoggingMemory[ 2 + i][this->OutputCounter % this->MaximumNumberOfEntries] = SentFRIData.cmd.cartStiffness [i]; 00278 this->LoggingMemory[ 2 + 1 * FRI_CART_VEC + i][this->OutputCounter % this->MaximumNumberOfEntries] = SentFRIData.cmd.cartDamping [i]; 00279 this->LoggingMemory[ 2 + 2 * FRI_CART_VEC + i][this->OutputCounter % this->MaximumNumberOfEntries] = SentFRIData.cmd.addTcpFT [i]; 00280 } 00281 } 00282 00283 if (this->CurrentControlScheme == FastResearchInterface::JOINT_IMPEDANCE_CONTROL) 00284 { 00285 for (i = 0; i < LBR_MNJ; i++) 00286 { 00287 this->LoggingMemory[ 2 + i][this->OutputCounter % this->MaximumNumberOfEntries] = ReceivedFRIData.data.msrJntTrq [i] ; 00288 this->LoggingMemory[ 2 + LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = DEG( SentFRIData.cmd.jntPos [i]); 00289 this->LoggingMemory[ 2 + 2 * LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = DEG( ReceivedFRIData.data.msrJntPos [i]); 00290 this->LoggingMemory[ 2 + 3 * LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = DEG( ReceivedFRIData.data.cmdJntPos [i]); 00291 this->LoggingMemory[ 2 + 4 * LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = SentFRIData.cmd.jntStiffness [i] ; 00292 this->LoggingMemory[ 2 + 5 * LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = SentFRIData.cmd.jntDamping [i] ; 00293 this->LoggingMemory[ 2 + 6 * LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = SentFRIData.cmd.addJntTrq [i] ; 00294 this->LoggingMemory[ 2 + 7 * LBR_MNJ + i][this->OutputCounter % this->MaximumNumberOfEntries] = DEG( ReceivedFRIData.data.cmdJntPosFriOffset [i]); 00295 } 00296 } 00297 00298 this->OutputCounter++; 00299 00300 return; 00301 } 00302 00303 00304 // **************************************************************** 00305 // WriteToFile() 00306 // 00307 int DataLogging::WriteToFile(void) 00308 { 00309 int ReturnValue = 0; 00310 00311 unsigned int StartIndex = 0 00312 , StopIndex = 0 00313 , Counter = 0 00314 , i = 0 00315 , ElementsPerLine = 0; 00316 00317 if (this->CurrentObjectState != DataLogging::PrepareLoggingCalled) 00318 { 00319 return(EPERM); 00320 } 00321 else 00322 { 00323 this->CurrentObjectState = DataLogging::WriteToFileCalled; 00324 } 00325 00326 //REMOVE 00327 //------------------------ 00328 #ifdef _NTO_ 00329 struct _clockperiod ClockResolution; 00330 00331 ClockResolution.nsec = 1000000; //ns 00332 ClockResolution.fract = 0; 00333 00334 ClockPeriod(CLOCK_REALTIME, &ClockResolution, NULL, 0); 00335 #endif 00336 //------------------------ 00337 00338 if (this->OutputCounter > this->MaximumNumberOfEntries) 00339 { 00340 StartIndex = (this->OutputCounter + 1) % this->MaximumNumberOfEntries; 00341 StopIndex = StartIndex + this->MaximumNumberOfEntries - 1; 00342 } 00343 else 00344 { 00345 StartIndex = 0; 00346 StopIndex = this->OutputCounter - 1; 00347 } 00348 00349 switch (this->CurrentControlScheme) 00350 { 00351 case FastResearchInterface::JOINT_POSITION_CONTROL: 00352 ElementsPerLine = 2 + 4 * LBR_MNJ; 00353 break; 00354 case FastResearchInterface::CART_IMPEDANCE_CONTROL: 00355 ElementsPerLine = 2 + 3 * FRI_CART_VEC; 00356 break; 00357 case FastResearchInterface::JOINT_IMPEDANCE_CONTROL: 00358 ElementsPerLine = 2 + 8 * LBR_MNJ; 00359 break; 00360 default: 00361 return(EINVAL); 00362 } 00363 00364 while (StopIndex >= StartIndex) 00365 { 00366 Counter++; 00367 fprintf(this->OutputFileHandler, "%d", Counter); 00368 for (i = 0; i < ElementsPerLine; i++) 00369 { 00370 fprintf(this->OutputFileHandler, " %12.6f", this->LoggingMemory[i][StartIndex]); 00371 } 00372 fprintf(this->OutputFileHandler, "\n"); 00373 StartIndex++; 00374 } 00375 00376 fflush(this->OutputFileHandler); 00377 ReturnValue = fclose(this->OutputFileHandler); 00378 00379 if (ReturnValue == 0) 00380 { 00381 return(EOK); 00382 } 00383 else 00384 { 00385 return(ReturnValue); 00386 } 00387 } 00388