基本文件格式如下:

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 
#include 
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& 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 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;
}