00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "PhysicalMomentumWheel.h"
00014
00015
00016
00017
00018
00019 PhysicalMomentumWheel::PhysicalMomentumWheel( )
00020 {
00021 pthread_mutex_init( &m_Mutex, NULL );
00022
00023
00024 m_fd = -1;
00025 m_BiasFlag = 0;
00026 m_CurrentWheelSpeed = 0.0;
00027
00028 m_MinVolts = 15;
00029 m_MaxAmps = 24;
00030
00031
00032
00033
00034 LAST_VEL = 0.0;
00035 LAST_TOR = 0.0;
00036 LAST_ERR = 0.0;
00037 LAST_VOLT = 25.0;
00038
00039
00040 m_TorqueControlFlag = 1;
00041 m_TorqueControllerDeltaTime = 0.4;
00042 m_TorqueControllerTorqueGain = 1;
00043 m_TorqueControllerNegativeTimeGain = 0.5;
00044 m_TorqueControllerSteadyStateGain = 1.0;
00045 m_TorqueControllerDesiredWheelSpeedFlag = 0;
00046
00047 m_exitConditionTorque = 1;
00048
00049
00050 m_MaxWheelTorque = 1023;
00051
00052 m_MinWheelTorque = -m_MaxWheelTorque;
00053 m_MaxTorqueStep = 700;
00054
00055
00056 m_Coefficients1.initialize(4);
00057 m_Coefficients2.initialize(3);
00058 m_Coefficients3.initialize(3);
00059 m_Coefficients4.initialize(4);
00060
00061 m_exitConditionSpeed = 1;
00062
00063 }
00064
00065 PhysicalMomentumWheel::~PhysicalMomentumWheel( )
00066 {
00067
00068 Deinitialize();
00069
00070 }
00071
00072
00073
00074
00075
00076
00077 int PhysicalMomentumWheel::Initialize( )
00078 {
00079
00080
00081 char *stringPort;
00082 stringPort = (char *)malloc(80);
00083
00084 if ( m_fd < 0 )
00085 {
00086 sprintf(stringPort,"%s",m_DaisyChainPort.c_str());
00087
00088 init_serial( stringPort, B9600, &m_fd );
00089
00090 Reset( );
00091
00092 ChangeBaud( );
00093
00094 close( m_fd );
00095
00096 init_serial( stringPort, B19200, &m_fd );
00097
00098 EchoOff( );
00099
00100 EnableTorqueMode( );
00101 }
00102
00103
00104
00105 if( m_BiasFlag )
00106 {
00107 m_DesiredWheelSpeed = m_BiasSpeed ;
00108 CommandWheelSpeed( );
00109 }
00110
00111
00112 cerr << "Start Speed Query for Wheel" << endl;
00113 StartSpeedQuery( );
00114 usleep( 500000 );
00115
00116 cerr << "Wheel Initialized: " << m_WheelName << endl;
00117
00118 return( 0 );
00119 }
00120
00121
00122 int PhysicalMomentumWheel::Deinitialize( )
00123 {
00124 cerr << "\n\nDEINITIALIZING WHEEL: " << m_WheelName << endl;
00125
00126
00127 if ( !m_TorqueControlFlag )
00128 {
00129 cerr << "Stop Torque Controller" << endl;
00130 StopTorqueController( );
00131 }
00132
00133 cerr << "Stop Wheel " << endl;
00134 Stop( );
00135
00136 cerr << "Stop Speed Query" << endl;
00137 StopSpeedQuery( );
00138
00139 cerr << "Deallocating memory from mutex" << endl;
00140 pthread_mutex_destroy( &m_Mutex );
00141
00142 cerr << "Serial Port Closing:\n";
00143 close( m_fd );
00144 return( 0 );
00145 }
00146
00147
00148 int PhysicalMomentumWheel::Reset( )
00149 {
00150 char *command;
00151 command = new char[80];
00152 sprintf( command, "Z\n\n" );
00153 pthread_mutex_lock(&m_Mutex);
00154 say( m_fd, command );
00155 cerr << "\nRESET MOMENTUM WHEEL SETTINGS for wheel: " << m_WheelName << endl;
00156 pthread_mutex_unlock(&m_Mutex);
00157
00158 usleep(1500000);
00159 delete command;
00160 return( 0 );
00161 }
00162
00163 int PhysicalMomentumWheel::ChangeBaud( )
00164 {
00165 char *posString = new char[80];
00166 char *command;
00167 command = new char[80];
00168 sprintf( command, "BAUD19200\n\n" );
00169 pthread_mutex_lock(&m_Mutex);
00170 say( m_fd, command );
00171 cerr << "RESET BAUD to 19200: " << m_WheelName << endl;
00172 hear( m_fd, posString, 15, 0, 50000, '\r' );
00173 pthread_mutex_unlock(&m_Mutex);
00174
00175 usleep(1500000);
00176 delete command;
00177 delete posString;
00178 return( 0 );
00179 }
00180
00181 int PhysicalMomentumWheel::EchoOn( )
00182 {
00183 char *command;
00184 command = new char[80];
00185 sprintf( command, "ECHO\n\n" );
00186 pthread_mutex_lock(&m_Mutex);
00187 say( m_fd, command );
00188 cerr << "SET ECHO ON for wheel: " << m_WheelName << endl;
00189 pthread_mutex_unlock(&m_Mutex);
00190
00191 usleep(1500000);
00192 delete command;
00193 return( 0 );
00194 }
00195
00196 int PhysicalMomentumWheel::EchoOff( )
00197 {
00198 char *command;
00199 command = new char[80];
00200 sprintf( command, "ECHO_OFF\n\n" );
00201 pthread_mutex_lock(&m_Mutex);
00202 say( m_fd, command );
00203 cerr << "SET ECHO OFF for wheel: " << m_WheelName << endl;
00204 pthread_mutex_unlock(&m_Mutex);
00205
00206 usleep(1500000);
00207 delete command;
00208 return( 0 );
00209 }
00210
00211 int PhysicalMomentumWheel::EnableTorqueMode( )
00212 {
00213 char *command;
00214 command = new char[80];
00215 sprintf( command, "MT\n\n" );
00216 pthread_mutex_lock(&m_Mutex);
00217 say( m_fd, command );
00218 cerr << "ENABLE TORQUE MODE for wheel: " << m_WheelName << endl;
00219 pthread_mutex_unlock(&m_Mutex);
00220
00221 usleep(1500000);
00222 delete command;
00223 return( 0 );
00224 }
00225
00226 int PhysicalMomentumWheel::TorqueCommand( double _power )
00227 {
00228 static char *torqueCommand = new char[80];
00229 sprintf( torqueCommand, "T%f\n\n", _power );
00230 pthread_mutex_lock(&m_Mutex);
00231 say(m_fd, torqueCommand);
00232 pthread_mutex_unlock(&m_Mutex);
00233 return( 0 );
00234 }
00235
00236
00237 int PhysicalMomentumWheel::Stop( )
00238 {
00239 pthread_mutex_unlock(&m_Mutex);
00240 Reset( );
00241 return( 0 );
00242 }
00243
00244 void PhysicalMomentumWheel::StartSpeedQuery( )
00245 {
00246 pthread_create( &m_SpeedThreadID, NULL, QueryWheelSpeed, (void*) this );
00247 }
00248
00249 void* QueryWheelSpeed( void* arg )
00250 {
00251 PhysicalMomentumWheel *wheel = (PhysicalMomentumWheel*) arg;
00252 double pos1 = 0.0;
00253 double pos2 = 0.0;
00254 double timeStamp1 = 0.0;
00255 double timeStamp2 = 0.0;
00256 char *posString = new char[80];
00257 char *posString2 = new char[80];
00258 double velocity = 0.0 ;
00259 int readdelay = 100000;
00260 char *RPCommand = new char[80];
00261
00262
00263
00264
00265
00266
00267
00268 sprintf(RPCommand, "RP\n");
00269
00270
00271 pthread_mutex_lock(&wheel->m_Mutex);
00272
00273
00274
00275 double timeA = Now( );
00276 hear( wheel->m_fd, posString, 15, 0, 50000, '\r' );
00277 double timeB = Now( );
00278 timeStamp1 = (timeB + timeA)/2;
00279
00280
00281
00282
00283 pthread_mutex_unlock(&wheel->m_Mutex);
00284 pos1 = atoi(posString);
00285
00286 int exit = 1;
00287
00288 while( exit )
00289 {
00290 pthread_testcancel();
00291
00292
00293
00294
00295 sprintf(RPCommand, "RP\n");
00296
00297 usleep(readdelay);
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 pthread_mutex_lock(&wheel->m_Mutex);
00323
00324 say(wheel->m_fd, RPCommand);
00325
00326 double timeC = Now( );
00327 hear(wheel->m_fd, posString2, 15, 0, 50000, '\r');
00328 double timeD = Now( );
00329 timeStamp2 = (timeD + timeC )/2;
00330
00331
00332 pthread_mutex_unlock(&wheel->m_Mutex);
00333
00334 pos2 = atoi(posString2);
00335
00336
00337 velocity = -( (pos2 - pos1) /( timeStamp2 - timeStamp1 ))*2*3.14159/4000.0;
00338
00339
00340
00341
00342 pthread_mutex_lock(&wheel->m_Mutex);
00343 wheel->m_CurrentWheelSpeed = velocity;
00344 wheel->m_VelocityTime = timeStamp2;
00345 pthread_mutex_unlock(&wheel->m_Mutex);
00346
00347
00348 pos1 = pos2;
00349 timeStamp1 = timeStamp2;
00350
00351 pthread_testcancel( );
00352
00353
00354 pthread_mutex_lock(&wheel->m_Mutex);
00355 exit = wheel->m_exitConditionSpeed;
00356
00357 pthread_mutex_unlock(&wheel->m_Mutex);
00358
00359 }
00360
00361 return arg;
00362 }
00363
00364 void PhysicalMomentumWheel::StopSpeedQuery( )
00365 {
00366 pthread_mutex_lock( &m_Mutex );
00367 m_exitConditionSpeed = 0;
00368 pthread_mutex_unlock( &m_Mutex );
00369
00370 pthread_join( m_SpeedThreadID, NULL );
00371 }
00372
00373
00374 void PhysicalMomentumWheel::CommandWheelTorque( double _wheelTorque )
00375 {
00376 if( m_TorqueControlFlag )
00377 {
00378 StartTorqueController( );
00379 m_TorqueControlFlag = 0;
00380 }
00381
00382 pthread_mutex_lock(&m_Mutex);
00383 m_DesiredWheelTorque = _wheelTorque;
00384
00385 pthread_mutex_unlock(&m_Mutex);
00386
00387 }
00388
00389 void PhysicalMomentumWheel::StartTorqueController()
00390 {
00391
00392 pthread_create(&m_TorqueThreadID, NULL, RunTorqueControllerRev, (void*) this);
00393 }
00394
00395
00396 void* RunTorqueControllerRev( void* arg )
00397 {
00398
00399 PhysicalMomentumWheel *reactionWheel = (PhysicalMomentumWheel*) arg;
00400
00401 int CommandWheelSpeedFlag = 0;
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 double Constant = 0;
00417 double ConstantPositive = 0.109;
00418
00419 double ConstantNegative = 0.109;
00420
00421 double time1=0;
00422 double time2=0;
00423 double desiredTorque=0.0;
00424
00425 double steadyStateWheelSpeed = 0.0;
00426
00427 double reduceWheelSpeedTimeGain = 0.0;
00428
00429 double reduceWheelSpeedGain = 0.25;
00430 double delayTime = 0.0;
00431 int condition = 0;
00432
00433 int exit = 1;
00434
00435
00436 while( exit )
00437 {
00438
00439 time1 = Now( );
00440
00441 reduceWheelSpeedTimeGain = 1;
00442
00443
00444 pthread_mutex_lock( &reactionWheel->m_Mutex );
00445
00446
00447 desiredTorque = reactionWheel->m_DesiredWheelTorque;
00448
00449 if ( reactionWheel->m_DesiredWheelTorque )
00450 {
00451 double finalWheelSpeed = reactionWheel->m_CurrentWheelSpeed
00452 + ( reactionWheel->m_TorqueControllerTorqueGain*(-reactionWheel->m_DesiredWheelTorque) )
00453 * reactionWheel->m_TorqueControllerDeltaTime/reactionWheel->m_AxialInertia;
00454
00455
00456 if ( finalWheelSpeed < reactionWheel->m_CurrentWheelSpeed && finalWheelSpeed >= 0 && reactionWheel->m_CurrentWheelSpeed >=0 )
00457 {
00458 condition = 1;
00459 }
00460 else if ( finalWheelSpeed > reactionWheel->m_CurrentWheelSpeed && finalWheelSpeed <= 0 && reactionWheel->m_CurrentWheelSpeed <= 0 )
00461 {
00462 condition = 1;
00463 }
00464 else
00465 {
00466 condition = 0;
00467 }
00468 if ( condition )
00469 {
00470
00471 Constant = ConstantNegative;
00472
00473
00474 steadyStateWheelSpeed = reduceWheelSpeedGain*reactionWheel->m_TorqueControllerSteadyStateGain
00475 * ( finalWheelSpeed - reactionWheel->m_CurrentWheelSpeed )/Constant;
00476 reduceWheelSpeedTimeGain = 0.2;
00477 }
00478 else
00479 {
00480 Constant = ConstantPositive;
00481 steadyStateWheelSpeed = reactionWheel->m_TorqueControllerSteadyStateGain
00482 * ( finalWheelSpeed + ( Constant - 1 )*reactionWheel->m_CurrentWheelSpeed )/Constant;
00483 }
00484
00485 reactionWheel->m_DesiredWheelSpeed = steadyStateWheelSpeed;
00486
00487
00488 reactionWheel->m_DesiredWheelTorque = 0;
00489 reactionWheel->m_TorqueControllerDesiredWheelSpeedFlag = 1;
00490 CommandWheelSpeedFlag = 1;
00491 }
00492 else
00493 {
00494 if( reactionWheel->m_TorqueControllerDesiredWheelSpeedFlag )
00495 {
00496 reactionWheel->m_DesiredWheelSpeed = reactionWheel->m_CurrentWheelSpeed;
00497 reactionWheel->m_TorqueControllerDesiredWheelSpeedFlag = 0;
00498 CommandWheelSpeedFlag = 1;
00499 }
00500 else
00501 {
00502 CommandWheelSpeedFlag = 0;
00503 }
00504 }
00505
00506 delayTime = reactionWheel->m_TorqueControllerDeltaTime*1000000*reduceWheelSpeedTimeGain;
00507
00508
00509 pthread_mutex_unlock( &reactionWheel->m_Mutex );
00510
00511
00512
00513 pthread_mutex_lock( &reactionWheel->m_Mutex );
00514 exit = reactionWheel->m_exitConditionTorque;
00515
00516 pthread_mutex_unlock( &reactionWheel->m_Mutex );
00517
00518 time2 = time1;
00519
00520
00521 if( CommandWheelSpeedFlag )
00522 {
00523
00524 reactionWheel->CommandWheelSpeed( );
00525 }
00526
00527
00528 usleep( int( delayTime ) );
00529 }
00530
00531 return arg;
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 void* RunTorqueController(void* arg)
00631 {
00632 PhysicalMomentumWheel *wheel = (PhysicalMomentumWheel*) arg;
00633
00634 double wheelAxialInertia;
00635 wheel->GetAxialInertia( wheelAxialInertia );
00636
00637 double w1;
00638
00639 double w2;
00640
00641 double wss;
00642
00643 double desiredTorque = 0;
00644
00645 double deltat = 0.5;
00646
00647 double C = 0.000001906374*pow(deltat,5) - 0.00012550397*pow(deltat,4) + 0.0032678612*pow(deltat,3)
00648 - 0.043053012550397*pow(deltat,4) + 0.0032678612*pow(deltat,3) - 0.0957*pow(deltat,2)
00649 + 0.3024019105*deltat + 0.00429944309;
00650
00651 int negflag = 1;
00652
00653 double k = 1;
00654
00655 double knt = 0.5;
00656
00657 double kpa = 1.12;
00658
00659 double kps = 7;
00660
00661 double minT = 0.03;
00662
00663 while( 1 )
00664 {
00665 pthread_testcancel();
00666
00667 pthread_mutex_lock( &wheel->m_Mutex );
00668
00669 desiredTorque = k * wheel->m_DesiredWheelTorque;
00670
00671
00672 w1 = - wheel->m_CurrentWheelSpeed;
00673
00674 cout << "w1: " << w1 << endl;
00675
00676 if( fabs( w1 ) > 200 )
00677 {
00678 w1 = wheel->LAST_VEL;
00679 }
00680
00681 cout << "w1 after check: " << w1 << endl;
00682
00683 pthread_mutex_unlock( &wheel->m_Mutex );
00684
00685
00686
00687
00688
00689 w2 = w1 + ( desiredTorque ) * deltat / ( wheelAxialInertia );
00690
00691 cout << "w2: " << w2 << endl;
00692
00693 wss = ( w2 + ( C - 1 ) * w1 ) / C;
00694
00695 cout << "wss: " << wss << endl;
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 if( fabs( desiredTorque ) < minT)
00731 {
00732 usleep((int) (deltat*1000000));
00733 }
00734 else if(negflag)
00735 {
00736 wheel->SetWheelSpeed( wss*kpa + kps*wss/fabs(wss) );
00737 wheel->CommandWheelSpeed( );
00738 usleep((int) (deltat*1000000));
00739 }
00740 else
00741 {
00742 usleep((int) (deltat*1000000 - deltat*1000000*fabs(desiredTorque)*knt));
00743 }
00744
00745
00746
00747
00748
00749 negflag = 1;
00750
00751 pthread_mutex_lock(&wheel->m_Mutex);
00752
00753
00754 wheel->LAST_VEL = w1;
00755
00756 pthread_mutex_unlock(&wheel->m_Mutex);
00757
00758 pthread_testcancel();
00759 }
00760 return NULL;
00761 }
00762
00763 void PhysicalMomentumWheel::StopTorqueController( )
00764 {
00765 pthread_mutex_lock( &m_Mutex );
00766 m_exitConditionTorque = 0;
00767 pthread_mutex_unlock( &m_Mutex );
00768
00769 pthread_join( m_TorqueThreadID, NULL );
00770 }
00771
00772 void PhysicalMomentumWheel::SetWheelSpeed( double desiredWheelSpeed )
00773 {
00774 pthread_mutex_lock( &m_Mutex );
00775 m_DesiredWheelSpeed = desiredWheelSpeed;
00776 pthread_mutex_unlock( &m_Mutex );
00777 }
00778
00779 void PhysicalMomentumWheel::CommandWheelSpeed( )
00780 {
00781
00782
00783 double volts;
00784 double amps;
00785
00786 volts = GetVolts( );
00787 amps = GetAmps( );
00788
00789 if( fabs(volts) < m_MinVolts )
00790 {
00791 cerr << "WARNING: " << m_WheelName << " Voltage is LOW! Voltage = " << volts << " .... Rechecking Voltage " << endl;
00792 volts = GetVolts( );
00793 if( fabs( volts ) < m_MinVolts )
00794 {
00795 cerr << "Warning 2nd Check: Voltage Too LOW! Voltage = "<< volts << " .... No Command Sent to Motor " << m_WheelName << endl;
00796 return;
00797 }
00798 }
00799 else if( fabs( amps ) > m_MaxAmps )
00800 {
00801 cerr << "WARNING: " << m_WheelName << " Current is High! Amps = " << amps << " .... Rechecking Current " << endl;
00802 amps = GetAmps( );
00803 if( fabs(amps) > m_MaxAmps )
00804 {
00805 cerr << "Warning 2nd Check: Current Too HIGH! Amps = "<< amps << " .... No Command Sent to Motor " << m_WheelName << endl;
00806 return;
00807 }
00808 }
00809 else
00810 { }
00811
00812
00813 double powerCommanded = 0;
00814 double scaledWheelRate = m_DesiredWheelSpeed / volts;
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 if ( scaledWheelRate >= -7.6 && scaledWheelRate < -1.2 )
00842 {
00843 powerCommanded = (m_Coefficients1)(1)*pow( scaledWheelRate, 3 ) + (m_Coefficients1)(2)*pow( scaledWheelRate, 2 ) + (m_Coefficients1)(3)*scaledWheelRate + (m_Coefficients1)(4);
00844 }
00845 else if ( scaledWheelRate >= -1.2 && scaledWheelRate < 0 )
00846 {
00847 powerCommanded = (m_Coefficients2)(1)*pow( scaledWheelRate, 2 ) + (m_Coefficients2)(2)*scaledWheelRate + (m_Coefficients2)(3);
00848 }
00849 else if ( scaledWheelRate >= 0 && scaledWheelRate<= 1.2 )
00850 {
00851 powerCommanded = (m_Coefficients3)(1)*pow( scaledWheelRate, 2 ) + (m_Coefficients3)(2)*scaledWheelRate + (m_Coefficients3)(3);
00852 }
00853 else if ( scaledWheelRate > 1.2 && scaledWheelRate <= 7.6 )
00854 {
00855 powerCommanded = (m_Coefficients4)(1)*pow( scaledWheelRate, 3 ) + (m_Coefficients4)(2)*pow( scaledWheelRate, 2 ) + (m_Coefficients4)(3)*scaledWheelRate + (m_Coefficients4)(4);
00856 }
00857 else
00858 {
00859
00860 cerr << "\nWARNING: OUTSIDE POWER COMMANDED to MOTOR BOUNDS. No Power setting sent to Wheel Motor. Wheel: " << m_WheelName
00861 << " Scaled Wheel Rate = " << scaledWheelRate << endl << endl;
00862 return;
00863 }
00864
00865 TorqueCommand( powerCommanded );
00866 LAST_VOLT = volts;
00867
00868 return;
00869 }
00870
00871 void PhysicalMomentumWheel::StartPID( )
00872 {
00873 pthread_create( &m_PIDThreadID, NULL, RunPIDController, (void*) this);
00874 }
00875
00876 void* RunPIDController(void* arg)
00877 {
00878 PhysicalMomentumWheel *wheel = (PhysicalMomentumWheel*) arg;
00879 double J = 0.04;
00880 double c = 555.56;
00881 double pi = 3.1415926535897;
00882 double timestep = 1000.0;
00883 double velocity;
00884 double desiredV;
00885 double error;
00886 double Kp;
00887 double Ki;
00888 double Kd;
00889 double torque;
00890 double TorqueChange;
00891
00892 usleep(15000);
00893 while (1)
00894 {
00895 pthread_testcancel();
00896
00897 cout << "PID THREAD RUNNING" << endl;
00898
00899 pthread_mutex_lock(&wheel->m_Mutex);
00900 velocity = wheel->m_CurrentWheelSpeed/2.0/pi;
00901 desiredV = wheel->m_DesiredWheelSpeed/2.0/pi;
00902 pthread_mutex_unlock(&wheel->m_Mutex);
00903
00904 error = desiredV - velocity;
00905
00906 cout << "current speed = " << velocity << endl;
00907 cout << "desired speed = " << desiredV << endl;
00908 cout << "error = " << error << endl;
00909
00910
00911 Kp = 9.65*J/c;
00912
00913 Ki = 0.0000055;
00914 if (fabs(error) >= 25 | fabs(desiredV) >= 25)
00915 {
00916 Ki = 0.0000013;
00917 }
00918
00919 Kd = 0.96*(fabs(error)*0.009029 + 1.92)*J/c;
00920 if (fabs(error) >= 25 | fabs(desiredV) >= 25)
00921 {
00922 Kd = 2.14*J/c;
00923 }
00924
00925
00926 TorqueChange = c*(Kp*error + Kd*(error - wheel->LAST_ERR)/timestep + Ki*error*timestep);
00927
00928 cout << "Torque Change = " << TorqueChange << endl;
00929
00930 torque = wheel->LAST_TOR + TorqueChange;
00931
00932 cout << "torqueA: " << torque << endl;
00933
00934
00935 if (abs((int) wheel->LAST_TOR - torque) > wheel->m_MaxTorqueStep && torque != 0)
00936 {
00937 if ((int) wheel->LAST_TOR >= 0 && (int) wheel->LAST_TOR < torque){
00938 torque = (int) wheel->LAST_TOR + 300;}
00939 else if ((int) wheel->LAST_TOR >= 0 && (int) wheel->LAST_TOR > torque){
00940 torque = (int) wheel->LAST_TOR - 300;}
00941 else if ((int) wheel->LAST_TOR < 0 && (int) wheel->LAST_TOR < torque){
00942 torque = (int) wheel->LAST_TOR + 300;}
00943 else if ((int) wheel->LAST_TOR < 0 && (int) wheel->LAST_TOR > torque){
00944 torque = (int) wheel->LAST_TOR - 300;}
00945 }
00946
00947 cout << "torque1: " << torque << endl;
00948
00949 cout << "max: " << wheel->m_MaxWheelTorque << endl;
00950
00951
00952 if (torque >= 0 && torque < 25.5 )
00953 {
00954 torque = torque + 25.5;
00955 }
00956 else if (torque < 0 && torque > -25.5 )
00957 {
00958 torque = torque - 25.5;
00959 }
00960 else
00961 { }
00962
00963
00964
00965 if (abs(torque) > 800 )
00966 {
00967 torque = (int) wheel->LAST_TOR;
00968 }
00969
00970 cout << "torque: " << torque << endl;
00971
00972 wheel->TorqueCommand( -int(torque) );
00973
00974
00975
00976
00977
00978 pthread_testcancel();
00979
00980 usleep(850000);
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 wheel->LAST_VEL = velocity;
01001 wheel->LAST_ERR = error;
01002 wheel->LAST_TOR = torque;
01003 pthread_testcancel();
01004 }
01005 return arg;
01006 }
01007
01008 void PhysicalMomentumWheel::StopPID()
01009 {
01010 pthread_cancel(m_PIDThreadID);
01011 pthread_mutex_unlock(&m_Mutex);
01012 }
01013
01014 void PhysicalMomentumWheel::CommandSystemTorque( double wheelTorque )
01015 {
01016
01017 pthread_mutex_lock(&m_Mutex);
01018
01019 wheelTorque = -wheelTorque/0.0018;
01020 wheelTorque = round(wheelTorque);
01021 int torque;
01022 torque = (int) wheelTorque;
01023
01024 if (abs((int)LAST_TOR - torque) > m_MaxTorqueStep && torque != 0)
01025 {
01026 if ((int) LAST_TOR >= 0 && (int) LAST_TOR < torque){
01027 torque = (int) LAST_TOR + 600;}
01028 else if ((int) LAST_TOR >= 0 && (int) LAST_TOR > torque){
01029 torque = (int) LAST_TOR - 600;}
01030 else if ((int) LAST_TOR < 0 && (int) LAST_TOR < torque){
01031 torque = (int) LAST_TOR + 600;}
01032 else if ((int) LAST_TOR < 0 && (int) LAST_TOR > torque){
01033 torque = (int) LAST_TOR - 600;}
01034 }
01035
01036
01037 if (abs(torque) > m_MaxWheelTorque)
01038 {
01039 torque = (int) LAST_TOR;
01040 }
01041
01042 static char *torqueCommand = new char[80];
01043 sprintf(torqueCommand, "T%d\n\n", torque);
01044 say(m_fd, torqueCommand);
01045
01046 m_CurrentWheelTorque = wheelTorque;
01047
01048
01049
01050 pthread_mutex_unlock(&m_Mutex);
01051 }
01052
01053
01054
01055
01056
01057
01058
01059 void PhysicalMomentumWheel::SetWheelTorqueLimits(const double& minWheelTorque, const double& maxWheelTorque)
01060 {
01061 m_MaxWheelTorque = maxWheelTorque;
01062 m_MinWheelTorque = minWheelTorque;
01063 }
01064
01065
01066 void PhysicalMomentumWheel::SetMaxTorqueStep(double maxTorqueStep)
01067 {
01068 m_MaxTorqueStep = maxTorqueStep;
01069 }
01070
01071 void PhysicalMomentumWheel::SetWheelAddress(int WheelAddress)
01072 {
01073 m_WheelAddress = 0x80 + WheelAddress;
01074 }
01075
01076 void PhysicalMomentumWheel::SetDaisyChainNumber(int DaisyChainNumber)
01077 {
01078 m_DaisyChainNumber = DaisyChainNumber;
01079
01080 }
01081
01082 void PhysicalMomentumWheel::SetDaisyChainPort(string DaisyChainPort)
01083 {
01084 m_DaisyChainPort = DaisyChainPort;
01085 }
01086
01087 void PhysicalMomentumWheel::SetBiasSpeed(double BiasSpeed)
01088 {
01089 m_BiasSpeed = BiasSpeed;
01090 if( m_BiasSpeed != 0 )
01091 {
01092 m_BiasFlag = 1;
01093 }
01094 }
01095
01096 void PhysicalMomentumWheel::SetAxialInertia(double _inertia)
01097 {
01098 m_AxialInertia = _inertia;
01099 }
01100
01101 void PhysicalMomentumWheel::SetWheelName( string _wheelName )
01102 {
01103 m_WheelName = _wheelName;
01104 }
01105
01106 void PhysicalMomentumWheel::SetWheelSpeedCoefficients( Vector _Coefficients1, Vector _Coefficients2, Vector _Coefficients3, Vector _Coefficients4 )
01107 {
01108 (m_Coefficients1)(_(1,4)) = _Coefficients1;
01109 (m_Coefficients2)(_(1,3)) = _Coefficients2;
01110 (m_Coefficients3)(_(1,3)) = _Coefficients3;
01111 (m_Coefficients4)(_(1,4)) = _Coefficients4;
01112 }
01113
01114
01115
01116
01117 void PhysicalMomentumWheel::GetWheelSpeed(double& Speed, double& measTime)
01118 {
01119 pthread_mutex_lock(&m_Mutex);
01120 Speed = m_CurrentWheelSpeed;
01121 measTime = m_VelocityTime;
01122 pthread_mutex_unlock(&m_Mutex);
01123 }
01124
01125
01126 double PhysicalMomentumWheel::QueryWheelTorque()
01127 {
01128 pthread_mutex_lock(&m_Mutex);
01129
01130 static char *clear = new char[80];
01131 hear(m_fd, clear, 79, 0, 3333, '\r');
01132
01133
01134 static char *RTCommand = new char[80];
01135 sprintf(RTCommand, "RT\n\n");
01136 say(m_fd, RTCommand);
01137
01138 static char *torqueString = new char[80];
01139 hear(m_fd, torqueString, 20, 0, 10000, '\r');
01140
01141 double Wtorque = atoi(torqueString+3) * 0.0018;
01142
01143 m_CurrentWheelTorque = Wtorque;
01144
01145 delete clear;
01146 delete RTCommand;
01147
01148 pthread_mutex_unlock(&m_Mutex);
01149 return Wtorque;
01150 }
01151
01152 void PhysicalMomentumWheel::GetAxialInertia( double& _inertia )
01153 {
01154 _inertia = m_AxialInertia;
01155 }
01156
01157 double PhysicalMomentumWheel::GetAxialInertia( )
01158 {
01159 return( m_AxialInertia );
01160 }
01161
01162 string PhysicalMomentumWheel::GetWheelName( )
01163 {
01164 return( m_WheelName );
01165 }
01166
01167 void PhysicalMomentumWheel::GetWheelTorqueLimits(double& minWheelTorque, double& maxWheelTorque)
01168 {
01169 maxWheelTorque = m_MaxWheelTorque;
01170 minWheelTorque = m_MinWheelTorque;
01171 return;
01172 }
01173
01174
01175 void PhysicalMomentumWheel::GetMaxTorqueStep(double& maxTorqueStep)
01176 {
01177 maxTorqueStep = m_MaxTorqueStep;
01178 return;
01179 }
01180
01181 int PhysicalMomentumWheel::GetWheelFD()
01182 {
01183 return m_fd;
01184 }
01185
01186 double PhysicalMomentumWheel::GetAmps()
01187 {
01188 char *ampString = new char[80];
01189 double mamps;
01190 double amps;
01191
01192
01193
01194 char *VarCommand = new char[80];
01195 sprintf(VarCommand, "a=UIA\rRa\n");
01196
01197 pthread_mutex_lock(&m_Mutex);
01198
01199
01200
01201 say(m_fd, VarCommand);
01202
01203
01204
01205
01206
01207
01208 hear(m_fd, ampString, 15, 0, 60000, '\r');
01209
01210 pthread_mutex_unlock(&m_Mutex);
01211
01212 mamps = atoi(ampString);
01213 amps = mamps/100;
01214
01215 return amps;
01216 }
01217
01218 double PhysicalMomentumWheel::GetVolts()
01219 {
01220 char *voltString = new char[80];
01221 double mvolts;
01222 double volts;
01223
01224 char* clear = new char[80];
01225
01226 char *VarCommand = new char[80];
01227 sprintf(VarCommand, "b=UJA\rRb\n");
01228
01229 pthread_mutex_lock(&m_Mutex);
01230
01231 while( !hear(m_fd, clear, 79, 0, 3333, 'c'));
01232
01233 say(m_fd, VarCommand);
01234
01235
01236
01237
01238
01239 hear(m_fd, voltString, 15, 0, 60000, '\r');
01240 pthread_mutex_unlock(&m_Mutex);
01241
01242 mvolts = atoi(voltString);
01243 volts = mvolts/10;
01244
01245 return volts;
01246 }
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303