kurario bloghttps://kurario-blog.comてんぱエンジニアが道楽の日々を綴ります。Sat, 18 Feb 2023 01:59:19 +0000jahourly1https://kurario-blog.com/wp-content/uploads/2022/12/cropped-スクリーンショット-2022-12-31-22.27.34-32x32.pngkurario bloghttps://kurario-blog.com3232 レンタルカートの耐久レースで走行ログを取ってみた#2https://kurario-blog.com/?p=166https://kurario-blog.com/?p=166#respondSun, 12 Feb 2023 13:27:15 +0000https://kurario-blog.com/?p=166

DroggerRWPで位置情報を取得し、Andoroidのスマホアプリ「DroggerGPS」を使ってスマホにログを取る。 ログ取得のための設定は公式HPの解説がわかりやすいのでそちらをご参照いただくとして、この記事では ... ]]>

この記事の内容

  • (前の記事)計測のためのハードウェアの準備
  • (この記事)計測と走行データの分析

計測

DroggerRWPで位置情報を取得し、Andoroidのスマホアプリ「DroggerGPS」を使ってスマホにログを取る。

ログ取得のための設定は公式HPの解説がわかりやすいのでそちらをご参照いただくとして、この記事では私がどのように設定したか簡単に記載しておく。

RTK基準局の設定

高精度位置情報を取得するためのRTKという技術は、普通のGPSの衛星とデバイス間の通信に加え、地上の基準局との通信が必要になる。そこで、まず必要なのが基準局の設定である。今回は趣味用途なので市販の位置情報提供サービスは使わずに、無料で基準局の情報を発信してくださっている方のご厚意にあやかる形にした。無料の基準局の情報がまとめてあるページがこちらである。

今回は三重県桑名市のレインボースポーツで走行した。一般的に基準局は半径10km以内にあるといいとされているが、近くに無料の基準局はなかったので、今回は海の向こうの東浦の基準局を使わせていただいた。設定時の写真を貼っておく。

ログ取得の設定

ログは後で解析しやすいように馴染みのあるCSVで出力することとした。またログの開始/停止の操作忘れ防止のためにスピードフィルタを設定し閾値を5km/hとすることで、動き出したら自動でログが始まり、低速になれば自動でログが停止するように設定しておいた。(実際に使ってみて、この機能はとても便利だなって感じました。)こちらも設定時の画面を貼っておく。

ログのアップロード

取得したCSVデータはアプリからそのままクラウドへ送信することができる。私はgoogleドライブにログ用のフォルダを作ってそこに保存するようにしている。一旦設定してしまえば、ログの送信は一瞬で完了する。(これもとっても便利だなって感じてます。)操作はとても簡単で送信したいログを選んで、右上のおしゃれなボタンを押して、送信したい場所を選択するだけだ。

走行データの分析

Googleドライブ上に保存されたログを自分のPCにダウンロードして分析を開始する。市販のソフトを使った解析もできないことはないと思うが今回は自分でやってみたかったので、Pythonをつかって分析してみた。

①データの分割(1ラップごと)

耐久レースでは1スティント20〜30分走行する。そのデータを眺めてもカオスなだけなので、まずはデータを1ラップごとに分割する。分割方法はいろいろあると思うが、コントロールラインの座標を設定し、その座標の近くを通った時に1ラップとカウントするようにプログラムを書いた。具体的にはコントロールラインの座標とログデータのある時点での座標の距離を求め、その距離がある閾値以下の時に1周とカウントする。

②v-tグラフのプロット

サーキット走行を経験された方ならわかる方も多いと思うが、横軸に時間、縦軸に速度をとったグラフ(v-tグラフ)はタイムアップのために非常に強力なデータとなる。(反省すべき点が多く見えるので、落ち込むことにもなるが。。)今回はラップ数を選択して、そのラップのv-tグラフを出力できるように書いてみた。

③位置情報のプロット

今回のこだわりポイントである位置情報のプロット。ただプロットするだけだと面白くないので、速度に合わせて色を変えてプロットしてみた。走行ラインが綺麗にプロットされていることがわかる。精度の良いGPSを使っているので、走行ラインの議論にも使えるところがいいところだ。

import gpxpy
import matplotlib.pyplot as plt
%matplotlib inline
import folium
from folium.plugins import HeatMap
import pandas as pd
import numpy as np
import scipy.signal as sg
import datetime
import matplotlib.colors as cl
filename = '2021-12-05_13-08-17.csv'
data = pd.read_csv(filename)
data.time = pd.to_datetime(data.time)
ps = data.loc[:,['latitude','longitude']]
lat = data.latitude
lon = data.longitude
sp = data.speed
#コントロールラインの座標設定
control_line = [35.049354,136.616640]
norm = cl.Normalize(vmin=20, vmax=80)
henkan = plt.get_cmap('jet')
#時間差計算関数
def time_diff(time): time_s = time[0] diff = [] for i in range(len(time)): diff.append((time[i] - time_s).total_seconds()) return diff
#コントロールラインとの差分計算
def pos_diff(position): pos_d = [] for k in range(len(position)): dpos = position[k,:] - np.array(control_line) pos_d.append(np.linalg.norm(dpos, ord=2)) return pos_d
#走行ライン計算関数
def plotlap(run_no): id1 = minid[0,run_no] id2 = minid[0,run_no+1] lat_lap = lat[id1:id2] lon_lap = lon[id1:id2] v_lap = sp[id1:id2]*3.6 V_lap = np.round(v_lap, decimals=0) pts = np.array([lat_lap,lon_lap]).T # 基準地点と初期の倍率を指定し、地図を作成する map1 = folium.Map(location=control_line, tiles='https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg', attr='レインボースポーツ 空中写真', zoom_start=20) # 基準地点にマーカーを設置する marker = folium.Marker(control_line, popup='home') map1.add_child(marker) for i in range(len(V_lap)): p = folium.CircleMarker(location=tuple(pts[i,:]), radius=1, popup=None, tooltip=None, color=cl.to_hex(henkan(norm(V_lap[id1+i])))) map1.add_child(p) return map1
#v-tグラフ描写関数
def vt_graph(run_no): t_lap = t_diff[minid[0,run_no]:minid[0,run_no+1]] - t_diff[minid[0,run_no]] v_lap = sp[minid[0,run_no]:minid[0,run_no+1]] return plt.plot(t_lap,v_lap*3.6)
#ラップタイム計算関数
def lap_time(minid): lptm = [] for i in range(len(minid.T)-1): ti = t_diff[minid[0,i+1]] - t_diff[minid[0,i]] lptm.append(ti) return plt.plot(lptm,'-o')
t = data.time
t_diff = np.array(time_diff(t))
#①データの分割(1ラップごと)
pos = np.array([lat, lon]).T
p_diff = np.array(pos_diff(pos))
minid = sg.argrelmin(p_diff, order=500) #最小値
minid = np.array(minid)
plt.plot(t_diff, p_diff, label='difference', c='c')
plt.plot(t_diff[minid],p_diff[minid],'ro',label='control_line')
plt.xlabel('time (s)')
#plt.legend(loc=0)
plt.show()
lap_time(minid)
plt.xlabel('Laps')
plt.ylabel('Laptime(s)')
plt.grid()
plt.ylim([70,80])
#②v-tグラフのプロット
run_no = 9
lap_time = t_diff[minid[0,run_no+1]] - t_diff[minid[0,run_no]]
print(lap_time)
vt_graph(run_no)
plt.title(lap_time)
plt.xlabel('time(s)')
plt.ylabel('velocity(km/h)')
plt.grid()
plt.ylim([20,80])
plt.xlim([0,80])
#③位置情報のプロット
plotlap(run_no)

おわりに

今回はレンタルカートの草レースで走行ログを取る方法について解説した。レースだけでなく練習走行の時間にも活用できる。ヘルメットとポーチを友人に渡すだけで簡単にログが取れるので、仲間内でログを比較してレベルアップに繋げるのにもおすすめだ。

]]>
https://kurario-blog.com/?feed=rss2&p=1660
レンタルカートの耐久レースで走行ログを取ってみた#1https://kurario-blog.com/?p=74https://kurario-blog.com/?p=74#respondSun, 01 Jan 2023 03:33:00 +0000https://kurario-blog.com/?p=74

クルマの運転が好きな私は公道での運転だけでは飽き足らず、サーキットで全開走行したい欲求に駆られることがある。学生の頃は自分の車をいじってサーキットに行くことはしばしばあったが、社会人になった今、日々のメンテナンスや部品の ... ]]>

この記事の内容

  • (この記事)計測のためのハードウェアの準備
  • (次の記事)計測と走行データの分析

なぜ取り組んだのか?

クルマの運転が好きな私は公道での運転だけでは飽き足らず、サーキットで全開走行したい欲求に駆られることがある。学生の頃は自分の車をいじってサーキットに行くことはしばしばあったが、社会人になった今、日々のメンテナンスや部品の置き場所等を考えるとどうしてもめんどくささが勝ってしまっていた。そこで巡りあったのがレンタルカートである。外からみると速さは感じられず、「それって楽しいの?」と言った感じではあるが、実際乗ってみると実に楽しい。帰りの足のことを考えなくてもいいので限界にもチャレンジしやすい。レンタルだからこそメンテナンスも不要というところもいい。そんな点に惹かれて仲間内でレンタルカートの耐久レース(誰でも参加できる草レース)に参加するようになった。

一方、レンタルカートに慣れてきた頃に直面するのがタイムが伸びないという問題だ。自分では乗れているつもりなのに仲間に対して自分だけ遅い。仲間に教えてもらうこともできるがイマイチぴんとこないこともある。そこで思いついたのが、走行ログを取得して比較すればその差が明らかになるのではないか、ということだ。

耐久レースで走行ログを取得する時の前提

耐久レースで走行ログを取得する場合は、自分の車の場合とは少し前提が異なる。レースの規定にもよるが、耐久レースの場合はドライバー交代の回数が決められており、その際にカートも交換する。カート交換時にロガーもセットし直せるほど余裕な時間はないので、自分の車のようにロガーはカートに固定しておくことができない。

そこで少々苦しまぎれではあるが、人の体にロガーを固定する方法を考えた。そうすればカート交代時にもスムーズに済む。固定位置はアクションカムがよくつけられているヘルメットが妥当だろう。

ログ取得上の個人的なこだわり

巷にはさまざまなGPSロガーが販売されており、最近ではスマホのGPSでも簡単なログ取得はできる。一方、一般的なGPSの測位精度は500mm~5000mmとも言われており、精度良く計測できたとしても普通車のタイヤ2本分はずれてしまう可能性がある。ここは個人的な思いであるが、このような測位精度で「走行ラインが〜〜」とか「ブレーキのポイントが〜〜」とか議論しても後で虚しくなりそうなのでそれは避けたい。

そこで目をつけたのがRTK-GPSである。普通のGPSとは違い、衛星から情報だけではなく地上の基準局からも情報をもらうことによって精度の高い測位(誤差1cm~5cm)を可能にしている。私が学生の頃はどれも3桁万円くらいしていて決して手を出せるものではなかったが、購入当時の2021年には10万円ほどで売られていた。学生の頃からするとバーゲンプライスな気がしてしまって、気がついた時にはポチっていた。後悔はしていない。

ということで、個人的なこだわりとして走行ログ取得にはRTK-GPSを利用する。


一般的なGPSとRTK-GPSの違いは下記サイトでわかりやすく説明されている。

計測のためのハードウェア

前置きが長くなってしまったが、こちらが計測に必要なハードウェアである。

  • Drogger RWP(RTK-GPS受信機のセット)
  • ヘルメット
  • GoPro用ヘルメットマウント
  • Gopro用1/4インチねじ変換アダプタ
  • ねじ径変換アダプタ
  • Androidスマホ
  • スマホポーチ

購入品のリンクを掲載しておく。*ヘルメットはホームセンターで購入、Androidスマホは友人からゆずってもらったものなのでリンクなし。

構成としては、ヘルメットにRTK-GPS受信機であるDrogger RWPをマウント。Drogger RWPはAndroidスマホにBluetoothでログを送る機能が付いているため、体にくくりつけたスマホポーチにスマホを入れておくだけである。配線が一切ないところがおしゃれなポイントだ。

これで計測のためのハードウェアの準備は整った。次回は計測と走行ログの分析について紹介する。

]]>
https://kurario-blog.com/?feed=rss2&p=740
DriftBoxのバイナリデータを読み解いた#2https://kurario-blog.com/?p=36https://kurario-blog.com/?p=36#respondSat, 31 Dec 2022 08:16:42 +0000https://kurario-blog.com/?p=36

前記事に書いた、VSCodeのHexEditorで確認すると改行を示す「0D 0A」がいくつか並んでいる。 そこで読み込みにはMATLABのfgetlを用いて1行ずつ読み込んでいき、ヘッダー部分の行数分で終了するプログラ ... ]]>

この記事の内容

  • (前の記事で紹介)VSCodeのHexEditorを利用したバイナリデータの概要把握
  • (この記事で紹介)MATLABでバイナリデータからtable形式への変換

MATLABを使ったデータの読みこみ

①ヘッダー部分の読み込み

前記事に書いた、VSCodeのHexEditorで確認すると改行を示す「0D 0A」がいくつか並んでいる。

そこで読み込みにはMATLABのfgetlを用いて1行ずつ読み込んでいき、ヘッダー部分の行数分で終了するプログラムを書いた。下記のように少し工夫することでtableのヘッダー風に読み込むことができた。

clear all; clc;
filename = 'DBOX_004.DBN';
%% バイナリファイルオープン
fid = fopen(filename,'r');
% ヘッダー部分読み込み
m = 1;n = 1;
for i = 1:40 a = fgetl(fid); if isempty(a) == 1 m = m+1; n = 1; else n = n+1; end A{m,n} = a;
end

Aという変数はセル配列になり、中身このようになる。

これで、ヘッダー部分を読み込むことができたようだ。

②数値データ部分の読み込み

ヘッダーに書いてあるSAT(1)という表記だが、SATは受信している衛星の数という意味で、()内は数値データのByte数を示していると想定している。衛星は1Byte,時間は3Byte,,,というように一回の記録で何Byte分あるのか確かめてみると、36Byteあるようだ。

データの形は既に想定できているので、MATLABのfreadを使って数値データの部分をいっきに読み込み、後から形を整えるようにプログラムしてみた。

freadで読み込み、reshapeで整え、衛生が受信できていない不要なデータ行を削除後、各データのByte数分を16進数の形で取り出す。その後、10進数に戻して必要な乗数を掛けている。この辺りの処理は冗長な感じが否めないので、この道のプロならおそらくもっといい方法を知っているのではないかと想像する。

kurario-tec
kurario-tec

必要な乗数はどこにも書いてなかったので、WindowsPCを借りて標準解析ツールより出力したCSVデータと見比べることで確かめました。本末転倒感。笑

num_byte = 36;
% データ部分読み込み
B = uint8(fread(fid));
% ベクトルを行列に変換
nd = length(B);
num_data = length(B)/num_byte;
C = reshape(B,[num_byte,num_data])';
% 衛星を受信できてないデータ行の取得
idx_nonGPS = C(:,2) = 1 | C(:,2) >= 15;
% tableに変換
D = array2table(C);
% 衛星を受信できてないデータの削除
D(idx_nonGPS,:) = [];
% 16進数で必要なバイト数分選択
time = hex2dec([dec2hex(D.C3),dec2hex(D.C3),dec2hex(D.C3)])*10;
lat = [dec2hex(D.C6),dec2hex(D.C7),dec2hex(D.C8),dec2hex(D.C9)];
lon = [dec2hex(D.C10),dec2hex(D.C11),dec2hex(D.C12),dec2hex(D.C13)];
vel = [dec2hex(D.C14),dec2hex(D.C15),dec2hex(D.C16)];
heading = [dec2hex(D.C17),dec2hex(D.C18)];
height = [dec2hex(D.C19),dec2hex(D.C20),dec2hex(D.C21),dec2hex(D.C22)];
vert_sp = [dec2hex(D.C23),dec2hex(D.C24)];
yaw_1 = [dec2hex(D.C25),dec2hex(D.C26)];
yaw_2 = [dec2hex(D.C27),dec2hex(D.C28)];
yaw_calc = [dec2hex(D.C29),dec2hex(D.C30)];
slip = [dec2hex(D.C31),dec2hex(D.C32)];
checksum = [dec2hex(D.C33),dec2hex(D.C34)];
% 10進数への変換と、データへの単位変換
E.sat = D.C2;
E.time = duration(milliseconds(time)+hours(9),'Format','hh:mm:ss.SSS');
E.lat_10 = hex2dec(lat)/60*10^-5;
E.lon_10 = hex2dec(lon)/60*10^-5;
E.vel_kmph = hex2dec(vel)*10^-2;
E.heading_deg = hex2dec(heading)*10^-2;
E.height_m = hex2dec(height)*10^-2;
E.vert_sp_mps = hex2dec(int16(vert_sp))*10^-2;
E.vert_sp_mps(E.vert_sp_mps > 600) = E.vert_sp_mps(E.vert_sp_mps > 600,:) - 655.35;
E.vert_sp_mps = E.vert_sp_mps*3.6;
E.yaw_2_degps = hex2dec(yaw_1)*10^-2;
E.yaw_1_degps = hex2dec(yaw_2)*10^-2;
E.yaw_calc = hex2dec(yaw_calc)*10^-2;
E.slip_deg = hex2dec(slip);
E.checksum = hex2dec(checksum);
% tableへ変換
E = struct2table(E);

以上、DriftBoxのバイナリデータを読み解けた。

MATLABのgeoscatterを使って走行軌跡を確認すると、しっかり当時走行した場所を示していた。これで自分のMacBookAirでもDriftBoxのデータを解析できるようになった。

]]>
https://kurario-blog.com/?feed=rss2&p=360
DriftBoxのバイナリデータを読み解いた#1https://kurario-blog.com/?p=20https://kurario-blog.com/?p=20#respondFri, 30 Dec 2022 15:09:17 +0000https://kurario-blog.com/?p=20

車両運動のデータロガーとしてRaceLogic社のDriftBoxを愛用中。 取得したデータは.DBNという拡張子で保存され、通常ならば専用の解析ツールを使ってデータを確認することができるのだが、残念なことに解析ツールは ... ]]>

この記事の内容

  • (この記事で紹介)VSCodeのHexEditorを利用したバイナリデータの概要把握
  • (次の記事で紹介)MATLABでバイナリデータからtable形式への変換

なぜ取り組んだのか?

車両運動のデータロガーとしてRaceLogic社のDriftBoxを愛用中。

取得したデータは.DBNという拡張子で保存され、通常ならば専用の解析ツールを使ってデータを確認することができるのだが、残念なことに解析ツールは私が使っているMacbookAir(M1)には非対応。せっかく取得したデータが見れないのは悲しい。

少し調べてみると公式サイトには.DBNはバイナリ形式であるとの記載を発見。バイナリ形式は今まで扱ったことがなかったが、「MATLABならできるはず。。」そんな思いで取り組んでみた。

バイナリデータを扱う専門の方ならもっといい方法でやってるのかもしれないが、そういった記事が見当たらなかったので誰かの参考になればと思って投稿しておく。

バイナリデータの構造把握

最初はMATLABで全て完結させようと取り組んだが、結局いい方法が見つけられなかった。

さまざまな拡張機能が充実している「VSCodeならできるはず。。」と思って調べてみると、Hex Editorというものを発見。

検索したら出てきた下記記事を参考にさせていただき、早速VScodeに拡張機能をインストールし実行。

バイナリファイルの編集?それ、VS Codeで出来るよ。 | 底辺プログラマーの戯言(新しいタブで開く)

設定をいじりながらデータを確認している画面がこちら。

バイナリ形式のファイルが16進数表記に表され、テキストにも変換されている。

最初はこれも見ても正直よくわからなかったが、この画面をしばらく眺めてデータの概要として想像したのは下記4点。

  • データの453バイト目まではヘッダーであること。
  • ヘッダーの文字コードはUTF-8であること。
  • 各ヘッダーの()内の数字は、おそらく取得データのバイト数を示していること。
  • 取得データの文字コードはUTF−8ではないこと。

これでデータの概要はある程度掴むことができた。

次回は想像したデータの概要があっているかを確認しつつ、MATLABを使ってtable形式に変換し、データを分析しやすい形にしていく。

DriftBoxのバイナリデータを読み解いた#2]]>
https://kurario-blog.com/?feed=rss2&p=200