Commit 5dc78a30 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev
Browse files

read imu log interface

parent 9a7461bc
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ SRCS = nmea2exif.c log_imu.c
OBJS =      nmea2exif.o
PHPSCRIPTS= start_gps_compass.php
PHPWEB=     logger_launcher.php imu_setup.php read_imu_log.php
WEB=        read_imu_log.html read_imu_log.js

CFLAGS   += -Wall -I$(STAGING_DIR_HOST)/usr/include-uapi
LDLIBS   += -lm
@@ -33,6 +34,7 @@ install: $(PROGS)
	$(INSTALL) -m $(INSTMODE) -o $(INSTOWNER) -g $(INSTGROUP) $(PROGS) $(DESTDIR)$(BINDIR)
	$(INSTALL) -m $(INSTMODE) -o $(INSTOWNER) -g $(INSTGROUP) $(PHPSCRIPTS) $(DESTDIR)$(BINDIR)
	$(INSTALL) -o $(INSTOWNER) -m $(INSTDOCS) $(PHPWEB)  $(DESTDIR)$(WWW_PAGES)
	$(INSTALL) -o $(INSTOWNER) -m $(INSTDOCS) $(WEB)  $(DESTDIR)$(WWW_PAGES)
	$(INSTALL) $(OWN)-d $(DESTDIR)$(VARHTML)
	$(LN) -sf $(VARHTML) $(DESTDIR)$(WWW_PAGES)var
	$(INSTALL) $(OWN)-d $(DESTDIR)$(CONFDIR)

src/read_imu_log.html

0 → 100644
+69 −0
Original line number Diff line number Diff line
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <meta name="author" content="?"/>
    <script src="read_imu_log.js"></script>
    <style>
    #results td{
      padding:0px 10px;
    }
    #results{
      font-size:14px;
    }
    
    #controls{
      background: rgba(100,200,100,0.5);
      padding: 10px;
    }
    </style>
  </head>
  <body>
    <table id='controls'>
    <tr>
      <td>
        <table>
        <tr>
          <td>Filename: <input type='text' id='file' value='/home/root/imu.log' style='width:200px;' onchange='getRqStr()'></td>
        </tr>
        <tr>
          <td colspan=''>Record filter:&nbsp;
            <span title='External device'>EXT
              <input id='filter_6' type='checkbox' checked onchange='getRqStr()'>
            </span>&nbsp;&nbsp;
            <span title='Image trigger signal'>IMG
              <input id='filter_5' type='checkbox' checked onchange='getRqStr()'>
            </span>&nbsp;&nbsp;
            <span title='IMU'>IMU
              <input id='filter_4' type='checkbox' checked onchange='getRqStr()'>
            </span>&nbsp;&nbsp;
            <span title='GPS'>GPS
              <input id='filter_3' type='checkbox' checked onchange='getRqStr()'>
              <input id='filter_2' type='checkbox' checked onchange='getRqStr()'>
              <input id='filter_1' type='checkbox' checked onchange='getRqStr()'>
              <input id='filter_0' type='checkbox' checked onchange='getRqStr()'>
            </span>
          </td>
        </tr>
        <tr>
          <td>
            <table>
            <tr>
              <td>Begin</td><td><input id='start' type='text' value='0' style='width:100px;text-align:right;' onchange='getRqStr()'></td>
            </tr>
            <tr>
              <td>End</td><td><input id='end' type='text' value='5000' style='width:100px;text-align:right;' onchange='getRqStr()'></td>
            </tr>
            </table>
          </td>
        </tr>
        <tr>
          <td><button onclick='show()'>Show</button>&nbsp;&nbsp;<span id='csvlink'></span></td>
        </tr>
        </table>
      </td>
    </tr>
    </table>
    <div id='results'></div>
  </body>
</html>

src/read_imu_log.js

0 → 100644
+171 −0
Original line number Diff line number Diff line
function init(){
  console.log("init");
}

function show(){
  console.log("show");
    
  report("status: waiting for response");
  
  var rqstr = getRqStr();
  
  var request = new XMLHttpRequest();
  request.open('GET', rqstr, true);

  request.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {      
      var resp = this.responseText;
      report("status: parsing response");
      clearInterval(loading_interval);
      parse_response(resp);
      report("<a href='"+rqstr+"'>Download in CSV format</a>");
    }
  };
  
  request.onerror = function() {
    // There was a connection error of some sort
  };
  
  loading_interval = setInterval(loading,100);
  request.send();
}

function getRqStr(){
  var filename = document.getElementById("file").value;
  
  var filter = 0;
  for(var i=0;i<7;i++){
    bit = (document.getElementById("filter_"+i).checked)?1:0;
    filter += (bit<<i);
  }
  
  var start = document.getElementById("start").value;
  var end = document.getElementById("end").value;
  
  var n = end - start;
  
  if (n<0) {
    console.log("Error: Begin > End");
    n = 1;
  }
  
  var rqstr = "read_imu_log.php?file="+filename+"&record="+start+"&nrecords="+n+"&filter="+filter;
  
  report("");
  setTimeout(function(){
    report("<a href='"+rqstr+"'>Download in CSV format</a>");
  },100);
  
  return rqstr;
}

function parse_response(csv){  
  var t = CSVToArray(csv,",");
  
  var result = "";
  
  for(var i=0;i<t.length;i++){
    if (t[i].length>0){
      result += "<tr>";
      for(var j=0;j<t[i].length;j++){
        result += "<td>"+t[i][j]+"</td>";
      }      result += "</tr>";

    }
  }
  document.getElementById("results").innerHTML = "<table>"+result+"</table>";
}

function report(msg){
  document.getElementById("csvlink").innerHTML = msg;
}

var loading_interval;

function loading(){
  console.log("loading");
}

//http://stackoverflow.com/questions/1293147/javascript-code-to-parse-csv-data
function CSVToArray( strData, strDelimiter ){
    // Check to see if the delimiter is defined. If not,
    // then default to comma.
    strDelimiter = (strDelimiter || ",");

    // Create a regular expression to parse the CSV values.
    var objPattern = new RegExp(
        (
            // Delimiters.
            "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +

            // Quoted fields.
            "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +

            // Standard fields.
            "([^\"\\" + strDelimiter + "\\r\\n]*))"
        ),
        "gi"
        );


    // Create an array to hold our data. Give the array
    // a default empty first row.
    var arrData = [[]];

    // Create an array to hold our individual pattern
    // matching groups.
    var arrMatches = null;


    // Keep looping over the regular expression matches
    // until we can no longer find a match.
    while (arrMatches = objPattern.exec( strData )){

        // Get the delimiter that was found.
        var strMatchedDelimiter = arrMatches[ 1 ];

        // Check to see if the given delimiter has a length
        // (is not the start of string) and if it matches
        // field delimiter. If id does not, then we know
        // that this delimiter is a row delimiter.
        if (
            strMatchedDelimiter.length &&
            strMatchedDelimiter !== strDelimiter
            ){

            // Since we have reached a new row of data,
            // add an empty row to our data array.
            arrData.push( [] );

        }

        var strMatchedValue;

        // Now that we have our delimiter out of the way,
        // let's check to see which kind of value we
        // captured (quoted or unquoted).
        if (arrMatches[ 2 ]){

            // We found a quoted value. When we capture
            // this value, unescape any double quotes.
            strMatchedValue = arrMatches[ 2 ].replace(
                new RegExp( "\"\"", "g" ),
                "\""
                );

        } else {

            // We found a non-quoted value.
            strMatchedValue = arrMatches[ 3 ];

        }


        // Now that we have our value string, let's add
        // it to the data array.
        arrData[ arrData.length - 1 ].push( strMatchedValue );
    }

    // Return the parsed data.
    return( arrData );
}
 No newline at end of file
+145 −114
Original line number Diff line number Diff line
<?php
if (!isset($_GET['file'])){ 

if (isset($_GET['file'])){
  if (is_file($_GET['file'])){
    $file = $_GET['file'];
    $numRecordsInFile=filesize($file)/64;
  }else{
    echo "File not found";
    die(0);  
  }
}else{
  echo "<pre>\n";
  echo "?file=log_file_name&record=record_number&nrecords=number_of_records&filter=filter";
  echo "</pre>\n";
  exit (0);
  echo <<<TEXT
  Usage: <b>http://address/read_imu_log.php?file=..&record=..&nrecords=..&filter=..</b>
      * <b>file</b> - absolute path to file
      * <b>record</b> - starting record index, default = 0
      * <b>nrecords</b> - number of records to parse, default = 5000
      * <b>filter</b> - filter out types of displayed records:
          0x10 - display imu records only
          0x20 - display image records only
          0x40 - display external trigger records only
        for gps records:
          0x01 - display NMEA GPRMC records (have coordinates)
          0x02 - display NMEA GPGGA records (have coordinates)
          0x04 - display NMEA GPGSA records
          0x08 - display NMEA GPVTG records,
        default = 0x7f (display everything)   
TEXT;
  die(0);
}

//$timeShift = 21600; // 6 hrs
$timeShift = 0; // 6 hrs
if (isset($_GET['record']))   $record = $_GET['record']+0;
else                          $record=0;

$file=$_GET['file'];
$numRecordsInFile=filesize($file)/64;
$record=0;
$nRecords=1;
if ($record>($numRecordsInFile-1)) $record=$numRecordsInFile-1;

if (isset($_GET['nrecords'])) $nRecords = $_GET['nrecords']+0;
else{
  if ($numRecordsInFile>5000)
    $nRecords=5000;
  else
    $nRecords=$numRecordsInFile;
}

if ($nRecords>($numRecordsInFile-$record)) $nRecords= $numRecordsInFile-$record;


if (isset($_GET['filter'])) $filter= intval($_GET['filter'],0);
else                        $filter= 0x7f;
/*
 1 - NMEA sentence 0 $GPRMC (log type 1)
 2 - NMEA sentence 1 $GPGGA (log type 1)
@@ -21,25 +55,22 @@ $nRecords=1;
16 - IMU (type 0)
32 - SYNC (type 2)
64 - ODOMETER (type 3)

*/
$filter=0x7f;

//$timeShift = 21600; // 6 hrs
$timeShift = 0; // 0 hrs

$type=-1;
$gpsType=-1;
if (isset($_GET['record']))   $record=    $_GET['record']+0;
if (isset($_GET['nrecords'])) $nRecords=  $_GET['nrecords']+0;
if (isset($_GET['filter']))   $filter=    $_GET['filter']+0;

if ($record>($numRecordsInFile-1)) $record=$numRecordsInFile-1;
if ($nRecords>($numRecordsInFile-$record)) $nRecords= $numRecordsInFile-$record;

  echo "<pre>\n";
  echo "Number of samples in file=$numRecordsInFile\n";
  echo "</pre>\n";

echo "Filename,$file\n";
echo "Found Records,$numRecordsInFile\n";
echo "Record filter,0x".dechex($filter)."\n";
echo "Start index,$record\n";
echo "End index,".($record+$nRecords)."\n\n";

$log_file=fopen($file,'r');

$averageIMU=array(
    "number"=>0,
    "gyroX"=> 0,
@@ -56,97 +87,94 @@ $averageIMU=array(
    "velocityZ"=>0,
    "temperature"=>0);

$imuFieldOrder = array(
    "gyroX",
    "gyroY",
    "gyroZ",
    "accelX",
    "accelY",
    "accelZ",
    "angleX",
    "angleY",
    "angleZ",
    "velocityX",
    "velocityY",
    "velocityZ",
    "temperature"
);
    
imuLogParse($log_file,$record,$nRecords,$filter);
exit(0);

die(0);

function imuLogParse($handle,$record,$nSamples,$filter,$tryNumber=10000){

  global $timeShift;

  global $averageIMU;
  global $imuFieldOrder;
  
  $showAll=($nSamples<=100000);
  
  $gpsFilter= $filter&0xf;
  
  $typeFilter=(($gpsFilter!=0)?2:0) | ((($filter&0x10)!=0)?1:0) | ((($filter&0x20)!=0)?4:0) | ((($filter&0x20)!=0)?8:0);
  
  fseek($handle,64*$record,SEEK_SET);
  echo "<pre>\n";
//  echo "filter=$filter, gpsFilter=$gpsFilter, typeFilter=$typeFilter, record=$record, nSamples=$nSamples\n";
  
  echo "Index,Timestamp,Type,".implode(",",$imuFieldOrder).",non-IMU data\n";
  
  for ($nSample=0;$nSample<$nSamples;$nSample++) {
  
    $sample=fread($handle,64);
    $arr32=unpack('L*',$sample);
    
    $time=(($arr32[1]&0xfffff)/1000000)+$arr32[2];
    $type=$arr32[1]>>24;
    $gps=($type==1)?($arr32[3]&0x3):0xf; // any if it is not GPS sample
    
    if ((((1<<$type)&$typeFilter)!=0) && (($type!=1) || (((1<<$gps)&$gpsFilter)!=0))) {
      //$arr8=unpack('C*',$sample);
      $time=(($arr32[1]&0xfffff)/1000000)+$arr32[2];
  if ($showAll) printf("%8d %f: ",($record+$nSample),$time);
    
      if ($showAll) printf("%8d,%f,$type,",($record+$nSample),$time);
      
      switch ($type) {
        // IMU record
        case 0:
//          print_r($arr32);
//           if ($showAll) {
//             for ($i=2;$i<16;$i++) {
//               printf(" %9d",$arr32[$i+1]);
//             }
//             echo "\n";
//              printf("%8d %f: ",($record+$nSample),$time);
//             for ($i=2;$i<16;$i++) {
//               printf(" %9x",0xffffffff&$arr32[$i+1]);
//             }
//             echo "\n";
//           }

          $imuSample=parseIMU($arr32);
          
	  //if ($showAll) print_r($imuSample);
	  if ($showAll) echo " [angleX]=>".$imuSample["angleX"]."     [angleY]=>".$imuSample["angleY"]."     [angleZ]=>".$imuSample["angleZ"].
          echo implode(",",$imuSample)."\n";
          
          /*
          echo " [angleX]=>".$imuSample["angleX"]."     [angleY]=>".$imuSample["angleY"]."     [angleZ]=>".$imuSample["angleZ"].
                             "     [gyroX] =>".$imuSample["gyroX"] ."      [gyroY]=>".$imuSample["gyroY"] ."      [gyroZ]=>".$imuSample["gyroZ"].
                             "     [accelX] =>".$imuSample["accelX"] ."      [accelY]=>".$imuSample["accelY"] ."      [accelZ]=>".$imuSample["accelZ"].
                             "     [velocityX] =>".$imuSample["velocityX"] ."      [velocityY]=>".$imuSample["velocityY"] ."      [velocityZ]=>".$imuSample["velocityZ"].
                             "     [temperature]=>".$imuSample["temperature"]."\n";

          $averageIMU["number"]++;
          foreach ($imuSample as $key=>$value) $averageIMU[$key]+=$value;

	  $avg_x = $averageIMU["angleX"]/$averageIMU["number"];
	  $avg_y = $averageIMU["angleY"]/$averageIMU["number"];
	  $avg_z = $averageIMU["angleZ"]/$averageIMU["number"];

	  //echo $avg_x." ".$avg_y." ".$avg_z."\n";
	  

          */
          break;
          
        // GPS record
        case 1:
        
          $nmeaArray=parseGPS($sample);
          $nmeaString='$';
          for ($i=0; $i<count($nmeaArray);$i++) {
            $nmeaString.=$nmeaArray[$i];
            if ($i < (count($nmeaArray)-1))$nmeaString.=',';
          }
          echo "GPS (NMEA): ".$nmeaString."\n";
          $nmeaString = '$'.implode(",",$nmeaArray);
          
          echo ",,,,,,,,,,,,,\"GPS (NMEA): ".$nmeaString."\"\n";
          break;
          
        // Master (Sync) record
        case 2:
          $masterTime=(($arr32[3]&0xfffff)/1000000)+$arr32[4];
          $subchannel = ($arr32[3] >> 24);
          echo "Subchannel: <b>".$subchannel."</b> MasterTimeStamp: <b>".($masterTime+$timeShift)."</b> TimeStamp: <b>".($time+$timeShift)."</b>   MasterTimeStamp(precise): 0x".dechex($arr32[4])."+".dechex($arr32[3])." TimeStamp(precise): 0x".dechex($arr32[2])."+".dechex($arr32[1])." $masterTime - ".gmdate(DATE_RFC850,$masterTime)." [local timestamp - ".gmdate(DATE_RFC850,$time)."]\n";
          echo ",,,,,,,,,,,,,\"Subchannel: <b>".$subchannel."</b> MasterTimeStamp: <b>".($masterTime+$timeShift)."</b> TimeStamp: <b>".($time+$timeShift)."</b>   MasterTimeStamp(precise): 0x".dechex($arr32[4])."+".dechex($arr32[3])." TimeStamp(precise): 0x".dechex($arr32[2])."+".dechex($arr32[1])." $masterTime - ".gmdate(DATE_RFC850,$masterTime)." [local timestamp - ".gmdate(DATE_RFC850,$time)."]\"\n";
          break;
          
        // Show hex data
        case 3: print_r($arr32);
          break;
      }
    }
  }
  if ($averageIMU['number']>0) {
		foreach ( $averageIMU as $key => $value )
			if ($key != 'number')
				$averageIMU [$key] /= $averageIMU ['number'];
		print_r ( $averageIMU );
		echo "</pre>\n";
		echo "<table>\n";
		foreach ( $averageIMU as $key => $value )
			echo "<tr><td>$key</td><td>$value</td></tr>\n";
		echo "</table>\n";
  }
}

function parseGPS($sample){
@@ -174,7 +202,7 @@ function parseGPS($sample){
  $type=$arr8[4];
  $nibbleNumber=16; // starting with 0;
  $gps=getNibble($nibbleNumber++,$arr8);
//echo "gps=$gps\n";

  $rslt=array(0=>$sentences[$gps]);
  for ($i=0;$i<count($formats[$gps]);$i++){
    $rslt[$i+1]='';
@@ -194,11 +222,44 @@ function parseGPS($sample){
  }
  return $rslt;
}

function getNibble($n,$arr8){
 return ($arr8[($n>>1)+1]>>(($n&1)?4:0))&0xf;
}
function parseNMEA($sent,$data){

function parseIMU ($arr32){
  $gyroScale=0.013108/65536;      // deg/sec
  $accelScale=0.8192/65536;       // mg
  $angleScale= 0.005493/65536;    // degrees
  $velocityScale=0.0030518/65536; // m/sec
  //$angleScale= 0.005493;      //degrees
  //$velocityScale=0.0030518;   //m/sec
  $temperatureScale=0.00565;      // C/LSB
  $t=($arr32[15] & 0xffff);
  if ($t>=32768) $t-=65536;
  
  for ($i=3;$i<15;$i++) if ((($arr32[$i] & 0x80000000)!=0) && ($arr32[$i] > 0)) $arr32[$i]-=0x100000000;
  
  return array(
    "gyroX"=> $arr32[ 3]*$gyroScale,
    "gyroY"=> $arr32[ 4]*$gyroScale,
    "gyroZ"=> $arr32[ 5]*$gyroScale,
    "accelX"=>$arr32[ 6]*$accelScale,
    "accelY"=>$arr32[ 7]*$accelScale,
    "accelZ"=>$arr32[ 8]*$accelScale,
    "angleX"=>$arr32[ 9]*$angleScale,
    "angleY"=>$arr32[10]*$angleScale,
    "angleZ"=>$arr32[11]*$angleScale,
    "velocityX"=>$arr32[12]*$velocityScale,
    "velocityY"=>$arr32[13]*$velocityScale,
    "velocityZ"=>$arr32[14]*$velocityScale,
    "temperature"=>$t*$temperatureScale+25
  );
}

/*
function parseNMEA($sent,$data){

eg4. $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh
1    = UTC of position fix
2    = Data status (V=navigation receiver warning)
@@ -297,37 +358,7 @@ eg3. $GPVTG,t,T,,,s.ss,N,s.ss,K*hh
    0x72, // time d/h [12:8] - day [5:0] - hours
    0x74,// time y/m  [14:8] year (from 2000), [3:0] - month


*/
}
function parseIMU ($arr32){
  $gyroScale=0.013108/65536;       // deg/sec
  $accelScale=0.8192/65536;       // mg
  $angleScale= 0.005493/65536;    //degrees
  $velocityScale=0.0030518/65536; //m/sec
//  $angleScale= 0.005493;    //degrees
//  $velocityScale=0.0030518; //m/sec
  $temperatureScale=0.00565; // C/LSB
  $t=($arr32[15] & 0xffff);
  if ($t>=32768) $t-=65536;
  for ($i=3;$i<15;$i++) if ((($arr32[$i] & 0x80000000)!=0) && ($arr32[$i] > 0)) $arr32[$i]-=0x100000000;
*/

  return array(
    "gyroX"=> $arr32[ 3]*$gyroScale,
    "gyroY"=> $arr32[ 4]*$gyroScale,
    "gyroZ"=> $arr32[ 5]*$gyroScale,
    "accelX"=>$arr32[ 6]*$accelScale,
    "accelY"=>$arr32[ 7]*$accelScale,
    "accelZ"=>$arr32[ 8]*$accelScale,
    "angleX"=>$arr32[ 9]*$angleScale,
    "angleY"=>$arr32[10]*$angleScale,
    "angleZ"=>$arr32[11]*$angleScale,
    "velocityX"=>$arr32[12]*$velocityScale,
    "velocityY"=>$arr32[13]*$velocityScale,
    "velocityZ"=>$arr32[14]*$velocityScale,
    "temperature"=>$t*$temperatureScale+25
//    "temperature"=>$t
// date/time
  );
}
?>