Bornhall / gt7telemetry

Python script to access/dump GT7 telemetry data
GNU General Public License v3.0
43 stars 8 forks source link

Is there any way to get track name? #1

Open Evisolpxe opened 1 year ago

Evisolpxe commented 1 year ago

Hi, thanks for your efforts.

I would like save the lap data and sort them by track, but didn't find any data about track.

Bornhall commented 1 year ago

Afraid not, there is no info on what track the telemetry comes from, unlike the car id. The only way I can think of is to examine the coordinates from when the car leaves the pit (in lobbies at least). The coordinates should be within some kind of tolerance though, and you'd have to go through all tracks and HOPE that there's no "collision" of coordinates between tracks.

Feel free to get back to me if you find a reliable way of identifying what track the telemetry comes from though!

Evisolpxe commented 1 year ago

Good idea. Trigger a car's position comparing when cross the finish line might be a possible way. And we can get finish line'position easily, just record telemetry data when lap refresh, the next work is pair the finish line with track name. I have no idea about same track but different layouts, maybe we need add check point data as well...

Bornhall commented 1 year ago

That is indeed an idea to investigate at least. I would say that you'd need two sets of xz coordinates (ignoring the vertical axis y in this case), one for the left hand side of the finish line and one for the right hand side. Then you can "draw" a line between those two coordinates. Next you'd take the current xz coordinate of the car and the previous xz coordinate of the car, and "draw" a line between those two coordinates. If the two lines (finish line and the car's travelling line) intersect, then you'd have a match.

You would have to filter for basically every track's finish line every time, but doing it only once (first time the lap counter changes) should be doable. With some extra logic you could check for one track every loop (60 possible tracks per second, more or less), since it wouldn't matter that much if it takes a second or two to get a result.

Sure, you'd have to "record" the finish line coordinates for each track. Tedious, but doable with some effort. Given time, I will look into it on my end, but don't let that stop you from experimenting yourself 👍🏻

Bornhall commented 1 year ago

Also, just remembered I forgot to mention that you could determine direction from the car's two xz coordinates, which should be helpful in determining which way on reverse tracks (assuming they actually share finish line coordinates – as far as I know all tracks are separate, i.e. High Speed Ring is a different track from High Speed Ring Reverse).

Bornhall commented 1 year ago

I threw together a separate Python script that you can use if you so wish. It uses Lucas Pettit's granturismo library instead of "doing it yourself", so you may need to install that first (see here: https://pypi.org/project/granturismo/ )

The script captures two sets of coordinates for the finish line, one for the left hand side and one for the right hand side. These are captured on separate laps, so on first lap you need to go (as slow as possible for best accuracy) slowly as far to the left hand side you can (on grass even). When the lap counter ticks over, the script will tell you to go another lap, but do the same on the other side of the finish line. After that it will tell you to do one more lap where the car crosses the finish line. This last lap is to determine which way the car is going (for normal or reverse layouts).

Also, it captures the max and min X and Y coordinates (or X and Z, really, but anyway). I figured this MAY be of use on track layouts where the finish line is the same for many layouts, but the layout itself differs (Blue Moon Bay, Maggiore).

I'm attaching the Python script here (rename it to .py), along with the CSV file I've gathered. The track ids are internal, but the tracks are the top row of the track selection in the lobby, i.e. Northern Isle(739), Broad Bean(743) + Reverse(744), Seaside(784) + Reverse(785), Gardens(782) + Reverse(783), High Speed Ring(745) + Reverse(746), Blue Moon(733) + Reverse(734), Infield A(735) + Reverse(736), Infield B(737) + Reverse(738) and finally Tsukuba(717).

Note that I didn't grab max/min X and Y for the first 5 rows, but for those tracks (Gardens essentially) it should suffice to check whether the direction is PX or NX to distinguish between the two. Possibly if there is a collision between various finish lines for other tracks the max/min X and Y could be useful.

The script is called with the ip address and a track id (integer), like this:

python3 gt7finish.py 192.168.0.123 456

You can use whatever track ids you prefer, but it's a good idea to keep track of what is what 😁

I will investigate this further as well, especially trying to come up with a decent track detection logic. If you capture any CSV data, feel free to share it.

gt7finish.py.txt gt7finish.csv

Evisolpxe commented 1 year ago

Awesome, works so quick. Thanks for your explaining and I'll do the capture work then pull a request here. I got covid yesterday just right do this at home.

This might be best track id we should followed. https://github.com/ddm999/gt7info/blob/web-new/_data/db/course.csv

Bornhall commented 1 year ago

Yeah, it's a good idea to use those track ids. Mine are used in a league I run, so that was easiest for me to use in testing.

Evisolpxe commented 1 year ago

Hi! I consider the script could do with some improvement. Actually we don't need go 3 full lap for get finish line, just retry 3 times is enough and that would be very efficient. And only go full lap when we need max XYZ.

Bornhall commented 1 year ago

That's a good idea actually, I will look into it after christmas. Shouldn't be a huge problem. Also, the 3rd run across the line is not technically necessary either, that's just for verifying that the two finish line coordinates are valid against the car crossing the finish line.

Bornhall commented 1 year ago

Hey there again! I haven't rewritten the code to take advantage of just going over the line and retrying, but I have gone through (I hope) all of the tracks (for other reasons as well) and there is a usable CSV file located in this repository at https://github.com/Bornhall/gt7telemetry/blob/main/gt7trackdetect.csv along with a Python script that I cobbled together that can be run and tries to detect the track (here: https://github.com/Bornhall/gt7telemetry/blob/main/gt7trackdetect.py).

The script will look for a matching finish line when the car crosses it (lap > 0 and lap changes to a higher lap), and if there are multiple matches where the car intersects the finish line, the script will try to look at the "bounding box" coordinates of the tracks to see which one matches best (for example, it can distinguish between Red Bull Ring full and short courses). It returns either a set of matches (3 by default) or None, and if there are matches, it will be in the form of an array of tuples with how well the bounding box matches (0 to 1, where 1 is an exact match) and the track id (see the CSV file).

For some tracks (both Monza variants, both Sarthe variants) it is hard to know which one it is without additional checks, so I will leave that up to someone else to handle if there is interest. As far as I am concerned there will be no further development of the gt7telemetry repository that I can foresee. Anyone else is free to pick up the torch and run with it.

Do note that Road Atlanta didn't exist in the CSV file you mentioned above (course.csv), and thus I have no internal id for that track, so I set it to 9999.

Have fun, and happy new year for those with that calendar! 👍🏻

Bornhall commented 1 year ago

Oh, and I do not guarantee this to be bug free in any way. I have tested it on a few tracks, but far from all. As I said, anyone is free to take this code and improve upon it.

Evisolpxe commented 1 year ago

Happy new year! I haven't been playing games much recently, apologize for replying so late.

I have looked over your works, it is certainly a very good approach, but there are also many details that need to be addressed. You've probably noticed that there's great mate at GTPlanet doing the same work, figuring this out by machine learning. I'd like to combine these two sets of code so that we can cross-reference the results and improve accuracy.

Hoping one day we can come up with an efficient way to get track names and use it in your app. ^_^

vthinsel commented 1 year ago

I am the one playing with ML 🙂 I would now need track traces so the model can learn and recognize all of them. Feel free to send me your captures, or ask questions. The gtplanet thread has all details

Bornhall commented 1 year ago

Sorry guys, been busy with starting up the new season of our league racing here... But yeah, I was looking into ML a little bit, but that was more in reference to finding out the state of the car/lap (as in, is it a flying lap or not, basically). Didn't get far though, I was too busy at work and getting EzioDash out the door.

I would assume it is much easier getting ML to recognize a track by the coordinates, for sure. Apart from the obvious outliers like for example Monza with or without the chicane, I would say that @Evisolpxe's idea of using the start/finish line works more or less flawlessly. I used the outer bounds of the track as well to add an extra safety net (see screenshots attached of an SVG representation, zoomed out all tracks and zoomed in and selected Northern Isle – id's are my internal id's here).

I will need to capture track data for the tracks for another reason, but I will take a look at @vthinsel's app for capturing the data and see if I can use that for my other project. Or if I can tweak my own capture script to output data suitable for the ML model training. But that will have to wait, at least from my end.

Keep me posted if you have any good ideas or need some input on your ends.

Skärmavbild 2023-01-15 kl  15 56 15 Skärmavbild 2023-01-15 kl  15 55 40

Evisolpxe commented 1 year ago

Hi, I am also playing AssettoCorsa, this game has a great third-party server that implements the timing section function in a clever way, there is documentation that explains the approach and it can be understood at a glance.

https://assettoserver.org/patreon-docs/plugins/PatreonTimingPlugin

By the way, I think this project is very user-friendly and pythonic, there is no need to spend more time developing on unpacking data. https://github.com/lucaspettit/telempy

@vthinsel 's project is running well on few tracks model, the drawback is that it is temporarily unable to identify the layout of the track in the opposite direction, and as the number of track data increases, recognition may not be so fast.

Bornhall commented 1 year ago

Hi, I am also playing AssettoCorsa, this game has a great third-party server that implements the timing section function in a clever way, there is documentation that explains the approach and it can be understood at a glance.

That's basically how I am implementing the checkpoints system, although it's not a WYSIWYG editor, like it seems to be for AC.

By the way, I think this project is very user-friendly and pythonic, there is no need to spend more time developing on unpacking data.

I have tried that, and use it sometimes, but I have found it sometimes lags more than the "hardcoded" version. For most of my purposes, it doesn't matter, but at times I want the raw values. Lucas' module performs some data processing I don't want. But it's mostly a non-issue for my purposes, I have decoding running in both Rust and Swift for production code.