TAPs 0.7.7.3
TAPsSensAble_hduRecord.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002 TAPsSensAble_hduRecord.cpp
00003 
00004 Modified from SensAble hduRecord.cpp
00005 
00006 SUKITTI PUNAK   (11/27/2006)
00007 UPDATE          (11/27/2006)
00008 ******************************************************************************/
00009 #include "TAPsSensAble_hduRecord.hpp"
00010 // Using Inclusion Model (i.e. definitions are included in declarations)
00011 //                       (this name.cpp is included in name.hpp)
00012 // Each friend is defined directly inside its declaration.
00013 
00014 
00015 // Original comment from hduRecord.cpp
00016 /*****************************************************************************
00017 
00018 Copyright (c) 2004 SensAble Technologies, Inc. All rights reserved.
00019 
00020 OpenHaptics(TM) toolkit. The material embodied in this software and use of
00021 this software is subject to the terms and conditions of the clickthrough
00022 Development License Agreement.
00023 
00024 For questions, comments or bug reports, go to forums at: 
00025     http://dsc.sensable.com
00026 
00027 Module Name:
00028 
00029   hduRecord.cpp
00030 
00031 Description: 
00032 
00033   Records device data from the scheduler for a specified number of ticks, and 
00034   with option to add additional user data.
00035 
00036 ******************************************************************************/
00037 
00038 //#include "hduAfx.h"
00039 
00040 #include <iostream>
00041 
00042 #include <HDU/hduRecord.h>
00043 #include <HDU/hduVector.h>
00044 
00045 #include <HD/hdCompilerConfig.h>
00046 #include <HD/hdScheduler.h>
00047 #include <HD/hdDevice.h>
00048 
00049 BEGIN_NAMESPACE_TAPs__Haptic
00050 //=============================================================================
00051 
00052 #if defined WIN32
00053 # include <process.h>
00054   typedef void thread_rv;
00055 #elif defined(linux) || defined(__APPLE__)
00056 # include <pthread.h>
00057   typedef void* thread_rv;
00058 #endif
00059 
00060 /* Scheduler callback for getting data for each iteration. */
00061 HDCallbackCode HDCALLBACK SensAble_RecordLoopCallback ( 
00062     void * SensAble_hduRecorder );
00063 
00064 /* Thread callback for writing out data to file. */
00065 thread_rv SensAble_RecordWriteCallback( void * data );
00066 
00067 /******************************************************************************
00068  Data packet for each iteration. 
00069 ******************************************************************************/
00070 struct SensAble_hduRecorderPacket
00071 {
00072     hduVector3Dd    m_force;
00073     hduVector3Dd    m_position;
00074     hduVector3Dd    m_velocity;
00075     char *          m_userData;
00076 };
00077 
00078 /******************************************************************************
00079  Main class that handles recording. 
00080 ******************************************************************************/
00081 class SensAble_hduRecorder
00082 {
00083     //---------------------------------------------------------------
00084 public:
00085     SensAble_hduRecorder (
00086         FILE *              file,
00087         HDURecordCallback & pUserCallback,
00088         void *              pUserCallbackData,
00089         int                 numData
00090     );
00091     virtual ~SensAble_hduRecorder ();
00092     HDboolean Start ();
00093     HDboolean AddData ();
00094     void WriteDataToFile ();
00095     //---------------------------------
00096     // HDSchedulerHandle is unsigned long.
00097     HDSchedulerHandle GetShedulerHandle () { return m_hdSchedulerHandle; }
00098     //-----------------------
00099 //  HDboolean GetStatusCompletion () {
00100 //      if ( m_hdSchedulerHandle == 0 ) return true;
00101 //      return !hdWaitForCompletion( m_hdSchedulerHandle, HD_WAIT_CHECK_STATUS );
00102 //  }
00103     //---------------------------------------------------------------
00104 private:
00105     SensAble_HDURecordCallback *    m_pUserCallback;
00106     void *                          m_pUserCallbackData;
00107     FILE *                          m_file;
00108     int                             m_numData;
00109     int                             m_index;
00110     SensAble_hduRecorderPacket *    m_data;
00111     //---------------------------------
00112     // For checking completion status
00113     HDSchedulerHandle               m_hdSchedulerHandle;
00114 };
00115 
00116 /******************************************************************************
00117  Constructor
00118 ******************************************************************************/
00119 SensAble_hduRecorder::SensAble_hduRecorder (
00120     FILE *                          file,
00121     SensAble_HDURecordCallback &    pUserCallback,
00122     void *                          pUserCallbackData,
00123     int                             numData
00124 ) :
00125     m_file( file ),
00126     m_pUserCallback( pUserCallback ),
00127     m_pUserCallbackData( pUserCallbackData ),
00128     m_numData( numData ),
00129     m_index( 0 ),
00130     m_data( 0 ), 
00131     m_hdSchedulerHandle( 0 )
00132 {
00133     m_data = new SensAble_hduRecorderPacket[ numData ];
00134 }
00135 
00136 /******************************************************************************
00137  Destructor
00138 ******************************************************************************/
00139 SensAble_hduRecorder::~SensAble_hduRecorder ()
00140 {
00141     for ( int i = 0; i < m_numData; ++i ) {
00142         delete m_data[i].m_userData;
00143     }
00144     delete[] m_data;
00145 }
00146 
00147 /******************************************************************************
00148  Start the recording.  Schedule a callback that records device data for 
00149  every scheduler tick. 
00150 ******************************************************************************/
00151 HDboolean SensAble_hduRecorder::Start ()
00152 {
00153     m_hdSchedulerHandle = hdScheduleAsynchronous(
00154         SensAble_RecordLoopCallback,
00155         this,
00156         HD_MIN_SCHEDULER_PRIORITY
00157     );
00158     return ( m_hdSchedulerHandle == HD_INVALID_HANDLE ? false : true );
00159 }
00160 
00161 /******************************************************************************
00162  Worker thread callback to write the data to file.
00163 ******************************************************************************/
00164 thread_rv SensAble_RecordWriteCallback ( void * data )
00165 {
00166     SensAble_hduRecorder * pRecord = ( SensAble_hduRecorder * ) data;
00167     pRecord->WriteDataToFile();
00168     delete pRecord;
00169 }
00170 
00171 /******************************************************************************
00172  Write all the data out at once when the recording is done.
00173 ******************************************************************************/
00174 void SensAble_hduRecorder::WriteDataToFile ()
00175 {
00176     //*
00177     //---------------------------------------------------------------
00178     // Without data names
00179     for ( int i = 0; i < m_numData; ++i ) {
00180         SensAble_hduRecorderPacket & data = m_data[i];
00181         fprintf( m_file, "%d\t", i );
00182         fprintf( m_file, "%f %f %f\t", 
00183                 data.m_force[0],
00184                 data.m_force[1],
00185                 data.m_force[2] );
00186         fprintf( m_file,"%f %f %f\t", 
00187                 data.m_position[0],
00188                 data.m_position[1],
00189                 data.m_position[2] );
00190         fprintf( m_file, "%f %f %f\t", 
00191                 data.m_velocity[0],
00192                 data.m_velocity[1],
00193                 data.m_velocity[2] );
00194         fprintf( m_file,"%s\n",data.m_userData );
00195     }
00196     //*/
00197     /*
00198     //---------------------------------------------------------------
00199     // With data names
00200     for ( int i = 0; i < m_numData; ++i ) {
00201         SensAble_hduRecorderPacket & data = m_data[i];
00202         fprintf( m_file, "%d\t", i );
00203         fprintf( m_file, "Force: %f %f %f\t\t", 
00204                 data.m_force[0],
00205                 data.m_force[1],
00206                 data.m_force[2] );
00207         fprintf( m_file,"Position: %f %f %f\t\t", 
00208                 data.m_position[0],
00209                 data.m_position[1],
00210                 data.m_position[2] );
00211         fprintf( m_file, "Velocity: %f %f %f\t\t", 
00212                 data.m_velocity[0],
00213                 data.m_velocity[1],
00214                 data.m_velocity[2] );
00215         fprintf( m_file,"%s\n",data.m_userData );
00216     }
00217     //*/
00218 }
00219 
00220 /******************************************************************************
00221  Scheduler callback; at each scheduler tick, add one tick's worth of data.
00222 ******************************************************************************/
00223 HDCallbackCode HDCALLBACK SensAble_RecordLoopCallback ( 
00224     void * _SensAble_hduRecorder )
00225 {
00226     SensAble_hduRecorder * pRecord = 
00227         ( SensAble_hduRecorder * ) _SensAble_hduRecorder;
00228     HDboolean bDone = pRecord->AddData();
00229     //---------------------------------------------------------------
00230     // If done, then create another thread to write out the data.
00231     if ( bDone ) {
00232 #if defined( WIN32 )
00233         _beginthread( SensAble_RecordWriteCallback, 0, pRecord );
00234 #elif defined(linux) || defined(__APPLE__)
00235         pthread_create( NULL, NULL, SensAble_RecordWriteCallback, pRecord );
00236 #endif
00237         return HD_CALLBACK_DONE;
00238     }
00239     //---------------------------------------------------------------
00240     return HD_CALLBACK_CONTINUE;
00241 }
00242 
00243 /******************************************************************************
00244  Adds data for one tick.  Return true if done
00245 ******************************************************************************/
00246 HDboolean SensAble_hduRecorder::AddData ()
00247 {
00248     //---------------------------------------------------------------
00249     // Get the data and fill one packet.
00250     static SensAble_hduRecorderPacket data;
00251     hdGetDoublev( HD_CURRENT_FORCE,     data.m_force );
00252     hdGetDoublev( HD_CURRENT_POSITION,  data.m_position );
00253     hdGetDoublev( HD_CURRENT_VELOCITY,  data.m_velocity );
00254     data.m_userData = 0;
00255     if ( m_pUserCallback ) {
00256         char * userData = ( * m_pUserCallback )( m_pUserCallbackData );
00257         data.m_userData = userData;
00258     }
00259     //---------------------------------------------------------------
00260     // Either add the data to storage, or stop getting data 
00261     // if the recorder has received the amount specified.
00262     if ( m_index < m_numData ) {
00263         m_data[m_index] = data;
00264         ++m_index;
00265         return false;
00266     }
00267     else {
00268         return true;
00269     }
00270 }
00271 
00272 /******************************************************************************
00273  Create a recorder, start recording.  
00274 ******************************************************************************/
00275 HDSchedulerHandle SensAble_hduStartRecord (
00276     FILE *              file,
00277     HDURecordCallback   pCallback,
00278     void *              pCallbackData,
00279     unsigned int        nData
00280 )
00281 {
00282     if ( !file ) {
00283         return false;
00284     }
00285     //-------------------------------------------
00286     SensAble_hduRecorder * pRecord = 
00287         new SensAble_hduRecorder(
00288                 file,
00289                 *pCallback,
00290                 pCallbackData,
00291                 nData );
00292     //-------------------------------------------
00293     if ( pRecord->Start() ) {
00294         return pRecord->GetShedulerHandle();
00295     }
00296     else {
00297         delete pRecord;
00298         return 0;
00299     }
00300 }
00301 /*****************************************************************************/
00302 //=============================================================================
00303 END_NAMESPACE_TAPs__Haptic
00304 //-----------------------------------------------------------------------------
00305 //34567890123456789012345678901234567890123456789012345678901234567890123456789
00306 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines