Jump to content Jump to content

F1 2020 UDP Specification


Recommended Posts

Just now, Hoo said:

I assumed you wanted something in the event packet, like we provide for penalty notification. Did you mean for this to be included in the LapData packet to indicate how many warnings a player received in a that lap?


The warning are already send on packet 3, it's an event. but if you don't receive the packet (some packet are lost) you never know the real number of warnings.
So yes, I would like the number total of warning have his own field (on packet 2) like penalty have it on packet 2 (lapdata).

 

Link to post
Share on other sites
  • Codemasters Staff
3 minutes ago, ThibaudPHP said:


The warning are already send on packet 3, it's an event. but if you don't receive the packet (some packet are lost) you never know the real number of warnings.
So yes, I would like the number total of warning have his own field (on packet 2) like penalty have it on packet 2 (lapdata).

 

Understood. I've updated the request for the dev team. 

  • Thanks 1
Link to post
Share on other sites
  • Codemasters Staff
On 5/4/2021 at 4:11 PM, krz9 said:

 

Initial feedback on your requests:

  1. Some mechanism to identify the end of a lap / start of a new lap.
    • Does m_currentLapNum work here? This might be difficult with our inlap / outlap idea in quali sessions though. We also have the final session results to give the total time. Are you able to provide an example of what you are trying to do?
  2. Exposing the AI difficulty level set for the (offline) session
    • Added to backlog
  3. Exposing an identifier for the Grand Prix weekend across sessions (so that qualifying and race sessions can be tied together, for instance).
    • Added to the backlog.
  4. Expose an identifier for the career mode season (like "My Team, Nickname ABC, Season 1").
    • This is a little more involved, but I’ve forwarded this to the relevant dev team members for discussion.
  5. Expose an identifier to link restarts of the same offline session (e.g. when using "mid session save & exit")
    • We intentionally don’t preserve this in the game to distinguish between retries of the same session, so would need additional work game side to accommodate this. Would the above suggestion to link all sessions within a given race weekend work here, where more recent sessions of the same type would denote restarts of that same session?
  6. A mechanism to clean telemetry data of flashbacks (for instance removing/skipping the telemetry data that is being overwritten because the user is driving the same distance again after a flashback)
    • This is a bit tricky as this is a real-time data stream, so the only good data is the latest data. It might be that repeated track progress info needs to be handled within your app? The suggestion by @101jez101 of adding a flag to mark whether the current level of track progress is being repeated becomes awkward when you can do multiple flashbacks across a section of track, so not sure if that would work either. I've sent it onto the devs for further investigation, but any thoughts from your side would be welcome.
  • Thanks 1
Link to post
Share on other sites
  • Codemasters Staff
On 5/4/2021 at 4:16 PM, 101jez101 said:

For me the negative lap distance, same lap number on flying outlaps is not ideal. If, every time you cross the start finish line, even if in the pits or if you abort the lap, the lap number increments would be better. My current solution is a bit of a hack but I'm probably missing something. Please explain how I should identify the start of a new lap if I am. 

Also, with flashbacks, a 'this is a replacement frame' flag would be useful. I get that you can't do a 'this frame is going to be deleted' flag 😊

  • Handling of first lap, outlaps and inlaps. 
    • This is tied into the current game functionality, so might be difficult to accommodate in the UDP output. I’ve forwarded to the devs for further investigation.
  • Handling of repeated progress data due flashbacks 
    • I merged your suggestion in with @krz9's point above about the same issue and sent it to the dev team for further discussion.
  • Thanks 1
Link to post
Share on other sites
  • Codemasters Staff
11 hours ago, LonelyRacer said:

 

  • Increase the number of buttons sent in m_buttonStatus to 32
    • Added to the backlog.

 

Link to post
Share on other sites
  • Codemasters Staff

Thanks for all of the suggestions so far. We have been able to sort out a couple already. Some of them look unlikely due to the complexity of the issue but are being discussed internally. Others have been placed on the active backlog and we hope to resolve some of these before 2021 launches (after which the spec should be locked). I'll do a combined update on the open requests in the future to help keep this thread a little tidier. 

  • Thanks 1
Link to post
Share on other sites
On 5/4/2021 at 12:51 PM, Hoo said:

Now is a good time! If anything is too complex to add for F1 2021 then it is still useful to know now for the future.
 

Thanks for listening to dev feedback. Just a couple of data points that I’d like to have considered for adding:

-Player pit stop strategy/window details

-Number of pit stops taken*

-Tyres used in session history (similar to classification packet)*

 

I realise that items with a * can be logged by the receiving app, however for this to be accurate, telemetry recording needs to be running from the start of the session which may not always be the case. A record from the game would alleviate possible gaps in data.

Thanks

David

Link to post
Share on other sites

@Hoo Thank you for looking into the suggestions, accepting some and following up on others. Very much appreciated! 🙌

2 hours ago, Hoo said:

Some mechanism to identify the end of a lap / start of a new lap.

  • Does m_currentLapNum work here? This might be difficult with our inlap / outlap idea in quali sessions though. We also have the final session results to give the total time. Are you able to provide an example of what you are trying to do?

We do make extensive use of currentLapNum. I was mentioning this because of the following challenges (as I type this, I realize that my suggestion should have been clearer - so thanks again for following up here):

  1. We want to store the total lap time incl. sector breakdown. The full lap time incl. sector 3 time is only known after the lap is complete, of course. I don't believe that this data point (ie. "total time incl. sector breakdown of the last completed lap") is exposed. Our workaround is to compute sector 3 time on the fly, with the assumption that the last packet before `m_currentLapNum` gets incremented gives us a reliable sector 3 time. It works in most cases, but we've noticed discrepancies of a few ms in the past. Please let me know if there's any more reliable way to get last lap total time incl. sector breakdowns.
  2. Similar problem for telemetry. We show telemetry data across an entire lap to our users (example here fyi). To do this, we need to know the start and end frame of a lap as part of the TelemetryPacket. The `m_currentLapNum` doesn't get incremented for (some?) outlaps (I don't know the exact logic, but know that when you start some sessions, or come out of the garage, the value stays at 1 even though you crossed the start/finish line). As a workaround, we've implemented custom code based on `lapDistance`. For instance, to handle the outlap issue I've mentioned, we have implemented code that automatically ignores all past frames when the `lapDistance` value changes from a large value (like 3000) to a small value (like 10), assuming that the user crossed the start/finish line, even though the `m_currentLapNum` didn't change. I'm sure there are many ways to solve this, but some way to clearly tell that a new lap was start, or that the start/finish line was crossed, would have saves us a lot of custom code.
2 hours ago, Hoo said:

Expose an identifier to link restarts of the same offline session (e.g. when using "mid session save & exit")

  • We intentionally don’t preserve this in the game to distinguish between retries of the same session, so would need additional work game side to accommodate this. Would the above suggestion to link all sessions within a given race weekend work here, where more recent sessions of the same type would denote restarts of that same session?

I understand your point re distinguishing between retries. You could also consider exposing two ID fields - one persistent and one that changes.

To answer your question, yes, if there is a way to reliably link a session to some sort of parent object (Grand Prix weekend, career mode season, multiplayer league, or similar), that should work for us. What we are solving for is to show our users a full race summary incl. all laps (see third screenshot here for instance). So for any session where a user might care about the full lap history (such as race sessions for instance; not session like time trial), we'd need a way to reliably link it to a parent object.

2 hours ago, Hoo said:
    • This is a bit tricky as this is a real-time data stream, so the only good data is the latest data. It might be that repeated track progress info needs to be handled within your app? The suggestion by @101jez101 of adding a flag to mark whether the current level of track progress is being repeated becomes awkward when you can do multiple flashbacks across a section of track, so not sure if that would work either. I've sent it onto the devs for further investigation, but any thoughts from your side would be welcome.

Yeah I understand why it works the way it does, and why that is a clean way to handle things. But it does make our life more difficult 🙂 As you mentioned, we handle the cleanup in our app. We solve this by separately storing the current `lapDistance`; we then compare each new frame's `lapDistance` to the last one; if it decreased, we clean up the frames in-between. It works, but is pretty complicated and doesn't feel very reliable long term.

Thanks again for taking our feedback into consideration! Looking forward to F1 2021!

Link to post
Share on other sites
2 hours ago, Hoo said:

 

  1. A mechanism to clean telemetry data of flashbacks (for instance removing/skipping the telemetry data that is being overwritten because the user is driving the same distance again after a flashback)
    • This is a bit tricky as this is a real-time data stream, so the only good data is the latest data. It might be that repeated track progress info needs to be handled within your app? The suggestion by @101jez101 of adding a flag to mark whether the current level of track progress is being repeated becomes awkward when you can do multiple flashbacks across a section of track, so not sure if that would work either. I've sent it onto the devs for further investigation, but any thoughts from your side would be welcome.

I do understand the issues you would have flagging flashbacks / replacement frames and was thinking about the multiple, partially overlapping flashback scenarios (while repeatedly missing my braking point into turn 1 at Monza). 

 

My best idea was that each lap you would have N lives in a counter field. Each time you flashback, that increments. Either / or that with a standalone event packet describing A) the last frameId before a pause and B) the last frameId *not* replaced.

  • Thanks 1
Link to post
Share on other sites
  • Codemasters Staff
35 minutes ago, krz9 said:

@Hoo Thank you for looking into the suggestions, accepting some and following up on others. Very much appreciated! 🙌

We do make extensive use of currentLapNum. I was mentioning this because of the following challenges (as I type this, I realize that my suggestion should have been clearer - so thanks again for following up here):

...

It should be possible to calculate sector 3 using m_lastLapTime and taking away the stores values for sector 1 and 2. If it's drifting out by a few ms then this could be a precision issue or data coming through on a different frame. I've added a task to the backlog to either store the previous lap's sector times, or work out why there is a discrepancy in the values.

I've got a query in with the dev team about the lap start / end issue, mapping sessions and flashbacks, so we'll see what they suggest.

Link to post
Share on other sites
  • Codemasters Staff
2 hours ago, DaveyGravy said:

Thanks for listening to dev feedback. Just a couple of data points that I’d like to have considered for adding:

-Player pit stop strategy/window details

-Number of pit stops taken*

-Tyres used in session history (similar to classification packet)*

 

I realise that items with a * can be logged by the receiving app, however for this to be accurate, telemetry recording needs to be running from the start of the session which may not always be the case. A record from the game would alleviate possible gaps in data.

Thanks

David

Thanks. I've added these to the backlog and will let you know if we can get these implemented.

Link to post
Share on other sites
54 minutes ago, 101jez101 said:

 standalone event packet describing A) the last frameId before a pause and B) the last frameId *not* replaced.

This doesn't necessarily have to be standalone. It could be included in the penalty packet if that was delivered every time there was a flashback. 

 

Is there a reason why only the first penalty packet in a lap is delivered? 

Link to post
Share on other sites
  • Codemasters Staff
9 minutes ago, 101jez101 said:

This doesn't necessarily have to be standalone. It could be included in the penalty packet if that was delivered every time there was a flashback. 

 

Is there a reason why only the first penalty packet in a lap is delivered? 

This should fire on each penalty awarded. If you are only getting one sent per lap then this is wrong. If you can confirm this behaviour I will ask our QA team to investigate further. 

Link to post
Share on other sites
1 minute ago, Hoo said:

This should fire on each penalty awarded. If you are only getting one sent per lap then this is wrong. If you can confirm this behaviour I will ask our QA team to investigate further. 

I think on TT at least, you don't get subsequent penalties like track limits after the first one (Inc flashback which is also a penalty), unless it also affects the next lap. I haven't tested other game modes. 

 

Even on the game itself, in TT, I think you only see the first invalidation event. I might be wrong. Usually after a marginal invalidation I get road rage and cut the next few corners and there don't appear to be any events. 

Link to post
Share on other sites
  • Codemasters Staff
Just now, 101jez101 said:

I think on TT at least, you don't get subsequent penalties like track limits after the first one (Inc flashback which is also a penalty), unless it also affects the next lap. I haven't tested other game modes. 

 

Even on the game itself, in TT, I think you only see the first invalidation event. I might be wrong. Usually after a marginal invalidation I get road rage and cut the next few corners and there don't appear to be any events. 

I don't think we record additional penalties on TT game side, so the behaviour you are seeing in the UDP output is probably correct. Let me know if you see this in any normal race session.

Link to post
Share on other sites
Just now, Hoo said:

I don't think we record additional penalties on TT game side, so the behaviour you are seeing in the UDP output is probably correct. Let me know if you see this in any normal race session.

Understood. Sorry for the lack of clarity and the minor panic. 

Link to post
Share on other sites
Posted (edited)
2 hours ago, Hoo said:

It should be possible to calculate sector 3 using m_lastLapTime and taking away the stores values for sector 1 and 2. If it's drifting out by a few ms then this could be a precision issue or data coming through on a different frame. I've added a task to the backlog to either store the previous lap's sector times, or work out why there is a discrepancy in the values.

I've got a query in with the dev team about the lap start / end issue, mapping sessions and flashbacks, so we'll see what they suggest.

@Hoo

I think the values one gets for S3 from (m_lastLapTime - (m_sectorTimeinMS + m_sectorTimeInMS)) are "very close". The issue here is that the m_laptime is float and the sectortimeInMS are ints. So if the laptime is 100.00056 and S1 is 35000 and S2 is 35000, you will get for S3 30.00056, i.e 30.001 (as a float + rounding) but 30.000 if you do the calculation in ints.

In the past there was also odd rounding in the values shown in game, but I think those were cleared/fixed few releases back.

A remedy in the UDP feed to the issue krz9 is having, would be to also report the laptime in MS, like the sector times. Then calculating the S3 would be simple int calculations and the float/int issue would go away.

Cheers.

PS.

Edit To illustrate this, here is a short code in Java:

    public static void main(String[] args) {
        int s1 = 35000;
        int s2 = 35000;
        float total = 100.00056f;
        System.out.println((int) (total * 1000) - (s1 + s2));
        System.out.println((total * 1000) - (float) (s1 + s2));
        System.out.println((total * 1000.0) - ((float) s1 + (float) s2));
    }

Which results:

30000
30000.555
30000.55694580078

So depending bit how one does the conversion, the results vary, as expected with float vs int.

Edited by LonelyRacer
Added short code.
  • Agree 2
Link to post
Share on other sites

I would like telemetry for the starting lights, with 6 stages, 5 red and 1 for off lights. if you don't have it, please add it will help a lot the leagues that use telemetry.

Link to post
Share on other sites
On 5/7/2021 at 4:36 PM, Hoo said:

It should be possible to calculate sector 3 using m_lastLapTime and taking away the stores values for sector 1 and 2. If it's drifting out by a few ms then this could be a precision issue or data coming through on a different frame. I've added a task to the backlog to either store the previous lap's sector times, or work out why there is a discrepancy in the values.

I've got a query in with the dev team about the lap start / end issue, mapping sessions and flashbacks, so we'll see what they suggest.

I see small amounts of drift too. Storing the previous laps sectors would be super handy.

1 hour ago, Keisam said:

I would like telemetry for the starting lights, with 6 stages, 5 red and 1 for off lights. if you don't have it, please add it will help a lot the leagues that use telemetry.

+1 for this.

Link to post
Share on other sites
  • Codemasters Staff
On 5/8/2021 at 6:25 PM, Keisam said:

I would like telemetry for the starting lights, with 6 stages, 5 red and 1 for off lights. if you don't have it, please add it will help a lot the leagues that use telemetry.

Hi @Keisam - do you have an example of how this might be used? 

Link to post
Share on other sites
On 5/10/2021 at 6:25 AM, Hoo said:

Hi @Keisam - do you have an example of how this might be used? 

In leagues for exemple, we can put external images in the OBS for start lights with the sound effect. This can also be used to training starts and calculate reaction times as "ThibaudPHP" mentioned.
the goal would be to use it in the leagues and leave the UDP released for spectator, because nowadays you only have the scenery lights and sometimes bug and delay for the spectator.

Exemple: https://www.youtube.com/watch?v=19kRNv_8MQI
imagine this on the screen of a transmission with chroma key or in a wheel screen dash custom

Link to post
Share on other sites
  • Codemasters Staff
12 hours ago, Keisam said:

In leagues for exemple, we can put external images in the OBS for start lights with the sound effect. This can also be used to training starts and calculate reaction times as "ThibaudPHP" mentioned.
the goal would be to use it in the leagues and leave the UDP released for spectator, because nowadays you only have the scenery lights and sometimes bug and delay for the spectator.

Exemple: https://www.youtube.com/watch?v=19kRNv_8MQI
imagine this on the screen of a transmission with chroma key or in a wheel screen dash custom

Thanks @Keisam, I've passed this info onto the dev team to review. I think the spectator delay bug was fixed shortly after launch, so hopefully you don't still see that.

  • Thanks 1
Link to post
Share on other sites
On 4/26/2021 at 2:16 PM, codeslave said:

Can you put all the code? How did you declare PacketCarStatusData? Why did you omit *(float *)& ... ?The variables has to be such an array .. I think you have missed something.

Sorry for responding so late.

I omitted the *(float*)&.. part because i didn't need to print that data.

Here's the code, i didnt insert the setup part because i just use it to config the udp reader

struct CarStatusData
{
    uint8_t       m_tractionControl;          // 0 (off) - 2 (high)
    uint8_t       m_antiLockBrakes;           // 0 (off) - 1 (on)
    uint8_t       m_fuelMix;                  // Fuel mix - 0 = lean, 1 = standard, 2 = rich, 3 = max
    uint8_t       m_frontBrakeBias;           // Front brake bias (percentage)
    uint8_t       m_pitLimiterStatus;         // Pit limiter status - 0 = off, 1 = on
    uint16_t       m_fuelInTank[2];               // Current fuel mass
    uint16_t       m_fuelCapacity[2];             // Fuel capacity
    uint16_t       m_fuelRemainingLaps[2];        // Fuel remaining in terms of laps (value on MFD)
    uint16_t      m_maxRPM;                   // Cars max RPM, point of rev limiter
    uint16_t      m_idleRPM;                  // Cars idle RPM
    uint8_t       m_maxGears;                 // Maximum number of gears
    uint8_t       m_drsAllowed;               // 0 = not allowed, 1 = allowed, -1 = unknown
    

    // Added in Beta3:
    uint16_t      m_drsActivationDistance;    // 0 = DRS not available, non-zero - DRS will be available
                                            // in [X] metres
    
    uint8_t       m_tyresWear[4];             // Tyre wear percentage
    uint8_t       m_actualTyreCompound;      // F1 Modern - 16 = C5, 17 = C4, 18 = C3, 19 = C2, 20 = C1
                // 7 = inter, 8 = wet
                // F1 Classic - 9 = dry, 10 = wet
                // F2 – 11 = super soft, 12 = soft, 13 = medium, 14 = hard
                // 15 = wet
   uint8_t       m_visualTyreCompound;        // F1 visual (can be different from actual compound)
                                            // 16 = soft, 17 = medium, 18 = hard, 7 = inter, 8 = wet
                                            // F1 Classic – same as above
                                            // F2 – same as above
    uint8_t       m_tyresAgeLaps;             // Age in laps of the current set of tyres
    uint8_t       m_tyresDamage[4];           // Tyre damage (percentage)
    uint8_t       m_frontLeftWingDamage;      // Front left wing damage (percentage)
    uint8_t       m_frontRightWingDamage;     // Front right wing damage (percentage)
    uint8_t       m_rearWingDamage;           // Rear wing damage (percentage)
    
    // Added Beta 3:
    uint8_t       m_drsFault;                 // Indicator for DRS fault, 0 = OK, 1 = fault
    
    uint8_t       m_engineDamage;             // Engine damage (percentage)
    uint8_t       m_gearBoxDamage;            // Gear box damage (percentage)
    int8_t        m_vehicleFiaFlags;          // -1 = invalid/unknown, 0 = none, 1 = green
                                            // 2 = blue, 3 = yellow, 4 = red
    uint16_t       m_ersStoreEnergy[2];           // ERS energy store in Joules
    uint8_t       m_ersDeployMode;            // ERS deployment mode, 0 = none, 1 = medium
                                            // 2 = overtake, 3 = hotlap
    uint16_t       m_ersHarvestedThisLapMGUK[2];  // ERS energy harvested this lap by MGU-K
    uint16_t       m_ersHarvestedThisLapMGUH[2];  // ERS energy harvested this lap by MGU-H
    uint16_t       m_ersDeployedThisLap[2];       // ERS energy deployed this lap
};

struct PacketCarStatusData
{
    PacketHeader      m_header;           // Header

    CarStatusData m_carStatusData[22];
};


void loop() {

  int packetSize = Udp.parsePacket();
  //If we received something.
  if(packetSize) {
     char packetBuffer[packetSize];
     Udp.read(packetBuffer, packetSize);

     Udp.read(packetBuffer, packetSize);
     int idPacket = int(packetBuffer[5]);

      if (idPacket==6){

      PacketCarTelemetryData *tmp_pckt = (PacketCarTelemetryData *) packetBuffer;
          
          Serial.printf("%u %u %u %u %u %u %u %u %u %u speed %d acc %f \n",tmp_pckt->m_header.m_packetFormat,
                                                  tmp_pckt->m_header.m_gameMajorVersion,
                                                  tmp_pckt->m_header.m_gameMinorVersion,
                                                  tmp_pckt->m_header.m_packetVersion,
                                                  tmp_pckt->m_header.m_packetId,
                                                  tmp_pckt->m_header.m_sessionUID[0],
                                                  tmp_pckt->m_header.m_sessionTime[0],
                                                  tmp_pckt->m_header.m_frameIdentifier[0],
                                                  tmp_pckt->m_header.m_playerCarIndex, 
                                                  tmp_pckt->m_header.m_secondaryPlayerCarIndex,
                                                  tmp_pckt->m_carTelemetryData[tmp_pckt->m_header.m_playerCarIndex].m_speed,
                                                  *(float *)&tmp_pckt->m_carTelemetryData[tmp_pckt->m_header.m_playerCarIndex].m_throttle[0]
                                                  );
       
  }     
  else if (idPacket==7){

  PacketCarStatusData *tmp_pckt2 = (PacketCarStatusData *) packetBuffer;
          
          Serial.printf("%u %u %u %u %u %u %u %u %u %u traction %u antilock %u fuelmix %u \n",tmp_pckt2->m_header.m_packetFormat,
                                                  tmp_pckt2->m_header.m_gameMajorVersion,
                                                  tmp_pckt2->m_header.m_gameMinorVersion,
                                                  tmp_pckt2->m_header.m_packetVersion,
                                                  tmp_pckt2->m_header.m_packetId,
                                                  tmp_pckt2->m_header.m_sessionUID[0],
                                                  tmp_pckt2->m_header.m_sessionTime[0],
                                                  tmp_pckt2->m_header.m_frameIdentifier[0],
                                                  tmp_pckt2->m_header.m_playerCarIndex, 
                                                  tmp_pckt2->m_header.m_secondaryPlayerCarIndex,
                                                  tmp_pckt2->m_carStatusData[tmp_pckt2->m_header.m_playerCarIndex].m_tractionControl,
                                                  tmp_pckt2->m_carStatusData[tmp_pckt2->m_header.m_playerCarIndex].m_antiLockBrakes,
                                                  tmp_pckt2->m_carStatusData[tmp_pckt2->m_header.m_playerCarIndex].m_fuelMix
                                                  //*(float *)&tmp_pckt2->m_carStatusData[tmp_pckt2->m_header.m_playerCarIndex].m_throttle[0]
                                                  );


                                                  Serial.println(tmp_pckt2->m_carStatusData[tmp_pckt2->m_header.m_playerCarIndex].m_fuelMix);

       
  			}  
  		}
	}
}

 

Link to post
Share on other sites
Posted (edited)

Hello,

my wish list is pretty simple:

1) m_tyresAgeLaps as public, since 2020 it's shown in the spectator menu, so it would make sense to have this property public also to telemetry data. Right now it's a bit tricky to have the tyre age if you don't record since the session start or if the drivers stays with the same compound after a PIT or if a drive through is served

2) have the PIT stop time

3) during the lobby would be nice to have drivers car number

4) Not sure if it's my implementation, but I've never been able to have the SpeedTrap event usable. It gives me non consistent data during online lobbies 

thanks!

Edited by emln22
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...