trclib/TrcAccel.h
author Michael Tsang
Sat Feb 05 16:24:20 2011 -0800 (2011-02-05)
changeset 40 ea68beef9fd9
parent 4 6abfe78f80c6
permissions -rw-r--r--
Cleaned up
     1 #if 0
     2 /// Copyright (c) Titan Robotics Club. All rights reserved.
     3 ///
     4 /// <module name="TrcAccel.h" />
     5 ///
     6 /// <summary>
     7 ///     This module contains the definition and implementation of the TrcAccel
     8 ///     class.
     9 /// </summary>
    10 ///
    11 /// <remarks>
    12 ///     Environment: Wind River C++ for National Instrument cRIO based Robot.
    13 /// </remarks>
    14 #endif
    15 
    16 #ifndef _TRCACCEL_H
    17 #define _TRCACCEL_H
    18 
    19 #ifdef MOD_ID
    20     #undef MOD_ID
    21 #endif
    22 #define MOD_ID                  MOD_ACCEL
    23 #ifdef MOD_NAME
    24     #undef MOD_NAME
    25 #endif
    26 #define MOD_NAME                "TrcAccel"
    27 
    28 //
    29 // 50 calibration points at 20ms each will cost us a total of 1 second start
    30 // up time.
    31 //
    32 #ifndef ACCEL_NUM_CAL_PTS
    33     #define ACCEL_NUM_CAL_PTS   50
    34 #endif
    35 #ifndef ACCEL_CAL_INTERVAL
    36     #define ACCEL_CAL_INTERVAL  0.01    //10ms
    37 #endif
    38 
    39 /**
    40  * This class defines and implements the TrcAccel object. The TrcAccel object
    41  * inherits the ADXL345_I2C accelerometer object from the WPI library. This
    42  * object periodically sample the accelerometer value for the acceleration
    43  * value. It also integrates the acceleration value to calculate the velocity
    44  * and then integrates the velocity to calculate the distance value.
    45  */
    46 class TrcAccel: public ADXL345_I2C
    47 {
    48 private:
    49     SEM_ID      m_semaphore;
    50     Notifier   *m_notifier;
    51     AllAxes     m_accelData;
    52     AllAxes     m_zeroOffset;
    53     AllAxes     m_deadBand;
    54     double      m_xVel;
    55     double      m_yVel;
    56     double      m_zVel;
    57     double      m_xDist;
    58     double      m_yDist;
    59     double      m_zDist;
    60     bool        m_fEnabled;
    61     UINT32      m_timestamp;
    62     
    63     /**
    64      * This function is called periodically by the a timer callback to
    65      * process the accelerometer data. It integrates the data with time
    66      * to calculate the velocity, integrates it again to calculate
    67      * distance.
    68      */
    69     void
    70     Integrator(
    71         void
    72         )
    73     {
    74         TLevel(HIFREQ);
    75         TEnter();
    76 
    77         CRITICAL_REGION(m_semaphore)
    78         {
    79             if (m_fEnabled)
    80             {
    81                 UINT32 timeCurr = GetMsecTime();
    82                 float period = (float)(timeCurr - m_timestamp)/1000.0;
    83                 m_timestamp = timeCurr;
    84                 m_accelData = GetAccelerations();
    85                 m_accelData.XAxis -= m_zeroOffset.XAxis;
    86                 m_accelData.YAxis -= m_zeroOffset.YAxis;
    87                 m_accelData.ZAxis -= m_zeroOffset.ZAxis;
    88                 m_accelData.XAxis = GRAVITY_CONSTANT*
    89                                     DEADBAND(m_accelData.XAxis,
    90                                              m_deadBand.XAxis);
    91                 m_accelData.YAxis = GRAVITY_CONSTANT*
    92                                     DEADBAND(m_accelData.YAxis,
    93                                              m_deadBand.YAxis);
    94                 m_accelData.ZAxis = GRAVITY_CONSTANT*
    95                                     DEADBAND(m_accelData.ZAxis,
    96                                              m_deadBand.ZAxis);
    97                 m_xVel += m_accelData.XAxis*period;
    98                 m_yVel += m_accelData.YAxis*period;
    99                 m_zVel += m_accelData.ZAxis*period;
   100                 m_xDist += m_xVel*period;
   101                 m_yDist += m_yVel*period;
   102                 m_zDist += m_zVel*period;
   103                 TSampling(("X(%f,%f,%f), Y(%f,%f,%f), Z(%f,%f,%f)",
   104                            m_accelData.XAxis*FEET_PER_METER,
   105                            m_xVel*FEET_PER_METER,
   106                            m_xDist*FEET_PER_METER,
   107                            m_accelData.YAxis*FEET_PER_METER,
   108                            m_yVel*FEET_PER_METER,
   109                            m_yDist*FEET_PER_METER,
   110                            m_accelData.ZAxis*FEET_PER_METER,
   111                            m_zVel*FEET_PER_METER,
   112                            m_zDist*FEET_PER_METER));
   113             }
   114         }
   115         END_REGION;
   116 
   117         TExit();
   118     }   //Integrator
   119 
   120     /**
   121      * This function is called when the timer expired. It will call the
   122      * non-static worker function.
   123      *
   124      * @param timer Points to the TrcAccel object to call the worker function.
   125      */
   126     static
   127     void
   128     CallIntegrator(
   129         __in void *accel
   130         )
   131     {
   132         TLevel(HIFREQ);
   133         TEnterMsg(("accel=%p", accel));
   134         ((TrcAccel *)accel)->Integrator();
   135         TExit();
   136     }   //CallIntegrator
   137 
   138 public:
   139 
   140     /**
   141      * This function is called to calibrate the zero G point and deadband.
   142      * It assumes the accelerometer is sitting still at level ground during
   143      * the calibration. It samples a number of points on all axes and averages
   144      * them to be the zero G point for the axes. Note that the Z-axis is not
   145      * really at zero G when it is still. Z-axis should be 1G at level ground.
   146      * But for the purpose of measuring relative G's on all axes, we calibrate
   147      * zero G for all axes. During calibration, we also determine the floor
   148      * and ceiling noise level to form the deadband zone.
   149      *
   150      * @param numCalPts Specifies the number of calibration points.
   151      * @param calInterval Specifies the calibration interval in seconds.
   152      */
   153     void
   154     Calibrate(
   155         __in UINT32 numCalPts,
   156         __in float calInterval
   157         )
   158     {
   159         AllAxes data;
   160         AllAxes zeroG;
   161         AllAxes min;
   162         AllAxes max;
   163 
   164         TLevel(INIT);
   165         TEnter();
   166 
   167         zeroG.XAxis = 0.0;
   168         zeroG.YAxis = 0.0;
   169         zeroG.YAxis = 0.0;
   170         min.XAxis = 1000.0;
   171         min.YAxis = 1000.0;
   172         min.ZAxis = 1000.0;
   173         max.XAxis = 0.0;
   174         max.YAxis = 0.0;
   175         max.ZAxis = 0.0;
   176         for (UINT32 i = 0; i < numCalPts; i++)
   177         {
   178             data = GetAccelerations();
   179 
   180             zeroG.XAxis += data.XAxis;
   181             zeroG.YAxis += data.YAxis;
   182             zeroG.ZAxis += data.ZAxis;
   183 
   184             if (data.XAxis < min.XAxis)
   185             {
   186                 min.XAxis = data.XAxis;
   187             }
   188             else if (data.XAxis > max.XAxis)
   189             {
   190                 max.XAxis = data.XAxis;
   191             }
   192 
   193             if (data.YAxis < min.YAxis)
   194             {
   195                 min.YAxis = data.YAxis;
   196             }
   197             else if (data.YAxis > max.YAxis)
   198             {
   199                 max.YAxis = data.YAxis;
   200             }
   201 
   202             if (data.ZAxis < min.ZAxis)
   203             {
   204                 min.ZAxis = data.ZAxis;
   205             }
   206             else if (data.ZAxis > max.ZAxis)
   207             {
   208                 max.ZAxis = data.ZAxis;
   209             }
   210 
   211             Wait(calInterval);
   212         }
   213 
   214         CRITICAL_REGION(m_semaphore)
   215         {
   216             m_zeroOffset.XAxis = zeroG.XAxis/numCalPts;
   217             m_zeroOffset.YAxis = zeroG.YAxis/numCalPts;
   218             m_zeroOffset.ZAxis = zeroG.ZAxis/numCalPts;
   219 
   220             m_deadBand.XAxis = max.XAxis - min.XAxis;
   221             m_deadBand.YAxis = max.YAxis - min.YAxis;
   222             m_deadBand.ZAxis = max.ZAxis - min.ZAxis;
   223 
   224             TInfo(("AccelZeroG:x=%f,y=%f,z=%f, AccelDeadBand:x=%f,y=%f,z=%f",
   225                    m_zeroOffset.XAxis, m_zeroOffset.YAxis, m_zeroOffset.ZAxis,
   226                    m_deadBand.XAxis, m_deadBand.YAxis, m_deadBand.ZAxis));
   227         }
   228         END_REGION;
   229 
   230         Reset();
   231 
   232         TExit();
   233     }   //Calibrate
   234 
   235     /**
   236      * Constructor: Create an instance of the TrcAccel object. It initializes
   237      * the object and starts the periodic timer.
   238      *
   239      * @param slot Specifies the slot of the digital module on which the I2C
   240      *        port is used for the accelerometer.
   241      * @param period Specifies the sampling time for doing calculations. This
   242      *        period is used to integrate acceleration into speed and distance
   243      *        travelled.
   244      */
   245     TrcAccel(
   246         __in UINT32 slot,
   247         __in float  period = 0.02
   248         ): ADXL345_I2C(slot)
   249     {
   250         TLevel(INIT);
   251         TEnterMsg(("slot=%d,period=%f", slot, period));
   252 
   253         m_semaphore = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
   254         m_notifier = new Notifier(TrcAccel::CallIntegrator, this);
   255         m_accelData.XAxis = 0.0;
   256         m_accelData.YAxis = 0.0;
   257         m_accelData.ZAxis = 0.0;
   258         m_zeroOffset.XAxis = 0.0;
   259         m_zeroOffset.YAxis = 0.0;
   260         m_zeroOffset.ZAxis = 0.0;
   261         m_deadBand.XAxis = 0.0;
   262         m_deadBand.YAxis = 0.0;
   263         m_deadBand.ZAxis = 0.0;
   264         m_xVel = 0.0;
   265         m_yVel = 0.0;
   266         m_zVel = 0.0;
   267         m_xDist = 0.0;
   268         m_yDist = 0.0;
   269         m_zDist = 0.0;
   270         m_fEnabled = false;
   271         Calibrate(ACCEL_NUM_CAL_PTS, ACCEL_CAL_INTERVAL);
   272         m_notifier->StartPeriodic(period);
   273 
   274         TExit();
   275     }   //TrcAccel
   276 
   277     /**
   278      * Destructor: Destroy an instance of the TrcAccel object.
   279      */
   280     ~TrcAccel(
   281         void
   282         )
   283     {
   284         TLevel(INIT);
   285         TEnter();
   286 
   287         semFlush(m_semaphore);
   288         SAFE_DELETE(m_notifier);
   289 
   290         TExit();
   291     }   //~TrcAccel
   292 
   293     /**
   294      * This function returns the current acceleration value of the X axis in
   295      * the unit of meters per second square.
   296      *
   297      * @return Returns the X acceleration value.
   298      */
   299     double
   300     GetMetricAccelX(
   301         void
   302         )
   303     {
   304         TLevel(HIFREQ);
   305         TEnter();
   306         TExitMsg(("=%f", m_accelData.XAxis));
   307         return m_accelData.XAxis;
   308     }   //GetMetricAccelX
   309 
   310     /**
   311      * This function returns the current acceleration value of the X axis in
   312      * the unit of feet per second square.
   313      *
   314      * @return Returns the X acceleration value.
   315      */
   316     double
   317     GetAccelX(
   318         void
   319         )
   320     {
   321         TLevel(HIFREQ);
   322         TEnter();
   323         double value = m_accelData.XAxis*FEET_PER_METER;
   324         TExitMsg(("=%f", value));
   325         return value;
   326     }   //GetAccelX
   327 
   328     /**
   329      * This function returns the current acceleration value of the Y axis in
   330      * the unit of meters per second square.
   331      *
   332      * @return Returns the Y acceleration value.
   333      */
   334     double
   335     GetMetricAccelY(
   336         void
   337         )
   338     {
   339         TLevel(HIFREQ);
   340         TEnter();
   341         TExitMsg(("=%f", m_accelData.YAxis));
   342         return m_accelData.YAxis;
   343     }   //GetMetricAccelY
   344 
   345     /**
   346      * This function returns the current acceleration value of the Y axis in
   347      * the unit of feet per second square.
   348      *
   349      * @return Returns the Y acceleration value.
   350      */
   351     double
   352     GetAccelY(
   353         void
   354         )
   355     {
   356         TLevel(HIFREQ);
   357         TEnter();
   358         double value = m_accelData.YAxis*FEET_PER_METER;
   359         TExitMsg(("=%f", value));
   360         return value;
   361     }   //GetAccelY
   362 
   363     /**
   364      * This function returns the current acceleration value of the Z axis in
   365      * the unit of meters per second square.
   366      *
   367      * @return Returns the Z acceleration value.
   368      */
   369     double
   370     GetMetricAccelZ(
   371         void
   372         )
   373     {
   374         TLevel(HIFREQ);
   375         TEnter();
   376         TExitMsg(("=%f", m_accelData.ZAxis));
   377         return m_accelData.ZAxis;
   378     }   //GetMetricAccelZ
   379 
   380     /**
   381      * This function returns the current acceleration value of the Z axis in
   382      * the unit of feet per second square.
   383      *
   384      * @return Returns the Z acceleration value.
   385      */
   386     double
   387     GetAccelZ(
   388         void
   389         )
   390     {
   391         TLevel(HIFREQ);
   392         TEnter();
   393         double value = m_accelData.ZAxis*FEET_PER_METER;
   394         TExitMsg(("=%f", value));
   395         return value;
   396     }   //GetAccelZ
   397 
   398     /**
   399      * This function returns the current velocity value of the X axis in
   400      * the unit of meters per second.
   401      *
   402      * @return Returns the X velocity value.
   403      */
   404     double
   405     GetMetricVelX(
   406         void
   407         )
   408     {
   409         TLevel(HIFREQ);
   410         TEnter();
   411         TExitMsg(("=%f", m_xVel));
   412         return m_xVel;
   413     }   //GetMetricVelX
   414 
   415     /**
   416      * This function returns the current velocity value of the X axis in
   417      * the unit of feet per second.
   418      *
   419      * @return Returns the X velocity value.
   420      */
   421     double
   422     GetVelX(
   423         void
   424         )
   425     {
   426         TLevel(HIFREQ);
   427         TEnter();
   428         double value = m_xVel*FEET_PER_METER;
   429         TExitMsg(("=%f", value));
   430         return value;
   431     }   //GetVelX
   432 
   433     /**
   434      * This function returns the current velocity value of the Y axis in
   435      * the unit of meters per second.
   436      *
   437      * @return Returns the Y velocity value.
   438      */
   439     double
   440     GetMetricVelY(
   441         void
   442         )
   443     {
   444         TLevel(HIFREQ);
   445         TEnter();
   446         TExitMsg(("=%f", m_yVel));
   447         return m_yVel;
   448     }   //GetMetricVelY
   449 
   450     /**
   451      * This function returns the current velocity value of the Y axis in
   452      * the unit of feet per second.
   453      *
   454      * @return Returns the Y velocity value.
   455      */
   456     double
   457     GetVelY(
   458         void
   459         )
   460     {
   461         TLevel(HIFREQ);
   462         TEnter();
   463         double value = m_yVel*FEET_PER_METER;
   464         TExitMsg(("=%f", value));
   465         return value;
   466     }   //GetVelY
   467 
   468     /**
   469      * This function returns the current velocity value of the Z axis in
   470      * the unit of meters per second.
   471      *
   472      * @return Returns the Z velocity value.
   473      */
   474     double
   475     GetMetricVelZ(
   476         void
   477         )
   478     {
   479         TLevel(HIFREQ);
   480         TEnter();
   481         TExitMsg(("=%f", m_zVel));
   482         return m_zVel;
   483     }   //GetMetricVelZ
   484 
   485     /**
   486      * This function returns the current velocity value of the Z axis in
   487      * the unit of feet per second.
   488      *
   489      * @return Returns the Z velocity value.
   490      */
   491     double
   492     GetVelZ(
   493         void
   494         )
   495     {
   496         TLevel(HIFREQ);
   497         TEnter();
   498         double value = m_zVel*FEET_PER_METER;
   499         TExitMsg(("=%f", value));
   500         return value;
   501     }   //GetVelZ
   502 
   503     /**
   504      * This function returns the current distance value of the X axis in
   505      * the unit of meters.
   506      *
   507      * @return Returns the X distance value.
   508      */
   509     double
   510     GetMetricDistX(
   511         void
   512         )
   513     {
   514         TLevel(HIFREQ);
   515         TEnter();
   516         TExitMsg(("=%f", m_xDist));
   517         return m_xDist;
   518     }   //GetMetricDistX
   519 
   520     /**
   521      * This function returns the current distance value of the X axis in
   522      * the unit of feet.
   523      *
   524      * @return Returns the X distance value.
   525      */
   526     double
   527     GetDistX(
   528         void
   529         )
   530     {
   531         TLevel(HIFREQ);
   532         TEnter();
   533         double value = m_xDist*FEET_PER_METER;
   534         TExitMsg(("=%f", value));
   535         return value;
   536     }   //GetDistX
   537 
   538     /**
   539      * This function returns the current distance value of the Y axis in
   540      * the unit of meters.
   541      *
   542      * @return Returns the Y distance value.
   543      */
   544     double
   545     GetMetricDistY(
   546         void
   547         )
   548     {
   549         TLevel(HIFREQ);
   550         TEnter();
   551         TExitMsg(("=%f", m_yDist));
   552         return m_yDist;
   553     }   //GetMetricDistY
   554 
   555     /**
   556      * This function returns the current distance value of the Y axis in
   557      * the unit of feet.
   558      *
   559      * @return Returns the Y distance value.
   560      */
   561     double
   562     GetDistY(
   563         void
   564         )
   565     {
   566         TLevel(HIFREQ);
   567         TEnter();
   568         double value = m_yDist*FEET_PER_METER;
   569         TExitMsg(("=%f", value));
   570         return value;
   571     }   //GetDistY
   572 
   573     /**
   574      * This function returns the current distance value of the Z axis in
   575      * the unit of meters.
   576      *
   577      * @return Returns the Z distance value.
   578      */
   579     double
   580     GetMetricDistZ(
   581         void
   582         )
   583     {
   584         TLevel(HIFREQ);
   585         TEnter();
   586         TExitMsg(("=%f", m_zDist));
   587         return m_zDist;
   588     }   //GetMetricDistZ
   589 
   590     /**
   591      * This function returns the current distance value of the Z axis in
   592      * the unit of feet.
   593      *
   594      * @return Returns the Z distance value.
   595      */
   596     double
   597     GetDistZ(
   598         void
   599         )
   600     {
   601         TLevel(HIFREQ);
   602         TEnter();
   603         double value = m_zDist*FEET_PER_METER;
   604         TExitMsg(("=%f", value));
   605         return value;
   606     }   //GetDistZ
   607 
   608     /**
   609      * This function resets the acceleration, velocity and distance values.
   610      */
   611     void
   612     Reset(
   613         void
   614         )
   615     {
   616         TLevel(API);
   617         TEnter();
   618 
   619         CRITICAL_REGION(m_semaphore)
   620         {
   621             m_accelData.XAxis = 0.0;
   622             m_accelData.YAxis = 0.0;
   623             m_accelData.ZAxis = 0.0;
   624             m_xVel = 0.0;
   625             m_yVel = 0.0;
   626             m_zVel = 0.0;
   627             m_xDist = 0.0;
   628             m_yDist = 0.0;
   629             m_zDist = 0.0;
   630         }
   631         END_REGION;
   632 
   633         TExit();
   634     }   //Reset
   635 
   636     /**
   637      * This function sets the accelerometer to enable or disable state.
   638      *
   639      * @param fEnabled If true, enables the accelerometer, false otherwise.
   640      */
   641     void
   642     SetEnabled(
   643         __in bool fEnabled
   644         )
   645     {
   646         TLevel(API);
   647         TEnter();
   648 
   649         m_fEnabled = fEnabled;
   650         if (fEnabled)
   651         {
   652             Reset();
   653             m_timestamp = GetMsecTime();
   654         }
   655 
   656         TExit();
   657     }   //SetEnabled
   658 };  //class TrcAccel
   659 
   660 #endif  //ifndef _TRCACCEL_H