-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata_collector.py
More file actions
221 lines (173 loc) · 7.61 KB
/
Copy pathdata_collector.py
File metadata and controls
221 lines (173 loc) · 7.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
"""
IMS-SD データ収集共通モジュール
"""
import time
import csv
from typing import List
from ims_device import ImsDevice # type: ignore
from packet_parser import PacketParser, EngineeringData # type: ignore
def collect_data(device: ImsDevice, packet_parser: PacketParser, frequency: int, matome_pc: int, duration: float) -> List[EngineeringData]:
"""
データ収集
Args:
device: ImsDeviceオブジェクト
packet_parser: PacketParserオブジェクト
frequency: 測定周波数(Hz)
matome_pc: PCまとめ数
duration: 記録時間(秒)
Returns:
List[EngineeringData]: 収集されたデータリスト、エラー時は空リスト
"""
data_buffer: List[EngineeringData] = []
# パケットサイズ計算(1まとめ分)
ch_count = 9 # 9軸センサー
packet_header_size = 4
packet_footer_size = 4
packet_size = ch_count * 2 * matome_pc + 2 * 2 # まとめ先頭に電池残量、温度
total_packet_size = packet_size + packet_header_size + packet_footer_size
# 測定周波数と時間から目標サンプル数を計算
target_samples = int(frequency * duration)
target_packets = target_samples // matome_pc # まとめ数で割る
print(f"データ収集開始: {duration}秒間", flush=True)
print(f" 1まとめパケットサイズ: {total_packet_size}バイト", flush=True)
print(f" 目標サンプル数: {target_samples}", flush=True)
print(f" 目標パケット数: {target_packets}", flush=True)
sample_count = 0
packet_count = 0
# 目標サンプル数分のデータを受信するまでループ
while sample_count < target_samples:
# 1まとめ分のバイト数が受信バッファに貯まるまで待機
while True:
# 受信バイト数チェック
bytes_in_buffer = device.serial.get_bytes_in_buffer()
# 必要バイト数に達したら読み込み
if bytes_in_buffer >= total_packet_size:
# 必要バイト数分を一括読み込み
packet_buffer = device.serial.read_bytes(total_packet_size)
break
time.sleep(0.001) # 1ms待機
# 1まとめ分のパケットを受信完了
packet_count += 1
sample_count += matome_pc # まとめ数分のサンプルを加算
# パケットデータを解析して工学値変換済みデータを取得
engineering_data_list = packet_parser.parse_and_convert(packet_buffer, packet_count)
if engineering_data_list:
# バッファに追加
data_buffer.extend(engineering_data_list)
# 進捗表示(最初のサンプルのデータを表示)
first = engineering_data_list[0]
print(f"パケット#{packet_count:04d}/{target_packets}: "
f"ACC[{first.acc_x:6.3f}, {first.acc_y:6.3f}, {first.acc_z:6.3f}]G "
f"SOC:{first.soc} "
f"温度:{first.temperature:.1f}℃", flush=True)
else:
print(f"パケット#{packet_count:04d}/{target_packets}: 解析エラー")
print(f"データ収集完了: {packet_count}パケット, {sample_count}サンプル", flush=True)
return data_buffer
def save_to_csv(data_buffer: List[EngineeringData], filename: str) -> bool:
"""
CSVファイル保存
Args:
data_buffer: 保存するデータリスト
filename: ファイル名
Returns:
bool: 保存成功時True
"""
try:
with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
# ヘッダー行
writer.writerow([
'Timestamp[s]',
'AccX[G]', 'AccY[G]', 'AccZ[G]',
'GyroX[deg/s]', 'GyroY[deg/s]', 'GyroZ[deg/s]',
'MagX[uT]', 'MagY[uT]', 'MagZ[uT]',
'SOC[%]', 'Temperature[C]'
])
# データ行
for data in data_buffer:
writer.writerow([
data.timestamp,
data.acc_x, data.acc_y, data.acc_z,
data.gyro_x, data.gyro_y, data.gyro_z,
data.mag_x, data.mag_y, data.mag_z,
data.soc, data.temperature
])
print(f"CSVファイル保存完了: {filename}")
return True
except Exception as e:
print(f"CSVファイル保存失敗: {e}")
return False
def setup_measurement_conditions(device: ImsDevice, frequency: int, matome_pc: int, save_to_flash: bool, acc_range: int) -> bool:
"""
測定条件設定
Args:
device: デバイス接続オブジェクト
frequency: 測定周波数(Hz)
matome_pc: PCまとめ数
save_to_flash: 保存先(True: Flash, False: PC)
acc_range: 加速度レンジ(G)
Returns:
bool: 設定成功時True
"""
print("\n=== 測定条件設定 ===")
# 測定周波数設定
if not device.set_frequency(frequency):
return False
# 保存先設定
if not device.set_save_to_flash(save_to_flash):
return False
# 加速度レンジ設定
if not device.set_acc_range(acc_range):
return False
# ジャイロレンジ設定:±4000deg/s(固定)
if not device.set_gyro_range(4000):
return False
# 加速度センサーバンド帯域設定
acc_bw_code = device.get_appropriate_acc_bw(frequency)
if not device.set_acc_bw_icm(acc_bw_code):
return False
# ジャイロセンサーバンド帯域設定
gyro_bw_code = device.get_appropriate_gyro_bw(frequency)
if not device.set_gyro_bw_icm(gyro_bw_code):
return False
# PCまとめ数設定
if not device.set_matome_pc(matome_pc):
return False
print("測定条件設定完了")
return True
def setup_sd_additional_conditions(device: ImsDevice, header: str = "TEST", step_number: int = 1, save_time: int = 10, stop_on_low_battery: bool = True, stop_soc_percent: int = 2, save_interval_hours: int = 1) -> bool:
"""
SD記録用追加設定(setup_measurement_conditions後に使用)
Args:
device: デバイス接続オブジェクト
header: ファイルヘッダ(半角5文字以内)
step_number: ステップナンバー(0-999)
save_time: 保存時間(秒)
stop_on_low_battery: 電池残量で測定停止するか
stop_soc_percent: 測定停止する電池残量(%)
save_interval_hours: SD保存時間間隔(時間)
Returns:
bool: 設定成功時True
"""
print("\n=== SD記録用追加設定 ===")
# ファイルヘッダ設定
if not device.set_file_header(header):
return False
# ステップナンバー設定
if not device.set_step_number(step_number):
return False
# 保存時間設定
if not device.set_save_time(save_time):
return False
# 電池残量での測定停止設定
if not device.set_stop_on_low_battery(stop_on_low_battery):
return False
# 測定停止する電池残量設定
if not device.set_meas_stop_soc(stop_soc_percent):
return False
# SD保存時間間隔設定
if not device.set_save_interval(save_interval_hours):
return False
print("SD記録用追加設定完了")
return True