基本文件格式如下:
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 |
注意:
a1版本文件,当传感器类型为tlocation时,'zhongpu'前面可能有‘00 1f’,且没有单位信息。
文件头的字符串后面以'\n'结尾,后面立即开始存储二进制数据
注意数据的大小端问题,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;
}