Jump to content Jump to content
F1 2021 | Online Services Update 11:00AM UK Time | Expected to last no longer than 2 hours ×

F1 2020 UDP Specification


Recommended Posts

I think the problems is related to 32bit and 64bit (I have an esp32) fields but i don't know the reason. It seems that these variables in size are bigger than 4 or 8 bytes Try to decompone 32 64 bit variables in 2 or 4 16 bit variables. I don't know if it is a bug on Arduino related or Esp32 compiling process.

struct PacketHeader
{
    uint16_t    m_packetFormat;             // 2020
    uint8_t     m_gameMajorVersion;         // Game major version - "X.00"
    uint8_t     m_gameMinorVersion;         // Game minor version - "1.XX"
    uint8_t     m_packetVersion;            // Version of this packet type, all start from 1
    uint8_t     m_packetId;                 // Identifier for the packet type, see below
    uint16_t    m_sessionUID1;               // Unique identifier for the session
    uint16_t    m_sessionUID2;               // Unique identifier for the session
    uint16_t    m_sessionUID3;               // Unique identifier for the session
    uint16_t    m_sessionUID4;               // Unique identifier for the session
    uint16_t    m_sessionTime1;              // Session timestamp
    uint16_t    m_sessionTime2;              // Session timestamp
    uint16_t    m_frameIdentifier1;          // Identifier for the frame the data was retrieved on
    uint16_t    m_frameIdentifier2;          // Identifier for the frame the data was retrieved on
    uint8_t     m_playerCarIndex;           // Index of player's car in the array

	// ADDED IN BETA 2:
    uint8_t     m_secondaryPlayerCarIndex;  // Index of secondary player's car in the array (splitscreen)
                                          	// 255 if no second player
};

The simplest way to read udp packets

void loop() {
	int packetSize = Udp.parsePacket();
 
	if(packetSize) {
		char packetBuffer[packetSize];
//		Serial.printf("Received %d bytes from %s, port %d\n",
//						packetSize,
//						Udp.remoteIP().toString().c_str(),
//						Udp.remotePort());
       
		Udp.read(packetBuffer, packetSize);
      
		int idPacket = int(packetBuffer[5]);
//		Serial.printf(" %d",idPacket);
		if (idPacket==6){
			PacketCarTelemetryData *tmp_pckt = (PacketCarTelemetryData *) packetBuffer;
          
			Serial.printf("%u %u %u %u %u %u %u %u %u %u speed %d \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_sessionUID1,
						tmp_pckt->m_header.m_sessionTime1,	
						tmp_pckt->m_header.m_frameIdentifier1,
						tmp_pckt->m_header.m_playerCarIndex, 
						tmp_pckt->m_header.m_secondaryPlayerCarIndex,
//						tmp_pckt->m_carTelemetryData[0].m_speed);
						// much better..
						tmp_pckt->m_carTelemetryData[tmp_pckt->m_header.m_playerCarIndex].m_speed);
		}
	}
}

 

Screenshot 2020-11-12 174835.jpg

Edited by codeslave
Link to post
Share on other sites
19 hours ago, codeslave said:

I think the problems is related to 32bit and 64bit (I have an esp32) fields but i don't know the reason. It seems that these variables in size are bigger than 4 or 8 bytes ..

 

 

It seems something related to data structure alignment (padding) here a link to try to understand https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member

Edited by codeslave
Link to post
Share on other sites

Try with directive __attribute__((packed)):

struct PacketHeader
{
    uint16_t    m_packetFormat;             // 2020
..
..
} __attribute__((packed));

Clearly has to be done in all struct declaration. You can evaluate with sizeof(Variable) and put out with serial.print:

ex

Serial.println(sizeof(PacketHeader));

 

If the problem persist I suppose  that also the position of variables (memory adrress) inside a struct can change (not an expert).

So for sure the first proposed solution remain the best, with somes improvement (array in place of multiple declarations).

 

struct PacketHeader
{
    uint16_t    m_packetFormat;             // 2020
    uint8_t     m_gameMajorVersion;         // Game major version - "X.00"
    uint8_t     m_gameMinorVersion;         // Game minor version - "1.XX"
    uint8_t     m_packetVersion;            // Version of this packet type, all start from 1
    uint8_t     m_packetId;                 // Identifier for the packet type, see below
    uint16_t    m_sessionUID[4];            // Unique identifier for the session
    uint16_t    m_sessionTime[2];           // Session timestamp
    uint16_t    m_frameIdentifier[2];       // Identifier for the frame the data was retrieved on
    uint8_t     m_playerCarIndex;           // Index of player's car in the array
   // ADDED IN BETA 2: 
    uint8_t     m_secondaryPlayerCarIndex;  // Index of secondary player's car in the array (splitscreen)
};

struct CarTelemetryData
{
    uint16_t    m_speed;                         // Speed of car in kilometres per hour
    uint16_t    m_throttle[2];                   // Amount of throttle applied (0.0 to 1.0)
    uint16_t    m_steer[2];                      // Steering (-1.0 (full lock left) to 1.0 (full lock right))
    uint16_t    m_brake[2];                      // Amount of brake applied (0.0 to 1.0)
    uint8_t     m_clutch;                        // Amount of clutch applied (0 to 100)
    int8_t      m_gear;                          // Gear selected (1-8, N=0, R=-1)
    uint16_t    m_engineRPM;                     // Engine RPM
    uint8_t     m_drs;                           // 0 = off, 1 = on
    uint8_t     m_revLightsPercent;              // Rev lights indicator (percentage)
    uint16_t    m_brakesTemperature[4];          // Brakes temperature (celsius)
    uint8_t     m_tyresSurfaceTemperature[4];    // Tyres surface temperature (celsius)
    uint8_t     m_tyresInnerTemperature[4];      // Tyres inner temperature (celsius)
    uint16_t    m_engineTemperature;             // Engine temperature (celsius)
    uint16_t    m_tyresPressure[8];              // Tyres pressure (PSI)
    uint8_t     m_surfaceType[4];                // Driving surface, see appendices
};

struct PacketCarTelemetryData
{
    PacketHeader      m_header;           // Header

    CarTelemetryData  m_carTelemetryData[22];

    uint16_t          m_buttonStatus[2];  // Bit flags specifying which buttons are being pressed
                                          // currently - see appendices

    // Added in Beta 3:
    uint8_t           m_mfdPanelIndex;    // Index of MFD panel open - 255 = MFD closed
                                          // Single player, race – 0 = Car setup, 1 = Pits
                                          // 2 = Damage, 3 =  Engine, 4 = Temperatures
                                          // May vary depending on game mode
    uint8_t           m_mfdPanelIndexSecondaryPlayer;   // See above
    int8_t            m_suggestedGear;    // Suggested gear for the player (1-8)
                                          // 0 if no gear suggested
};

#include <WiFi.h>
#include <WiFiUdp.h>

static const int servoPin = 13;

const char* ssid = "XXXXXXXXXX";
const char* password =  "XXXXXXXXXX";

WiFiUDP Udp;
unsigned int localUdpPort = 20777;  // local port to listen on

WiFiClient espClient;
 
void setup() {
  Serial.begin(115200);
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
 
  Udp.begin(localUdpPort);
  Serial.println(sizeof(PacketHeader));
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
  delay(2000);
}
 
void loop() {
 int packetSize = Udp.parsePacket();
  
  //If we received something.
  if(packetSize) {
       char packetBuffer[packetSize];
       //Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
       Udp.read(packetBuffer, packetSize);
       
         
       int idPacket = int(packetBuffer[5]);
 //    Serial.printf(" %d",idPacket);
       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]
                                                  );
         }
       }
  }

 

 

 

Let me know if the solutions proposed solve your problem and I will appreciate tips.

 

Bye

Edited by codeslave
  • Agree 1
Link to post
Share on other sites
On 11/17/2020 at 4:19 PM, ThibaudPHP said:

Event (packet 3) stop and go

@ThibaudPHP  Please could you check, if there is also a event for clearing penalties?

I get only penalties like this:

Event: PENA
Details:
PenaltyType:      1
InfringementType: 17
VehicleIdx:       19
OtherVehicleIdx:  255
Time:             5
LapNum:           1
PlacesGained:     0

After this "speeding in pitlane" I don't get another event if I clear the penalty by pitting again in the next lap.
So my problem still exists: I am not able to see the correct penalties during the race.  :o(

Kind regards,
Mark

Link to post
Share on other sites

Can't believe UDP it's broken again...RST is not working now, as @devvydevdev reported "if a driver pits, their `m_driverStatus` is stick at 2 (in lap) for the rest of the session" means now in TT or any other game mode, there's no chances for the telemetry software to understand the "session" is over and starts a new one...are they gonna fix this???

 

Link to post
Share on other sites
  • 2 weeks later...
3 minutes ago, JeremiaszDX said:

i have a question... Where can I find information about the grip level or how wet the track is or the equivalent of this stamp @Hoo:

tor.PNG

The weather information is in the Session packet in the m_weather field and then m_trackTemperature and m_airTemperature. The m_weatherForecastSamples field would give you the forecast for the session.

  • Thanks 1
Link to post
Share on other sites
32 minutes ago, gparent said:

This may help for F2 tyres: https://gitlab.com/gparent/f1-2020-telemetry/-/commit/6063dd6dc3b82743ab8597f58d09493117750590

Keep in mind the visual and actual tyres are different values.

Were the values for the F2 2020 teams documented somewhere or did you just take them from actual data? I couldn't find them in the previous post(s) https://gitlab.com/gparent/f1-2020-telemetry/-/commit/f7984f0ffe9667374e8fae9dd3a4957bdd998665

Link to post
Share on other sites
6 minutes ago, gparent said:

No worries. Once I have some free time I'll make a release with the F2 2020 changes. I'm missing driver IDs at the moment. I have the team ones.

Legend! I just wish this wouldn't be left up to us developers to figure out in the future 😞

Link to post
Share on other sites

Luckily my tool has  automated detection for ids/data not seen earlier.

Here are the F2 2020 new drivers + new teams detected. These are from the Enums, my tool uses. TLA is automatically created, but should be correct.

Drivers (I did edit the names, as the game only gives family name for these drivers). Format is (name, TLA, IDinGame)

DanTicktum("Dan Ticktum", "TIC", 91),
MarcusArmstrong("Marcus Armstrong", "ARM", 92),
ChristianLundgaard("Christian Lundgaard", "LUN", 93),
YukiTsunoda("Yuki Tsunoda", "TSU", 94),
JehanDaruvala("Jehan Daruvala", "DAR", 95),
GuilhermeSamaia("Guilhrme Samaia", "SAM", 96),
PedroPiquet("Pedro Piquet", "PIQ", 97),
FelipeDrugovich("Felipe Drugovich", "DRU", 98),
RobertShwartzman("Robert Shwartzman", "SHW", 99),
RoyNissany("Roy Nissany", "NIS", 100),
MarinoSato("Marino Sato", "SAT", 101),

F2 2020 Teams (took team names from the Race Director). Format is (IDinGame, Year, Long name, short name, Color Used e.g. in Map)

F2_2020_ART(70, 2020, "ART Grand Prix", "Art 2020", Color.GRAY), // ART
F2_2020_CAMPOS(71, 2020, "Campos Racing", "Campos 2020", Color.ORANGE), // Campos
F2_2020_CARLIN(72, 2020, "Carlin", "Carlin 2020", Color.BLUE), //Carlin
F2_2020_CHAROUZ(73, 2020, "Charouz Racing System", "Charouz 2020", Color.DARKBLUE), // Charouz
F2_2020_DAMS(74, 2020, "DAMS", "DAMS 2020", Color.CYAN), // DAMS // light blue?
F2_2020_UNI(75, 2020, "UNI-Virtuosi Racing", "UNI 2020", Color.YELLOW), // Uni virtu
F2_2020_MP(76, 2020, "MP Motorsport", "MP 2020", Color.DARKRED), // MP Motorsport
F2_2020_PREMA(77, 2020, "Prema Racing", "Prema 2020", Color.RED), // Prema
F2_2020_TRIDENT(78, 2020, "Trident", "Trident 2020", Color.BLUE), // Trident
F2_2020_BWT(79, 2020, "BWT HWA RACELAB", "BWT 2020", Color.PINK), // BWT
F2_2020_HITECH(80, 2020, "Hitech Grand Prix", "Hitech 2020", Color.LIGHTGRAY), // Hitech

If here are any errors, let me know.

Cheers

Edited by LonelyRacer
  • Like 1
Link to post
Share on other sites

I would like to thank all the developers of the F1 2020 game for making it even more unplayable and bug-ridden to the point of no longer being able to race without seeing cars going wrong or disappearing and reappearing from one point of the track to another! All this after the F2 2020 update. Thank you so much because we all understood that we threw our MONEY to the wind!
We are a group that organizes, indeed, organized Formula 1 championships but now after yet another bad figure we have decided to totally change the type of game !! You only think about your profits and instead of improving things you make them worse and you don't care about the feedback from the end customer! I'm sure I won't be the only one complaining, as my group of 200 and I represent perhaps 1% of everyone who uses the game! But to complain even a professional Formula 1 driver means that there is some problem, but you are only interested in selling and earning !!
I hope that someone reads this post and that you solve all the problems that are there shortly because I, like other 1000 people, at least in Italy, will certainly not buy F1 2021.
Best regards

Link to post
Share on other sites
23 minutes ago, djspeedy76 said:

I would like to thank all the developers of the F1 2020 game for making it even more unplayable and bug-ridden to the point of no longer being able to race without seeing cars going wrong or disappearing and reappearing from one point of the track to another! All this after the F2 2020 update. Thank you so much because we all understood that we threw our MONEY to the wind!
We are a group that organizes, indeed, organized Formula 1 championships but now after yet another bad figure we have decided to totally change the type of game !! You only think about your profits and instead of improving things you make them worse and you don't care about the feedback from the end customer! I'm sure I won't be the only one complaining, as my group of 200 and I represent perhaps 1% of everyone who uses the game! But to complain even a professional Formula 1 driver means that there is some problem, but you are only interested in selling and earning !!
I hope that someone reads this post and that you solve all the problems that are there shortly because I, like other 1000 people, at least in Italy, will certainly not buy F1 2021.
Best regards

That appears to be off-topic here.

Link to post
Share on other sites
  • 2 weeks later...

I know this has been widely debated here, but wouldn't it be possible to receive at least one unique id per gametag, encoded or as codemasters consider that it doesn't put the privacy of the players at risk.

If anyone can broadcast the list of gamertags to the entire world on twich, what is the problem with a person receiving it on a device at home?

Thanks

Edited by pedrosdt
Link to post
Share on other sites

Hello. Is there any further definition of the telemetry attributes below?

In other words, the importance of the measurement(s) or the receipt of measurements combining?

 

struct CarMotionData

{

    float         m_worldPositionX;           // World space X position

    float         m_worldPositionY;           // World space Y position

    float         m_worldPositionZ;           // World space Z position

    float         m_worldVelocityX;           // Velocity in world space X

    float         m_worldVelocityY;           // Velocity in world space Y

    float         m_worldVelocityZ;           // Velocity in world space Z

    int16         m_worldForwardDirX;         // World space forward X direction (normalised)

    int16         m_worldForwardDirY;         // World space forward Y direction (normalised)

    int16         m_worldForwardDirZ;         // World space forward Z direction (normalised)

    int16         m_worldRightDirX;           // World space right X direction (normalised)

    int16         m_worldRightDirY;           // World space right Y direction (normalised)

    int16         m_worldRightDirZ;           // World space right Z direction (normalised)

    float         m_gForceLateral;            // Lateral G-Force component

    float         m_gForceLongitudinal;       // Longitudinal G-Force component

    float         m_gForceVertical;           // Vertical G-Force component

    float         m_yaw;                      // Yaw angle in radians

    float         m_pitch;                    // Pitch angle in radians

    float         m_roll;                     // Roll angle in radians

};

 

struct PacketMotionData

{

    PacketHeader    m_header;               // Header

 

    CarMotionData   m_carMotionData[22];    // Data for all cars on track

 

    // Extra player car ONLY data

    float         m_suspensionPosition[4];      // Note: All wheel arrays have the following order:

    float         m_suspensionVelocity[4];      // RL, RR, FL, FR

    float         m_suspensionAcceleration[4]; // RL, RR, FL, FR

    float         m_wheelSpeed[4];           // Speed of each wheel

    float         m_wheelSlip[4];               // Slip ratio for each wheel

    float         m_localVelocityX;         // Velocity in local space

    float         m_localVelocityY;         // Velocity in local space

    float         m_localVelocityZ;         // Velocity in local space

    float         m_angularVelocityX;     // Angular velocity x-component

    float         m_angularVelocityY;           // Angular velocity y-component

    float         m_angularVelocityZ;           // Angular velocity z-component

    float         m_angularAccelerationX;       // Angular velocity x-component

    float         m_angularAccelerationY;     // Angular velocity y-component

    float         m_angularAccelerationZ;       // Angular velocity z-component

    float         m_frontWheelsAngle;           // Current front wheels angle in radians

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...