ここではSSMをつかったプログラミングの一例を示します。


SSMを利用する際のソフトウェア構成

SSMを利用したプログラムは、センサのデータを連続して読み込みSSMにデータを登録するセンサドライバ側と、 センサのデータを任意のタイミングで読み込むユーザプログラム側とにわかれます。

定義が必要なパラメータ

新しいセンサを導入したい場合は、それに対応したセンサドライバを用意する必要があります。 センサドライバを新しく作成する際は下記を決定する必要があります。

  • センサの名前
  • センサのデータ型
  • タイムスタンプの取得方法
  • (センサのプロパティのデータ型)(必要に応じて)

センサの名前はユーザプログラム側からセンサを呼び出す際に必要です。 またセンサのデータ型は、ドライバ側とそのセンサを利用するソフトウェアで共有する必要があるので、 ヘッダファイルとして提供することが必要です。

基本的な起動順番

ユーザプログラム側の手順としては、

  • initSSM()で初期化し、
  • openSSM(センサ名, ID, 0)で利用するセンサをオープン、
  • readSSMやreadSSM_timeでデータを読み込みます。

また、SSM特有の概念として、センサID(SSM_sid型)と時刻ID(int型)があります。 センサIDはファイルポインタのようなもので、センサにアクセスする際に必要です。 これはopenSSMやcreateSSMにより得られます。 時刻IDは、センサデータ中の通し番号で、データが入力される毎にインクリメントされます。

以降に利用できる関数とドライバおよびユーザ側プログラムのサンプルを載せます。


関数

初期化

  • int initSSM(void)

登録・オープン

  • SSM_sid createSSM(char* センサ名, int センサのID, int データのサイズ, double 記憶する期間, double 記録するおおよその周期) 返り値:センサID
  • SSM_sid openSSM(char* センサ名, int センサのID, 0) 返り値:センサID

書き込み・読み込み(共有メモリアクセスのみ)

  • int writeSSM(SSM_sid センサのSID, char* 書き込むデータのアドレス, double 計測時刻);
  • int readSSM(SSM_sid センサのSID, char* 読み込むデータのアドレス, double* 計測時刻を記録する変数のアドレス, int 時刻ID) 返り値:時刻ID
  • int readSSM_time(SSM_sid センサのSID, char* 読み込むデータのアドレス, double 指定時刻, double* 計測時刻を記録する変数のアドレス) 返り値:時刻ID

プロパティの読み書き

  • set_propertySSM(char* センサ名, int センサのID, char* 登録するデータのアドレス, int 登録するデータの大きさ);
  • get_propertySSM(char* センサ名, int センサのID, char* 取得するデータのアドレス);

データを書き込む側(センサドライバ側)

センサのデータをSSMに書き込む例について示します。 ここでは、SensorAというセンサをSSMに適用する例を示します。

まず、SensorAの登録名を、

sensor_A
と定義します。 名前は任意ですが、ログ取り等の際にも利用しますので、あまり長くない方が良いでしょう。

つぎに、書き込みたいデータの型をSensor_A.hに次のように定義したとします。

 Sensor_A.h
 
 #ifndef __SENSOR_A__
 #define __SENSOR_A__ 
 
 typedef struct{
   double a;
   double b;
   int    c;
 }SensorA;
 
 #endif 
この際、SensorAのデータを読み込み、SSMに書き込むプログラムは次のようになります。
 SensorA_driver.c
 
 #include<ssm_common.h>
 #include<Sensor_A.h>
 #include<unistd.h>
 
//センサデータを読み込むかわりに適当なデータを生成
void receive_sensorA(SensorA *data, double *time){
 static double a,b;
 static int c;
  a+=0.1;
  b+=0.01;
  c++;
  data->a = a;
  data->b = b;
  data->c = c;
  *time = gettimeSSM();
  usleep(100000);
}

int main(int argc, char *argv[]){
SensorA sens_data;
double measured_time;
SSM_sid sensA_sid; 

  initSSM();
      //名前をsensor_Aで、IDを0で、0.1秒おきに来るデータを10秒間保持するよう領域を確保。 
  sensA_sid = createSSM_time("sensor_A", 0, sizeof(SensorA), 10, 0.1);

  while(1){
       //SensorAのデータを何かしらの方法(例えばシリアル通信)で取得し、頑張って観測時刻を推定する関数。
   receive_sensorA(&sens_data, &measured_time);
       //SSMへのデータの書き込み。
   writeSSM(sensA_sid, (char*)&sens_data, measured_time);
  }
}  


データを読み込む側(ユーザプログラム側)

ここではセンサデータを利用するユーザプログラム側のプログラム例について示します。

SSMではセンサの情報を様々な方法でアクセスできます。 ここではつぎの4種類のプログラム例を示します。

  • 最新のデータへのアクセス
  • 全てのデータへのアクセス
  • 過去のデータへのアクセス
  • 複数のセンサの同期

最新のデータへのアクセス

最新のデータにアクセスするには、readSSMの最後の引数の時刻IDに-1を入れることで可能です。

1秒おきに最新のSensorAのデータを読み込むには次の様にします。

SensorA_print.c

#include<ssm_common.h>
#include<Sensor_A.h>
#include<unistd.h>
#include<stdio.h>

int main(int argc, char *argv[]){
SensorA sens_data;
double measured_time;
SSM_sid sensA_sid;

 initSSM();
 sensA_sid = openSSM("sensor_A", 0, 0);
 
 while(1){
   readSSM(sensA_sid, (char*)&sens_data, &measured_time, -1);
   printf("time=%f a=%f b=%f c=%d\n",measured_time, sens_data.a, sens_data.b, sens_data.c);
   sleep(1);
 }
}
この場合、読み込む周期がセンサの更新周期が早ければ全てのデータを利用するとは限りません。

データを順番に読み込む場合

オドメトリなどを独自で計算したい場合などは得られたセンサデータ全てを利用したくなります。 ここでは時刻IDを用いることで、得られたSensorAのデータを順番に読み込む例について示します。

SensorA_print2.c

#include<ssm_common.h>
#include<Sensor_A.h>
#include<unistd.h>
#include<stdio.h>

int main(int argc, char *argv[]){
SensorA sens_data;
double measured_time;
SSM_sid sensA_sid;
int tid;

 initSSM();
 sensA_sid = openSSM("sensor_A", 0, 0);
     //最新のデータのTIDを取得する。
 tid = readSSM(sensA_sid, (char*)&sens_data, &measured_time, -1);
 while(1){
   while(readSSM(sensA_sid, (char*)&sens_data, &measured_time, tid) <= 0){
     usleep(20000);  //データがまだきていなければちょっと待ってみる。
   }
   printf("time=%f tid=%d a=%f b=%f c=%d\n",measured_time, tid, sens_data.a, sens_data.b, sens_data.c);
   tid++;
 }




}

readSSMは指定したTIDのセンサデータがなければ0以下の値を返します。

過去のデータへのアクセス

時刻IDもしくは時刻を指定することで、過去のデータを読み込む事ができます。

SensorA_print3.c

#include<ssm_common.h>
#include<Sensor_A.h>
#include<unistd.h>
#include<stdio.h>

int main(int argc, char *argv[]){
SensorA sens_data;
double measured_time;
SSM_sid sensA_sid;
int tid;
double now_time;

 initSSM();
 sensA_sid = openSSM("sensor_A", 0, 0);

 while(1){
   now_time = gettimeSSM();  //現在時刻を取得 

       //現在時刻の1秒前のデータを取得
   tid = readSSM_time(sensA_sid, (char*)&sens_data, now_time-1, &measured_time);
   printf("time=%f tid=%d a=%f b=%f c=%d\n",measured_time, tid, sens_data.a, sens_data.b, sens_data.c);
       //その一つ後のデータを取得
   tid++;
   readSSM(sensA_sid, (char*)&sens_data, &measured_time, tid);
   printf("time=%f tid=%d a=%f b=%f c=%d\n\n",measured_time, tid, sens_data.a,  sens_data.b, sens_data.c);
   
   sleep(1); 
 }
}

異なるセンサの同時刻のデータの取得

時刻指定で読み込むことで、異なるセンサ間での同時刻のデータを読み込む事ができます。

SensorAB_print.c

#include<ssm_common.h>
#include<unistd.h>
#include<stdio.h>
#include<Sensor_A.h>
#include<Sensor_B.h> 

int main(int argc, char *argv[]){
SensorA sens_dataA;
SensorB sens_dataB;
double measured_time;
SSM_sid sensA_sid, sensB_sid;
int tid;
double time;

 initSSM();
 
 sensA_sid = openSSM("sensor_A", 0, 0);
 sensB_sid = openSSM("sensor_B", 0, 0);
 
 while(1){
       //センサAの最新データを取得
   tid = readSSM(sensA_sid, (char*)&sens_dataA, &measured_time, -1);

       //同時刻のデータ(もっとも近く、過去のもの)を取得
   readSSM_time(sensB_sid, (char*)&sens_dataB, measured_time, &time);
   printf("timeA=%f timeB=%f A.a=%f B.a=%f",measured_time,time,sens_dataA.a, sens_dataB.a);   
   sleep(1); 
 }
}


センサの静的情報(プロパティ)の登録・読み込み

6/30付けでセンサの静的情報記録機能が追加されました。

センサの位置やステップ角、車輪径等センサ固有の情報を記録できます。

関数

  set_propertySSM(char* センサ名, int センサのID, char* 登録するデータのアドレス, int 登録するデータの大きさ);
  get_propertySSM(char* センサ名, int センサのID, char* 取得するデータのアドレス);

センサプロパティの記録

型を決める。例えば、

typedef struct{ 
  double a;
  char name[10];
}SensorA_Property;
等。で、登録する。
SensorA_Property sensA_property;

 sensA_property.a = 100;
 sprintf(sensA_property.name, "SensorA");
 set_propertySSM("sensor_A", 0, &sensA_property, sizeof(SensorA_Property));

センサプロパティの取得

SensorA_Property sensA_property;

 get_propertySSM("sensor_A", 0, &sensA_property);
 printf("%s %f\n",sensA_property.name, sensA_property.a);