これまでのGT7データ解析の取り組みをおさらい
GitHubにあるGT7Dashboardを使用して、グランツーリスモ7の走行データ(テレメトリーデータ)を取得する方法を紹介しました。さらに保存したデータを解析するC#クラスを作成しました。
関連ページのリンク
- GT7 Dashboardでテレメトリーデータを取得
- GT7DashboardのJSONデータをC#で解析してみた
- 自作ソフトでGT7Dashboardの色々なデータをトレースした←この記事
- GT7DashBoardのデータで車両解析する
これまでは速度のデータしか表示していませんでしたが、他のデータを表示してみたいと思います。
鈴鹿サーキット × FT-1 VGT Gr.3
鈴鹿サーキット × GT-RニスモGT3
鈴鹿サーキット × RC F GT3
一部ソースコードの紹介
データの読み込み、表示クラスとチャート表示フォームクラスを紹介します。
アプリケーションの構成
メインクラスで表示するデータを選択してからフォームクラスインスタンスを作成、表示します。その後、データ読み込み、表示クラスでjsonデータをロードします。データロード時にフォームクラスのインスタンスにデータ参照を追加することでデータを表示できます。チャート表示フォームクラスにはデータ表示の時間軸を設定するメソッド"SetDispArea"があるので、タイマー等で表示範囲を変更することでデータをトレースできます。
速度データの読み込み、表示クラス
一例として速度データのクラスを紹介しますが、他のデータでも基本的なつくりは同じです。
using JsonTool; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; namespace GT7DashboardDataAnalyzer { public class VehicleSpeedGraph { public VehicleSpeedGraph(Chart chart) { chart.ChartAreas.Clear(); chart.Series.Clear(); chart.Legends.Clear(); chart.Dock = DockStyle.Fill;//フォームいっぱいに表示 chart.ChartAreas.Add(new ChartArea("chartArea"));//グラフエリア } public bool AddData(GT7DashboardData gt7DashboardData, Chart chart) { bool result = false; //凡例を作成 //chart.Legends.Add(new Legend(gt7DashboardData.Title));//凡例 //データ系列を作成 Series series = new Series(); //折れ線グラフを選択 series.ChartType = SeriesChartType.Line; for (int i = 0; i < gt7DashboardData.DataTime.Count(); i++) { series.Points.AddXY(gt7DashboardData.DataTime[i], gt7DashboardData.DataSpeed[i]); } chart.Series.Add(series); return result; } } }
チャート表示フォームクラス
一例として2つのチャートを表示するクラスです。
using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; using JsonTool; namespace GT7DashboardDataAnalyzer { public partial class ChartForm2 : Form { private List<Chart> charts; private List<ChartDataType> chartTypes { get; set; } private readonly int CHART_COUNT; private double dispAreaTn1 { get; set; } private double dispAreaTn2 { get; set; } private StripLine stripLine { get; set; } private VehicleSpeedGraph vehicleSpeedGraph { get; set; } private RpmGraph rpmGraph { get; set; } private ThrottleGraph throttleGraph { get; set; } private BrakingGraph brakingGraph { get; set; } private GearGraph gearGraph { get; set; } private TiresGraph tiresGraph { get; set; } private BoostGraph boostGraph { get; set; } public enum ChartDataType { Throttle, Braking, Speed, Rpm, Gear, Tires, Position, Boost, RotationYaw, AbsoluteYawRatePerSecond } public ChartForm2(List<ChartDataType> types) { InitializeComponent(); CHART_COUNT = 2; //InitChartDataType = new ChartDataType[CHART_COUNT]; //InitChartDataType[0] = ChartDataType.Speed; //InitChartDataType[1] = ChartDataType.Rpm; chartTypes = types; if(types.Count() == CHART_COUNT) { charts = new List<Chart>(); charts.Add(chart1); charts.Add(chart2); } } private void ChartForm2_Load(object sender, EventArgs e) { for(int i = 0; i < CHART_COUNT; i++) { //this.Text = Enum.GetName(typeof(ChartDataType), chartTypes[i]); switch (chartTypes[i]) { case ChartDataType.Throttle: InitThrottleData(i); break; case ChartDataType.Braking: InitBrakingData(i); break; case ChartDataType.Speed: InitSpeedData(i); break; case ChartDataType.Rpm: InitRpmData(i); break; case ChartDataType.Gear: InitGearData(i); break; case ChartDataType.Tires: InitTiresData(i); break; case ChartDataType.Position: InitPositionData(i); break; case ChartDataType.Boost: InitBoostData(i); break; case ChartDataType.RotationYaw: InitRotationYawData(i); break; case ChartDataType.AbsoluteYawRatePerSecond: InitAbsoluteYawRatePerSecond(i); break; default: break; } } } private void InitThrottleData(int chartNum) { throttleGraph = new ThrottleGraph(charts[chartNum]); SetChartAxisXTitle(chartNum, 0, "Time[s]"); SetChartAxisYTitle(chartNum, 0, "Throttle[%]"); InitStripLine(chartNum); } private void InitBrakingData(int chartNum) { brakingGraph = new BrakingGraph(charts[chartNum]); SetChartAxisXTitle(chartNum, 0, "Time[s]"); SetChartAxisYTitle(chartNum, 0, "Braking[%]"); InitStripLine(chartNum); } private void InitSpeedData(int chartNum) { vehicleSpeedGraph = new VehicleSpeedGraph(charts[chartNum]); SetChartAxisXTitle(chartNum, 0, "Time[s]"); SetChartAxisYTitle(chartNum, 0, "Speed[km/h]"); InitStripLine(chartNum); } private void InitRpmData(int chartNum) { rpmGraph = new RpmGraph(charts[chartNum]); SetChartAxisXTitle(chartNum, 0, "Time[s]"); SetChartAxisYTitle(chartNum, 0, "rpm"); InitStripLine(chartNum); } private void InitGearData(int chartNum) { gearGraph = new GearGraph(charts[chartNum]); SetChartAxisXTitle(chartNum, 0, "Time[s]"); SetChartAxisYTitle(chartNum, 0, "Gear"); InitStripLine(chartNum); } private void InitTiresData(int chartNum) { tiresGraph = new TiresGraph(charts[chartNum]); SetChartAxisXTitle(chartNum, 0, "Time[s]"); SetChartAxisYTitle(chartNum, 0, "Tires"); InitStripLine(chartNum); } private void InitPositionData(int chartNum) { } private void InitBoostData(int chartNum) { boostGraph = new BoostGraph(charts[chartNum]); SetChartAxisXTitle(chartNum, 0, "Time[s]"); SetChartAxisYTitle(chartNum, 0, "Boost"); InitStripLine(chartNum); } private void InitRotationYawData(int chartNum) { } private void InitAbsoluteYawRatePerSecond(int chartNum) { } private void InitStripLine(int chartNum) { stripLine = new StripLine { Text = $"time", TextAlignment = StringAlignment.Near, // テキストの水平位置(Near:左, Center:中央, Far:右) TextLineAlignment = StringAlignment.Far, // テキストの垂直位置(Near:下, Center:中央, Far:上) Interval = 0, // 線分の表示間隔 値を設定すると指定した間隔で表示される。 //IntervalOffset = offset, // 線分の表示オフセット BorderWidth = 1, BorderDashStyle = ChartDashStyle.DashDot, BorderColor = Color.Red, }; charts[chartNum].ChartAreas[0].AxisX.StripLines.Add(stripLine); } public void AddData(GT7DashboardData data) { if(chartTypes.Count() == charts.Count()) { int chartNum = 0; foreach (var chart in charts) { switch (chartTypes[chartNum]) { case ChartDataType.Throttle: throttleGraph.AddData(data, charts[chartNum]); break; case ChartDataType.Braking: brakingGraph.AddData(data, charts[chartNum]); break; case ChartDataType.Speed: vehicleSpeedGraph.AddData(data, charts[chartNum]); break; case ChartDataType.Rpm: rpmGraph.AddData(data, charts[chartNum]); break; case ChartDataType.Gear: gearGraph.AddData(data, charts[chartNum]); break; case ChartDataType.Tires: tiresGraph.AddData(data, charts[chartNum]); break; case ChartDataType.Boost: boostGraph.AddData(data, charts[chartNum]); break; } chartNum++; } } } private void SetChartAxisXTitle(int chartNum, int areaNum, string title) { charts[chartNum].ChartAreas[areaNum].AxisX.Title = title; } private void SetChartAxisYTitle(int chartNum, int areaNum, string title) { charts[chartNum].ChartAreas[areaNum].AxisY.Title = title; } public void SetChartAreas(int areaNum) { foreach (var chart in charts) { // 表示範囲の設定 chart.ChartAreas[areaNum].AxisX.Minimum = Math.Round(dispAreaTn1, 1); chart.ChartAreas[areaNum].AxisX.Maximum = Math.Round(dispAreaTn2, 1); //ストリップラインの更新 chart.ChartAreas[0].AxisX.StripLines.Clear(); stripLine.IntervalOffset = (dispAreaTn1 + dispAreaTn2) / 2; chart.ChartAreas[0].AxisX.StripLines.Add(stripLine); } } public void SetChartAreas(object obj) { SetChartAreas((int)obj); } public void ChartAxisXInit(int areaNum, double x1, double x2) { foreach (var chart in charts) { chart.ChartAreas[areaNum].InnerPlotPosition.Auto = false; chart.ChartAreas[areaNum].InnerPlotPosition.X = 8.0f; chart.ChartAreas[areaNum].InnerPlotPosition.Y = 4.0f; chart.ChartAreas[areaNum].InnerPlotPosition.Width = 84.0f; chart.ChartAreas[areaNum].InnerPlotPosition.Height = 84.0f; double axisXInterval = (x2 - x1) / 10; chart.ChartAreas[areaNum].AxisX.Interval = axisXInterval; } } public void SetDispArea(double dispSpan) { dispAreaTn1 = -dispSpan / 2; dispAreaTn2 = dispSpan / 2; } public void SetDispArea(double t1, double t2) { dispAreaTn1 = t1; dispAreaTn2 = t2; } } }