传感器文件格式说明

基本文件格式如下:

Zhongpu Labenius [MAJOR] [MINOR] [SENSOR_TYPE] [DATA_UNIT]
TimeStamp(long: 64bit)  [Value]*[ITEM_NUM]
TimeStamp(long: 64bit)  [Value]*[ITEM_NUM]
...
TimeStamp(long: 64bit)  [Value]*[ITEM_NUM]

其中:

  • MAJOR: 主版本号,当前只有A
  • MINOR:次版本号,当前有1或2,其区别请参考“注意”
  • SENSOR_TYPE:传感器类型
  • DATA_UNIT:单位
  • TimeStamp:时间戳
  • VALUE: 数值
  • ITEM_NUM:一组数据包含的数值个数

当传感器类型不同时,各项内容不同:

Sensor SENSOR_TYPE TimeStamp单位 DATA_UNIT ITEM_NUM Value类型 数据含义
加速度 acceleration ns m/s^2 3 float 32bit X,Y,Z方向的加速度
重力 gravity ns m/s^2 3 float 32bit X,Y,Z方向的重力分量
陀螺仪 gyroscope ns rad/s 3 float 32bit X,Y,Z轴的旋转角速度
线型加速度 linear_acceleration ns m/s^2 3 float 32bit X,Y,Z方向的加速度减去重力分量
压力 pressure ns hPa 1 float 32bit
温度 ambient_temperature ns °C 1 float 32bit
相对湿度 relative_humidity ns % 1 float 32bit
位置 ms UTCTime deg_deg_m 3 double 64bit 纬度、经度和海拔
速度 speed ms UTCTime m/s 1 float 32bit 注意:A2版本后加入,A1版本错误的写成了TLocation

注意:

  1. A1版本文件,当传感器类型为TLocation时,'zhongpu'前面可能有‘00 1F’,且没有单位信息。

  2. 文件头的字符串后面以'\n'结尾,后面立即开始存储二进制数据

  3. 注意数据的大小端问题,AndroidSDK指定为大端,但仍可能与您使用的android设备有关。

示例程序

  • Python
# -*- coding: utf-8 -*-
"""
Hangzhou Zhonpu Inc.
Record file read example code for Vibration Calculator A1&A2 format
Date: 2021-11-24
Author: zgy
"""

import struct
import matplotlib.pyplot as plt
import numpy as np

def read_word(fd):
    word = []
    ch = fd.read(1)
    while ch != b' ' and ch != b'\n':
        word.append(struct.unpack('B', ch)[0])
        ch = fd.read(1)
    return bytes(word).decode()

def sensor_data_num(sensor_type):
    if sensor_type == 'TLocation' or sensor_type == 'acceleration' or sensor_type == 'gravity' or sensor_type == 'gyroscope' or sensor_type == 'linear_acceleration':
        return 3
    return 1

def read_recfile(filename):
    f = open(filename, 'rb')
    zhongpu = read_word(f)
    labgenius = read_word(f)
    major = read_word(f)
    minor = read_word(f)
    sensor_type = read_word(f)

    unit = ''
    if sensor_type != 'TLocation':
        unit = read_word(f)
    elif zhongpu == 'Zhongpu':
        #must be A2
        unit = read_word(f)
    else:
        # TLocation have no zero after string but with 2 bytes for string length at the beginning in Version A1
        zhongpu = zhongpu[2:]


    print(zhongpu, labgenius, major, minor, sensor_type, unit)
    if zhongpu != 'Zhongpu' or labgenius != 'Labenius':
        raise Exception("File is not created by Zhongpu LabGenius")

    # Notice: data endian may be different from devices and data types
    # On my device, int64 and double is big endian, but float is little endian.
    num = sensor_data_num(sensor_type)
    timestamps = []
    values=[]
    dendian = '>'
    dtype = 'f'
    dsize = 4
    if sensor_type == 'TLocation':
        dendian='>'
        dtype = 'd'
        dsize = 8

    try:
        while True:
            tb = f.read(8);
            t = struct.unpack('>Q', tb)[0]
            tds = f.read(dsize * num)
            d = struct.unpack(dendian + dtype*num, tds)
            timestamps.append(t)
            values.append(d)
    except:
        pass

    return sensor_type, unit, np.array(timestamps), np.array(values)


if __name__ == '__main__':
    filename = r"I:/lgsc/2021-11-24 10_02_04/linear_acceleration"
    sensor_type, unit, t, v= read_recfile(filename)
    plt.figure()

    t = (t - t[0])/1E9
    plt.plot(t, v[:,0],t, v[:,1],t, v[:,2])     
    plt.title("linear acceleration")

    filename = r"I:/lgsc/2021-11-24 10_02_04/gyroscope"
    sensor_type, unit, t, v= read_recfile(filename)
    plt.figure()
    t = (t - t[0])/1E9
    plt.plot(t, v[:,0], t, v[:,1], t, v[:,2])
    plt.title("gyroscope")

    filename = r"I:/lgsc/2021-11-24 10_02_04/acceleration"
    sensor_type, unit, t, v= read_recfile(filename)
    plt.figure()
    t = (t - t[0])/1E9
    plt.plot(t, v[:,0], t, v[:,1], t, v[:,2])
    plt.title("acceleration")

    filename = r"I:/lgsc/2021-11-24 10_02_04/gravity"
    sensor_type, unit, t, v= read_recfile(filename)
    plt.figure()
    t = (t - t[0])/1E9
    plt.plot(t, v[:,0], t, v[:,1], t, v[:,2])
    plt.title("gravity")

    filename = r"I:/lgsc/2021-11-24 10_57_59/speed"
    sensor_type, unit, t, v= read_recfile(filename)
    t = (t - t[0])/1E3
    plt.figure()
    plt.plot(t, v[:,0])
    plt.title("speed")

    filename = r"I:/lgsc/2021-11-24 10_02_04/location"
    sensor_type, unit, t, v= read_recfile(filename)
    t = (t - t[0])/1E3
    print(v)
  • C++
/*
Hangzhou Zhonpu Inc.
Record file read example code for Vibration Calculator A1&A2 format
Date: 2021-11-24
Author: zgy
*/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>

struct Value {
    double value[3];
};

bool read_word(FILE* f, char* buffer, int buflen, std::string& holder) {
    char ch;
    int idx = 0;
    int ret = fread(&ch, 1, 1, f);
    while (ret) {
        if (ch != ' ' && ch != '\n' && ch != 0) {
            if (idx < buflen - 1)
                buffer[idx++] = ch;
            else
                return false;
        }
        else{
            break;
        }
        ret = fread(&ch, 1, 1, f);
    }
    buffer[idx] = 0;
    if (idx) {
        holder = buffer;
    }
    return idx > 0;
}

struct DataInfo {
    int byteSize;
    int itemCount;
    double tick;
};

DataInfo GetDataInfo(const char* sensor) {
    if (strcmp(sensor, "acceleration") == 0 ||
        strcmp(sensor, "gravity") == 0 ||
        strcmp(sensor, "gyroscope") == 0 || 
        strcmp(sensor, "linear_acceleration") == 0 ) {
        return { 4, 3, 1E9};
    }
    else if (strcmp(sensor, "TLocation") == 0) {
        return { 8, 3, 1E3 };
    }
    else if (strcmp(sensor, "speed") == 0) {
        return { 4, 1, 1E3 };
    }
    else {
        return { 4, 1, 1E9 };
    }
}

void BigEndianToLittleEndian(char* buffer, int len) {
    char ch = 0;
    for (int i = 0; i < len / 2; ++i) {
        ch = buffer[i];
        buffer[i] = buffer[len - i - 1];
        buffer[len - i - 1] = ch;
    }
}

unsigned _int64 BytesToTick(char* buffer, int len) {
    //big-little
    BigEndianToLittleEndian(buffer, len);
    return *(unsigned _int64*)buffer;
}

double BytesToValue(char* buffer, int len) {
    BigEndianToLittleEndian(buffer, len);
    if (len == 4) {
        return *(float*)buffer;
    }
    else if (len == 8) {
        return *(double*)buffer;
    }
    return 0.0;
}

int read_file(const char* filename, std::vector<double>& times, std::vector<Value>& values) {
    int ret = 0;

    FILE* file = fopen(filename, "rb");
    if (file) {
        const int BUFFER_LEN = 1024;
        char buffer[BUFFER_LEN];

        std::string zp, lg, major, minor, sensor, unit;
        if (read_word(file, buffer, BUFFER_LEN, zp) && 
            read_word(file, buffer, BUFFER_LEN, lg) &&
            read_word(file, buffer, BUFFER_LEN, major) &&
            read_word(file, buffer, BUFFER_LEN, minor) &&
            read_word(file, buffer, BUFFER_LEN, sensor)) {

            bool success = true;
            if (lg != "Labenius" || major != "A" || (minor!="1" && minor!="2")) {
                //header error
                success = false;
            }
            else if (minor == "1" && sensor == "TLocation") {
                //For A1 TLocation
                if (zp != "\x00\x1FZhongpu") {
                    //header error
                    success = false;
                }
            }
            else if(!(zp == "Zhongpu" && read_word(file, buffer, BUFFER_LEN, unit))) {
                //header error
                success = false;
            }

            if (success) {
                DataInfo dataInfo = GetDataInfo(sensor.c_str());

                unsigned _int64 startTick = 0;
                unsigned _int64 curTick = 0;
                double time = 0;
                bool bFirst = true;
                while (true)
                {
                    int rv = fread(buffer, 8, 1, file);
                    if (rv == 1) {
                        curTick = BytesToTick(buffer, 8);
                        if (bFirst) {
                            startTick = curTick;
                            bFirst = false;
                        }
                        time = (curTick - startTick) / dataInfo.tick;
                        Value val;
                        int i = 0;
                        for (i = 0; i < dataInfo.itemCount; ++i) {
                            rv = fread(buffer, dataInfo.byteSize, 1, file);
                            if (rv == 1) {
                                val.value[i] = BytesToValue(buffer, dataInfo.byteSize);
                            }
                            else {
                                break;
                            }
                        }
                        if (i == dataInfo.itemCount) {
                            times.push_back(time);
                            values.push_back(val);
                        }
                        else {
                            break;
                        }
                    }
                    else {
                        break;
                    }
                }
                if (!values.empty()) {
                    ret = dataInfo.itemCount;
                }
            }
        }

        fclose(file);
    }
    return ret;
}

int main()
{
    std::vector<double> time;
    std::vector<Value> values;
    int items = read_file("I:/lgsc/2021-11-24 10_02_04/linear_acceleration", time, values);

    time.clear();
    values.clear();
    items = read_file("I:/lgsc/2021-11-24 10_02_04/location", time, values);

    time.clear();
    values.clear();
    items = read_file("I:/lgsc/2021-11-24 10_02_04/speed", time, values);

    time.clear();
    values.clear();
    items = read_file("I:/lgsc/2021-11-24 10_02_04/gyroscope", time, values);

    return 0;
}

results matching ""

    No results matching ""