GT7 is compatible with motion rig ?

  • Thread starter poumpoum
  • 686 comments
  • 191,115 views
So the first three are the imaginary part and the last one is the real part?
Yes, or, to use Hamilton's own terminology, the vector (he actually coined the word) part followed by the scalar part.
The issue here is the time delta -- if you use the time progression in milliseconds you cannot use races with time progression factor that is unequal to one, and with time progression 0 you won't get any time progression. If you use external time measurements (measure time between arrival of packets) you will get inaccuracies. I came up with a timing solution based on the packet numbers and that the timing between them is almost-always-but-not-quite fixed to 1/60s. But it is quite involved and requires you to not miss some special packets. It doesn't work in some cases like standing starts. @Stoobert also found some velocity discrepancies with live vs. replays in the data so the time retrieval is sketchy and thus also deriving things from it like acceleration.

How do you get the time delta to differentiate from velocity to acceleration?
I think you're over-complicating this. The only thing we're interested in is the sampling period, which is 1/60 s.

I just do a[n] = 60 * (v[n] - v[n-1]), where v[n] is the velocity vector in packet n.

(because a = dv/dt -> a = dv/(1/60) = 60 * dv. And dv = v[n] - v[n - 1].)

For lap timing I accumulate 1/60 s. for each logged (i.e. non pause-flagged) packet. This yields the exact lap times displayed in-game to the millisecond, so I can't see where the alleged special packets fit in.

Edit: Ok, having logged a couple of whole races (with standing start,) there's something weird going on, but only on the final lap of the race. From my logger's debug messages it seems like the game skips a lot of packets, so the calculated timing for the last lap (and only that) is off.
 
Last edited:
Yes, or, to use Hamilton's own terminology, the vector (he actually coined the word) part followed by the scalar part.
Hamilton would turn in his grave if he knew that his beloved quaternions are nowadays not used for proper physics but for rotations in computer graphics. :lol:
This yields the exact lap times displayed in-game to the millisecond, so I can't see where the alleged special packets fit in.
...down to 1/60s would be the maximum resolution, so the laptime can only be down to about 16ms. There is a packet that has essentially an increased lap counter and the last lap time down to the millisecond. I think that this packet is emitted out of the fixed sampling rate. I might be wrong, so far i didn't log the packets -- really need to do that to analyze this further. But you are right that we only need to ignore some packets like paused ones and go with a fixed sample rate for the time in order to get a good estimate for the acceleration -- the error doesn't add up like it would when integrating, there is only a fixed small error for each acceleration value.
 
Don't know if it's any relevant, but while digging ACSIM I found that the constant 0.0166806 aka 0xAFA5883C (which * 60 frames would more or less be 1) was used when doing calculations against the car position vector.
 
Hamilton would turn in his grave if he knew that his beloved quaternions are nowadays not used for proper physics but for rotations in computer graphics. :lol:

...down to 1/60s would be the maximum resolution, so the laptime can only be down to about 16ms. There is a packet that has essentially an increased lap counter and the last lap time down to the millisecond. I think that this packet is emitted out of the fixed sampling rate. I might be wrong, so far i didn't log the packets -- really need to do that to analyze this further. But you are right that we only need to ignore some packets like paused ones and go with a fixed sample rate for the time in order to get a good estimate for the acceleration -- the error doesn't add up like it would when integrating, there is only a fixed small error for each acceleration value.

Oh, I didn't mean to imply the resolution is to the millisecond - what I meant was that the times displayed in the game are the same as calculated by accumulating 1/60 s. per packet - unless you're on the last lap of a race, somehow.

I've edited my post above to reflect that.
 
Don't know if it's any relevant, but while digging ACSIM I found that the constant 0.0166806 aka 0xAFA5883C (which * 60 frames would more or less be 1) was used when doing calculations against the car position vector.
That's probably the (floating point rounded) sampling period - the reciprocal of the sample rate (i.e. 60 Hz.)
 
Last edited:
Guys this look already fantastic to me. But I must admit I have no clue how to get it running.
I managed to install Python on my machine but thats it. No idea how to get, eg. Snimats scripts, from the git page running in my system. :confused:
 
It seems that during a replay, the rpm prints out fractions instead of integers, at least for the combo I've been testing. It doesn't really solve much, but it's at least a factor to easily discard such laps.
 
Hey guys I have dof h3 and managed to get motion and dd1 with drivehub working in gt7.. big shout out to nenkai for passing this to sim racing studio to make it possible.. your a bloody legend!

I now need simhub to work along with sim racing studio to enable my wind sim and led flag and basx shakers.. anybody figured out way to portforward to sim hub app?
 
Considering the effort that went in and the licenses between each repositories, I was surprised to find out that they sell access to certain fields and also a total lack of credits.
Make yourselves a favor and use SIM Dashboard instead.
Hello Nenkai,

I am the developer of DashPanel and I’m very sad to see I seem to have upset you.

Let me explain a bit of my situation.
First 100% credit to you and the others that figured this out. It’s very impressive.

This API development caught me at a time when I was very ill and didn’t even own a PS5. So to see other apps start to take advantage of this data while I couldn’t act on it was frustrating. I was receiving emails from customers asking I add this to my app. As soon as I was well enough I started trying to develop this ‘blind’ with two people that agreed to try it on their playstations. This was pretty impossible so as soon as I got lucky enough to find some stock I could buy a PS5 and get to work. It took quite a bit of work as my app is built in Unity and many modern code features such as async and the libraries you used are unavailable or do not work when deployed on mobile. As soon as it was finally ready as a fist take I have rushed it out.

Now I’m sorry to say in my haste I haven’t thought of a way to include a MIT license with a mobile app? With my Steam app I just include the text files. Not sure what I should do with the mobile app as this is the first open source code in the client. Is this what has bothered you or is there some other license with your code I don’t know about? AFAK the MIT license has no commercial use restriction? I’m not sure why you’re offended by my commercial app when Sim Dashboard isn’t free either?

As for my app not being free well I have been building it for 10 years I don’t feel ashamed charging for all that effort. It’s also my only source of income. Free software is great but isn’t always possible in the real world. I started with only my Android phone and PC, then to build support for many different games, screens, VR, iOS devices, Mac computer to build iOS, development licenses, many Unity Assets used within the app and most recently a PS5 the money to pay for all of these things has come from me selling the app. The app wouldn’t exist as it is now if it didn’t make any money. How can I spend 10 years and thousands of dollars so sim racers can have the app free that’s obviously not realistic? Needless to say if I was just greedy I could make a lot more money with my skills elsewhere. I've been sim racing my whole life since Papyrus Indy 500 and its my passion that makes me continue with this work, definitely not the pay.

So again I’m sorry you became offended, excuse the lack of credit I didn’t have any good ideas in a hurry. Perhaps in the next version I can add an about button to the UI that lists your license from the GitHub repo? Would this be a decent solution that satisfies you? I intend to look further into what info can be extracted from this API, the current version was a rush job just to give people what they were asking from me.

Regards
Berno
 
Last edited:
The MIT License requires to give attribution to the author and include the license terms from here: PDTools License

In SIM Dashboard all licenses and their authors are listed in the About section of the app.

There are also credits in the update notice of the app.

You should be fine if you integrate the license and give attribution within the app.

Beside that: Thanks again for all the efforts of the GT Planet Community Users here!
 
Last edited:
I managed to install Python on my machine but thats it. No idea how to get, eg. Snimats scripts, from the git page running in my system. :confused:
If you don't want to use git to use the code, go to Code->Download ZIP and get a copy:
Bildschirmfoto 2022-08-20 um 11.50.34.png

Then unzip the file, go to the gt7dashboard folder, open a command window and execute the commands as in the instructions on the github page:
Code:
pip3 install -r requirements.txt
GT7_PLAYSTATION_IP=XXX.XXX.XXX.XXX bokeh serve gt7dashboard.py
You need to find out your playstation IP address in order to communicate with it via the telemetry channel.

Hope this helps!
 
Then unzip the file, go to the gt7dashboard folder, open a command window and execute the commands as in the instructions on the github page:
Code:
pip3 install -r requirements.txt
GT7_PLAYSTATION_IP=XXX.XXX.XXX.XXX bokeh serve gt7dashboard.py
You need to find out your playstation IP address in order to communicate with it via the telemetry channel.
I was struggling with the IP, kept getting this error message:
GT7_PLAYSTATION_IP=111.111.1.111 : The term 'GT7_PLAYSTATION_IP=111.111.1.111' is not recognized as the name of a cmdle
t, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that t
he path is correct and try again.

After a lot of Googling, this finally worked for me:
Code:
$Env:GT7_PLAYSTATION_IP="111.111.1.111"
bokeh serve gt7dashboard.py
 
Hello Nenkai,

I am the developer of DashPanel and I’m very sad to see I seem to have upset you.

Let me explain a bit of my situation.
First 100% credit to you and the others that figured this out. It’s very impressive.

This API development caught me at a time when I was very ill and didn’t even own a PS5. So to see other apps start to take advantage of this data while I couldn’t act on it was frustrating. I was receiving emails from customers asking I add this to my app. As soon as I was well enough I started trying to develop this ‘blind’ with two people that agreed to try it on their playstations. This was pretty impossible so as soon as I got lucky enough to find some stock I could buy a PS5 and get to work. It took quite a bit of work as my app is built in Unity and many modern code features such as async and the libraries you used are unavailable or do not work when deployed on mobile. As soon as it was finally ready as a fist take I have rushed it out.

Now I’m sorry to say in my haste I haven’t thought of a way to include a MIT license with a mobile app? With my Steam app I just include the text files. Not sure what I should do with the mobile app as this is the first open source code in the client. Is this what has bothered you or is there some other license with your code I don’t know about? AFAK the MIT license has no commercial use restriction? I’m not sure why you’re offended by my commercial app when Sim Dashboard isn’t free either?

As for my app not being free well I have been building it for 10 years I don’t feel ashamed charging for all that effort. It’s also my only source of income. Free software is great but isn’t always possible in the real world. I started with only my Android phone and PC, then to build support for many different games, screens, VR, iOS devices, Mac computer to build iOS, development licenses, many Unity Assets used within the app and most recently a PS5 the money to pay for all of these things has come from me selling the app. The app wouldn’t exist as it is now if it didn’t make any money. How can I spend 10 years and thousands of dollars so sim racers can have the app free that’s obviously not realistic? Needless to say if I was just greedy I could make a lot more money with my skills elsewhere. I've been sim racing my whole life since Papyrus Indy 500 and its my passion that makes me continue with this work, definitely not the pay.

So again I’m sorry you became offended, excuse the lack of credit I didn’t have any good ideas in a hurry. Perhaps in the next version I can add an about button to the UI that lists your license from the GitHub repo? Would this be a decent solution that satisfies you? I intend to look further into what info can be extracted from this API, the current version was a rush job just to give people what they were asking from me.

Regards
Berno
Appeciate the response - by no means consider my response as me being offended, but it is indeed a strange design choice I was not particularily a fan of;

I think the issue I have with is not commercial products per-se (hence why I'm actually fine with anything else, thus the choice of MIT license for my library at least), but it's the specific fields locked behind a paywall. The thing is, I can understand it for any other game as it's mostly officially provided, but work went into this and I think we, and not just me, do indeed deserve at least a credit for it.

I really do appreciate dash applications picking this up and while other applications may require an upgrade to use different dashes, or more widgets, at least the information is all out there, none of the core information that took some of our time to figure is locked away from the user.

Could be seen as dangerous aswell; We don't actually know whether PDI is okay with commercial apps selling that data unofficially.

But yeah, a mere credit, and this goes for most of GTPlanet users on this thread who helped not just documenting, but building samples, test programs and devoted their time into the various algorithms here deserve it, more than me if anything.
The MIT License requires to give attribution to the author and include the license terms from here: PDTools License

In SIM Dashboard all licenses and their authors are listed in the About section of the app.

There are also credits in the update notice of the app.

You should be fine if you integrate the license and give attribution within the app.

Beside that: Thanks again for all the efforts of the GT Planet Community Users here!
Addendum, just in general: my MIT license covers my library use, it obviously doesn't cover the whole protocol so anyone can use it as will - this is down to PDI at the end of the line.

All of this is still merely my personal opinion.
 
Last edited:
I was struggling with the IP, kept getting this error message:
GT7_PLAYSTATION_IP=111.111.1.111 : The term 'GT7_PLAYSTATION_IP=111.111.1.111' is not recognized as the name of a cmdle
t, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that t
he path is correct and try again.

After a lot of Googling, this finally worked for me:
Code:
$Env:GT7_PLAYSTATION_IP="111.111.1.111"
bokeh serve gt7dashboard.py
The thing is, you have to define the environment variable called GT7_PLAYSTATION_IP with your IP address. After defining it you can run bokeh serve gt7dashboard.py . In Unix systems like MacOs and Linux you can simply type it as a one-liner just in front of bokeh ..., like in my examples. If any one knows how to do it in Windows, I will gladly add it the README. Your example looks like some Powershell, does it?
 
Appeciate the response - by no means consider my response as me being offended, but it is indeed a strange design choice I was not particularily a fan of;

I think the issue I have with is not commercial products per-se (hence why I'm actually fine with anything else, thus the choice of MIT license for my library at least), but it's the specific fields locked behind a paywall. The thing is, I can understand it for any other game as it's mostly officially provided, but work went into this and I think we, and not just me, do indeed deserve at least a credit for it.

I really do appreciate dash applications picking this up and while other applications may require an upgrade to use different dashes, or more widgets, at least the information is all out there, none of the core information that took some of our time to figure is locked away from the user.

Could be seen as dangerous aswell; We don't actually know whether PDI is okay with commercial apps selling that data unofficially.

But yeah, a mere credit, and this goes for most of GTPlanet users on this thread who helped not just documenting, but building samples, test programs and devoted their time into the various algorithms here deserve it, more than me if anything.

Addendum, just in general: my MIT license covers my library use, it obviously doesn't cover the whole protocol so anyone can use it as will - this is down to PDI at the end of the line.

All of this is still merely my personal opinion.
I hear what you are saying. I don't agree, to me its just different ways of cutting up the free vs premium pie. As a developer I'm sure also you appreciate my design choice is deeply embedded within the app and changing it to limiting the number of widgets instead of data available is totally non trivial.

I admitted my mistake in not having a way to view credits or license in my app. The fact that there is no about dialog at all in the app should prove this wasn't intentional. Regardless the product is now no longer for sale. If proper credit hasn't been given and you're not happy I felt this was the best move. I had planned on adding to the investigations into the API, prebuilding the tracks in my app so that perhaps it could work with the time delta and fuel calculator. But if PD can pull the plug on this at any time it seems dangerous to invest too much into this.

Now I don't want to derail this thread but in regards to some shade being thrown my way about being less of a 'moral' choice than other developers. Well as a moral person this is something I absolutely cannot stomach. I will share a short story of the genesis of my app. I had paid for full access to an Android dashboard application called HUD Dash. At one point this app was no longer updated and stopped functioning. Some time later an application with exactly the same interface (albeit with minor pallet change) appeared. I personally felt I would rather build my own application than pay again for an obvious rebranding. Such low tactics don't fly with me.

Take a look at the APK and screenshots and draw your own conclusions if you like:

Have fun and good luck with discovering more of the API.
 
But if PD can pull the plug on this at any time it seems dangerous to invest too much into this.
I highly doubt it as it's been open for almost 10 years and I suppose if they locked a lot of people with motion rigs will riot quite a bit.
Adding credits to the app in general and even jumping in here helping out with developing more stuff would be awesome!
 
Now I don't want to derail this thread but in regards to some shade being thrown my way about being less of a 'moral' choice than other developers. Well as a moral person this is something I absolutely cannot stomach. I will share a short story of the genesis of my app. I had paid for full access to an Android dashboard application called HUD Dash. At one point this app was no longer updated and stopped functioning. Some time later an application with exactly the same interface (albeit with minor pallet change) appeared. I personally felt I would rather build my own application than pay again for an obvious rebranding. Such low tactics don't fly with me.

I don't usually respond to this type of insult because it's absolutely a lame joke, but this needs a reaction.

Long story short, I was a user of HUD Dash myself back in 2016 and enjoyed using it. But as you said, it stopped working and was no longer maintained.
Thus I decided to give this myself a go and come up with my own app, just as you did.

The similarity of the User Interface comes from the fact that both utilize android User Interface components like the Android Expandable Listview that any app can freely use to show the list of widgets to choose from.

For me it is really frustrating that you are trying to discredit me and imply that I would have changed my name and address back in 2016 (um yeah) to re-release an existing app. The App HUD Dash was developed by a completly different person and is in no way related to me.

SIM Dashboard even has an option to purchase a full version since Day 1 in 2017, which can still be used in 2022 without having to pay again, while there has been added support for like 50 games and hundrets of widgets and features in the meantime.

As a last note: I really thought that there is a way to coexistist with multiple apps in the Sim Racing universe, thats why I took the chance to give you some help a few posts above on how you could update your app to comply with the license terms of Nenkais work. But it seems I was wrong, you are taking this much too serious, we are all here to have fun.
 
I am going to throw my 2 cents into this as well, seeing as DashPanel is for the moment the only (?) working simracing dash for iOS with support for GT7, and I don't currently own an Android phone.

First off, I don't have any problem with charging for an app that the developer invests time in, but here's my point of view on this particular case...
But if PD can pull the plug on this at any time it seems dangerous to invest too much into this.
Now, as others mentioned above, this undocumented and unofficial "API" has been around for a while, and we will likely never get any form of official documentation on this. That said, as has been mentioned, none of us knows if or when PD pulls the plug on this. This fact alone makes it, IMHO, something that I personally wouldn't have put behind a paywall.

It's totally fine if you design a specific dash with specific info and sell that as an in-app purchase. But access to the data? Data that may not be available at some point in the future? That turned me off from your app (DashPanel, that is). And I was initially stoked to find an app for iOS that had support for GT7, but that turned into disappointment rather quickly, I'm sorry to say.

This is not in any way meant as a demand or plea to "make it free", nor is it a comment on whether any of us gets credited or not. It's simply my USER experience, albeit as an informed user, and how I feel about the app in question. More of an FYI.
Have fun and good luck with discovering more of the API.
Don't think there's much more to discover at this point, I'm sorry to say. At least not from this API...
 
guys, if any of you is interested in a simple dash for GT7 on iOS, let me know and I'll port the one I wrote for Android GT7 dash app
I won't be able to sign so won't be publishing it in AppStore but it could be sideloaded.
alternatively you could try to find an old Android phone ;)
let me know if you're interested as I also don't have a lot of spare time and I'm still figuring out some of the telemetry data for my motion platform (been waiting for this since GT 5 Prologue on PS3)
 
Last edited:
For those looking for a way to use this on a mobile device, I figured how to make @snimat ‘s code run on iOS - and it doesn’t require any paid app (I’m sure you can follow similar steps to get this running on Android as well).

There are apps on iOS that run python code, but none seem to support salsa20 package. It turns out a pure python alternative works fine, but we need to make minor edits to the code. Below is a short walkthrough if anyone is interested:

1. Download @snimat ’s code as a zip from the github (https://github.com/snipem/gt7dashboard) and extract it to a folder
2. In the gt7communication.py and gt7telemetry.py files, we’ll change two lines:

change “from salsa20 import Salsa20_xor” to “from pure_salsa20 import salsa20_xor”

and

change “Salsa20_xor(dat, bytes(IV), KEY[0:32])” to “salsa20_xor(KEY[0:32], bytes(IV), dat)”

3. Head over to your iOS device and download the app “Carnets - Jupyter (with scipy)” - I couldn’t get it running with another app, but luckily this one has the added benefit of being free
4. Transfer the folder from step 1 to your iphone and put it under On My iPhone/Carnets plus/
5. Open carnets app, and navigate to the folder and click “Create Document”. This will open a Jupyter notebook.
6. In an empty cell write

%pip install pure-salsa20
%pip install tabulate

and run the code.
8. Once its done running, in another empty cell write (change the link to whatever your playstation’s ip is, which you can find from your playstation’s network setting)
!GT7_PLAYSTATION_IP=192.168.2.111 bokeh serve gt7dashboard.py
and run the code. In the output, there will be a link like “http://localhost:5006/gt7dashboard”. Just click on that and it will open the page where the dashboard is displayed.
9. Next time you open the app, all you need to do is do step 8. You don’t need to install packages again every time.

I hope some will find this useful. And of course, thank you to all the original contributors for making this possible!
 
Last edited:
For those looking for a way to use this on a mobile device, I figured how to make @snimat ‘s code run on iOS - and it doesn’t require any paid app (I’m sure you can follow similar steps to get this running on Android as well).

There are apps on iOS that run python code, but none seem to support salsa20 package. It turns out a pure python alternative works fine, but we need to make minor edits to the code. Below is a short walkthrough if anyone is interested:

1. Download @snimat ’s code as a zip from the github (https://github.com/snipem/gt7dashboard) and extract it to a folder
2. In the gt7communication.py and gt7telemetry.py files, we’ll change two lines:

change “from salsa20 import Salsa20_xor” to “from pure_salsa20 import salsa20_xor”

and

change “Salsa20_xor(dat, bytes(IV), KEY[0:32])” to “salsa20_xor(KEY[0:32], bytes(IV), dat)”

3. Head over to your iOS device and download the app “Carnets - Jupyter (with scipy)” - I couldn’t get it running with another app, but luckily this one has the added benefit of being free
4. Transfer the folder from step 1 to your iphone and put it under On My iPhone/Carnets plus/
5. Open carnets app, and navigate to the folder and click “Create Document”. This will open a Jupyter notebook.
6. In an empty cell write

%pip install pure-salsa20
%pip install tabulate

and run the code.
8. Once its done running, in another empty cell write (change the link to whatever your playstation’s ip is, which you can find from your playstation’s network setting)
!GT7_PLAYSTATION_IP=192.168.2.111 bokeh serve gt7dashboard.py
and run the code. In the output, there will be a link like “http://localhost:5006/gt7dashboard”. Just click on that and it will open the page where the dashboard is displayed.
9. Next time you open the app, all you need to do is do step 8. You don’t need to install packages again every time.

I hope some will find this useful. And of course, thank you to all the original contributors for making this possible!
For other iOS interpreters have a look at the requirements.txt. I think you are missing some dependencies. Scipy is one of them. Use pip install -r requirements.txt to install all the dependencies.

I also looked into the native salsa20 port. It seems to work exactly the same but without any native dependencies on the host system. This should make this easier to port to a broad range of devices.
 
For other iOS interpreters have a look at the requirements.txt. I think you are missing some dependencies. Scipy is one of them. Use pip install -r requirements.txt to install all the dependencies.

I also looked into the native salsa20 port. It seems to work exactly the same but without any native dependencies on the host system. This should make this easier to port to a broad range of devices.
Due to iOS restrictions, it’s not possible to download C+ based packages on iOS python interpreters. So to be able to have packages like scipy, the apps need to have them installed by default. All the packages I left out were installed by default on the Carnets app, but if anyone tries this at a different app, do take a look at the requirements.txt for other dependencies.
 
Well well well...... I'm still struggling with local velocity calculation against the world velocity provided by telemetry.
I have used many approaches, especially the one detailed here: https://stackoverflow.com/questions/1996957/conversion-euler-to-matrix-and-matrix-to-euler
But I still get strange local velocity values: high negative ones whereas I never used brake .
Any idea of what I have missed ?
The Rotation values from 0x1C to 0x28 are actually quaternion coefficients. Let's try to work out how to get the rotated vector using the quaternion (i haven't tried this, just working it out from scratch here, so there might be errors):

Here is an introduction to using unit quaternions to represent rotations, and here are operations to do rotations using only the quaternion coefficients:

Let's say we have the three floats A =(ax,ay,az) at 0x1c and the float w at 0x28, and these make up a unit quaternion Q=(A,w) with the vector part A and the scalar part w: Q=w+ax*I+ay*J+az*K. I,J,K can be thought of as unit vectors spanning 3D space. A unit quaternion means that the length of the 4D vector of the coefficients is 1 or ax*ax+ay*ay+az*az+w*w = 1. The quaternion will encode a rotation about some axis and some angle. This rotation using Q will result in a rotated vector R given any input vector V. It can be calculated like this:

R = (V + 2*A)x(AxV + w*V)

here AxB is the cross product C of the vector A=(ax,ay,az) and B=(bx,by,bz): C=(ay*bz-az*by,az*bx-bz*ay,ax*by-bx*ay)
x*V is scaling S of vector V=(vx,vy,vz) by number x: S=(x*vx,x*vy,x*vz)
A+B is vector addition (ax+bx,ay+by,az+bz)

So let's write it out in pseudocode:

given Q=(ax,ay,az,w) and V=(vx,vy,vz)

T = 2*A = (2*ax, 2*ay, 2*az) = (tx,ty,tz)
U = AxV = (ay*vz-az*vy, az*vx-vz*ax, ax*vy-vx*ay) = (ux,uy,uz)
P = U+w*V = (ux+w*vx, uy+w*vy, uz+w*vz) = (px,py,pz)
R = V+TxP = (vx + ty*pz-tz*py, vy + tz*px-tx*pz, vz + tx*py-ty*px)

R is the rotated vector. If you want the inverse rotation, you have to do the same calculations, but with the conjugated quaternion that is the quaternion with the vector part flipped in sign. With Q=(A,w)=((ax,ay,az),w) the conjugated quaternion is Q*=(-A,w)=((-ax,-ay-az),w).

Applied to the Velocity rotation: You have velocity V in global coordinates, and you want to transform into car coordinates. You have the rotation quaternion Q from the data as described above. This will rotate a vector from global coordinates to the car coordinates. So in order to reverse this you need to take the conjugated quaternion Q* and then calculate the rotated vector of V and Q* as described above.

Hope this helps!

EDIT: corrected the formulas above.
 
Last edited:
Thanks @tarnheld for your analysis. But Data at 0x1C - 0x28 really look like the standard roll/pitch/yaw in range (-1 1) Multiply by pi and you get the angle in rad. yaw goes -pi / pi when turning, pitch change when you climb, and roll changes when or go left on speedrings. Those values change over time the same way in all other games, and are heavily used in motion rigs to reflect the car position.
On the other hand, I'm not able to turn out something relevant with those values..... with world_velocity_z=world_velocity_y=0 I should have local_velocity_z = world_velocity_x . This is not the case as you can see in the charts.... I'm still missing something. Will try to understand this quaternion stuff you mention, thanks !
 
Well well well...... I'm still struggling with local velocity calculation against the world velocity provided by telemetry.
I have used many approaches, especially the one detailed here: https://stackoverflow.com/questions/1996957/conversion-euler-to-matrix-and-matrix-to-euler
But I still get strange local velocity values: high negative ones whereas I never used brake .
Any idea of what I have missed ?
View attachment 1186438
local velocity, verified against the mps provided by telemetry, is sqrt(vx*vx+vy*vy+vz*vz)
i.e. you need to combine velocity on all 3 axis to get the final velocity.
 
Last edited:
Oh, not been around for the last week due to work, vacation, and all that guzzle. Interesting to see the quaternions and what not!

I just noticed the patch notes and saw:
- Adjusted the simulation for tyre heat generation and wear ratio. This adjustment makes it easier to see the remaining tread

Intersting to see if these changes are reflected in the telemetry and if we can now figure out the wear.
 
Thanks @tarnheld for your analysis. But Data at 0x1C - 0x28 really look like the standard roll/pitch/yaw in range (-1 1) Multiply by pi and you get the angle in rad. yaw goes -pi / pi when turning, pitch change when you climb, and roll changes when or go left on speedrings. Those values change over time the same way in all other games, and are heavily used in motion rigs to reflect the car position.
On the other hand, I'm not able to turn out something relevant with those values..... with world_velocity_z=world_velocity_y=0 I should have local_velocity_z = world_velocity_x . This is not the case as you can see in the charts.... I'm still missing something. Will try to understand this quaternion stuff you mention, thanks !
It's not just the rotation angles -- the range of [-1,1] indicates that they are sin/cos of an angle. So need to do an asin/acos to get to the angles in radians, then multiply with 180/pi to get to the angle in degrees. If you do that, you will notice that the angles are just half the angles of the actual rotation in the game. If you rotate the car 90° you will notice that the rotation angles will only indicate 45°. All of this indicates that the values are coefficients of a unit quaternion -- if you read up on that here, you see that the quaternion coefficients are sin/cos of half the rotation angle about a certain axis which is also encoded in the coefficients.

Here is an example python script that does the velocity vector rotation to get to the local velocity. The Z component of the local vector seems the main direction of travel, and the sign of the velocity is reversed. I guess the X component corresponds to sideways velocity, with positive meaning leftways, so all in all it seems that PD is using a right handed coordinate system. Here is the script, including Acceleration and G-Force calculation as described by @Skinny McLean:

Python:
import socket
import sys
import struct
import math
import datetime
# pip3 install salsa20
from salsa20 import Salsa20_xor

#https://github.com/Nenkai/PDTools/blob/master/SimulatorInterface/SimulatorInterface.cs
SendDelaySeconds = 10

ReceivePort = 33740
SendPort = 33739

port = ReceivePort

if len(sys.argv) == 2:
    # Get "IP address of Server" and also the "port number" from
    ip = sys.argv[1]
else:
    print("Run like : python3 gt7racedata.py <playstation-ip>")
    exit(1)

# Create a UDP socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the port
server_address = ('0.0.0.0', port)
s.bind(server_address)
s.settimeout(10)

#https://github.com/Nenkai/PDTools/blob/master/PDTools.Crypto/SimulationInterface/SimulatorInterfaceCryptorGT7.cs
def salsa20_dec(dat):
  KEY = b'Simulator Interface Packet GT7 ver 0.0'
  oiv = dat[0x40:0x44]
  iv1 = int.from_bytes(oiv, byteorder='little') # Seed IV is always located there
  iv2 = iv1 ^ 0xDEADBEAF #// Notice DEADBEAF, not DEADBEEF
  IV = bytearray()
  IV.extend(iv2.to_bytes(4, 'little'))
  IV.extend(iv1.to_bytes(4, 'little'))
  ddata = Salsa20_xor(dat, bytes(IV), KEY[0:32])#.decode()
  #check magic number
  magic = int.from_bytes(ddata[0:4], byteorder='little')
  if magic != 0x47375330:
    return bytearray(b'')
  return ddata

def send_hb(s):
  #send HB
  send_data = 'A'
  s.sendto(send_data.encode('utf-8'), (ip, SendPort))
  print('send heartbeat')

send_hb(s)

#see https://www.gtplanet.net/forum/threads/gt7-is-compatible-with-motion-rig.410728/post-13823560

def quat_conj(Q):
    return (-Q[0],-Q[1],-Q[2],Q[3])
def quat_vec(Q):
    return (Q[0],Q[1],Q[2])
def quat_scalar(Q):
    return Q[3]
def cross(A,B):
    return (A[1]*B[2]-A[2]*B[1],A[2]*B[0]-A[0]*B[2],A[0]*B[1]-A[1]*B[0])
def add(A,B):
    return (A[0]+B[0],A[1]+B[1],A[2]+B[2])
def sub(A,B):
    return (A[0]-B[0],A[1]-B[1],A[2]-B[2])
def scale(A,s):
    return (A[0]*s,A[1]*s,A[2]*s)
def quat_rot(V,Q):
    Qv = quat_vec(Q)
    U = cross(Qv,V)
    w = quat_scalar(Q)
    P = add(U,scale(V,w))
    T = scale(Qv,2)
    RR = cross(T,P)
    R = add(V,RR)
    return R

print("Ctrl+C to exit the program")
dp_prev = 0
pknt = 0
Vp = (0,0,0)
while True:
    try:
        data, address = s.recvfrom(4096)
        pknt = pknt + 1
        print("received: %d bytes" % len(data))
        ddata = salsa20_dec(data)
        if len(ddata) > 0:
            magic = struct.unpack_from('i',ddata,0)
            P = struct.unpack_from('fff',ddata,0x4)
            print('Position',P)
            V = struct.unpack_from('fff',ddata,0x10)
            print('Global Velocity',V)
            Q = struct.unpack_from('ffff',ddata,0x1C)
            Qc = quat_conj(Q)
            Vl = quat_rot(V,Qc)
            print("Local Velocity:",Vl)
            dV = sub(Vl,Vp)
            A = scale(dV,60)
            print("Acceleration:",A)
            G = scale(A,1.0/9.81)
            print("G-Forces:",G)
            Vp = Vl # save current local velocity for next packet

        if pknt > 900:
            send_hb(s)
            pknt = 0
    except Exception as e:
        print(e)
        send_hb(s)
        pknt = 0
        pass

EDIT: Oh and by the way: The telemetry channel is still open in GT7 version 1.20! :D
 
Last edited:
Back