JitterCompany / f1-led-circuit

Formula 1 LED circuit
0 stars 0 forks source link

Format race data #36

Open CodingInGreen opened 1 week ago

CodingInGreen commented 1 week ago

The location data provides the timestamps and x,y,z coordinates per driver, it also provides the driver number. Unfortunately we can't pull all of the location data down at once because the API server has a timeout after 1 minute.

This is the format of the API URL to request the location data for Max Verstappen for the 2023 Dutch Grand Prix:

https://api.openf1.org/v1/location?session_key=9149&driver_number=1

The format is json.

The format looks like this:

[{"x":0,"y":0,"z":0,"driver_number":1,"date":"2023-08-27T12:01:01.614000+00:00","session_key":9149,"meeting_key":1217},{next json objects until end}]
CodingInGreen commented 1 week ago

We want to combine the datasets for the locations all the drivers sorted by timestamp. Then we have the full dataset from the source, but it's missing the led numbers for the drivers. There should be a mapping between the x,y coordinates in the source dataset and the led's x,y coordinates (which we need to calculate).

CodingInGreen commented 1 week ago

After we have a dataset that includes the x,y coordinates from the source dataset and our calculated x_led, y_led coordinates for the led lights, we can then assign led numbers by mapping x,y and x_led, y_led using a calculation like nearest neighbor. Once we've arrived at a new dataset with the timestamp, driver number, and led number, this is all the data that we need to convert it to the format that we want to use for processing. We can discard the remaining fields from the source dataset.

This issue explains the process I used to arrive at this new dataset. Some extra steps were added that later we found to be unnecessary.

https://github.com/JitterCompany/f1-led-circuit/issues/19

CodingInGreen commented 1 week ago

Then we want to convert the dataset with the timestamp, driver number, and led number to a new format that we can use for processing. This is tricky, because the timestamps in the dataset across drivers aren't in sync. So we need a way to normalize the timestamps for a certain period of time (50 ms, 100ms, 250 ms, etc.). The results will be that we have multiple driver numbers and led locations for each period of time, which would constitute an "UpdateFrame" for processing on the physical board's led lights.

CodingInGreen commented 1 week ago

This is the format that we want to arrive at, at the end of this process. As you can see, each UpdateFrame corresponds to a sample of the source dataset for a given period of time based upon the normalization of timestamps across drivers and based upon a possible nearest neighbor calculation to map the led lights on the board to the x,y coordinates in the source dataset for that period of time.


#[derive(Debug)]
pub struct DriverData {
    pub driver_number: u32,
    pub led_num: u32,
}

#[derive(Debug)]
pub struct UpdateFrame {
    pub drivers: [Option<DriverData>; 20],
}

#[derive(Debug)]
pub struct VisualizationData {
    pub update_rate_ms: u32,
    pub frames: [UpdateFrame; 1548],
}

pub const VISUALIZATION_DATA: VisualizationData = VisualizationData {
    update_rate_ms: 1000,
    frames: [
        UpdateFrame {
            drivers: [
                Some(DriverData {
                    driver_number: 23,
                    led_num: 53,
                }),
                Some(DriverData {
                    driver_number: 14,
                    led_num: 31,
                }),
                Some(DriverData {
                    driver_number: 77,
                    led_num: 70,
                }),
                Some(DriverData {
                    driver_number: 10,
                    led_num: 49,
                }),
                Some(DriverData {
                    driver_number: 24,
                    led_num: 8,
                }),
                Some(DriverData {
                    driver_number: 44,
                    led_num: 52,
                }),
                Some(DriverData {
                    driver_number: 27,
                    led_num: 48,
                }),
                Some(DriverData {
                    driver_number: 40,
                    led_num: 34,
                }),
                Some(DriverData {
                    driver_number: 16,
                    led_num: 85,
                }),
                Some(DriverData {
                    driver_number: 20,
                    led_num: 64,
                }),
                Some(DriverData {
                    driver_number: 4,
                    led_num: 51,
                }),
                Some(DriverData {
                    driver_number: 31,
                    led_num: 14,
                }),
                Some(DriverData {
                    driver_number: 11,
                    led_num: 52,
                }),
                Some(DriverData {
                    driver_number: 81,
                    led_num: 77,
                }),
                Some(DriverData {
                    driver_number: 63,
                    led_num: 56,
                }),
                Some(DriverData {
                    driver_number: 55,
                    led_num: 3,
                }),
                Some(DriverData {
                    driver_number: 2,
                    led_num: 47,
                }),
                Some(DriverData {
                    driver_number: 18,
                    led_num: 27,
                }),
                Some(DriverData {
                    driver_number: 22,
                    led_num: 25,
                }),
                Some(DriverData {
                    driver_number: 1,
                    led_num: 45,
                }),
            ],
        },```
CodingInGreen commented 5 days ago

I updated created a handmade data structure/dataset for processing the leds, and I reviewed that against the computer made data structure/dataset. The two didn't match, so I revised the processing program, for this one the data structures/datasets match:

https://github.com/CodingInGreen/f1-led-circuit-format-data-finalized

I then processed the sample dataset using that program and tested on the board.

The behavior matches more closely with the race, but I need to review the race tracker alongside the board running the program.

CodingInGreen commented 5 days ago

One of the problems I discovered is that I was omitting 0,0 x,y coordinate timestamps in the original dataset for processing. This was throwing off the order of timestamps, in looking at the raw data there actually are matching timestamps, in many cases for all 20 drivers. It then becomes easy to consolidate those timestamps into an UpdateFrame for processing.

CodingInGreen commented 5 days ago

So we need to decide how to handle the 0,0 x,y timestamp data. We can't omit it, currently the nearest neighbor is led number 41 on the pcb. So in the current data processing and visualization, led 41 will light up until all cars have started the race for the formation lap. 0,0 x,y data is also assigned when a driver has been eliminated from the race. One thing we might do is assign a led number that is out of range, for example 97 doesn't map to an led number. Then we could handle that special case in hd108.rs if needed.

CodingInGreen commented 4 days ago

We decided for the time being to set 0,0 x,y positions to led number 97.