Sommarprojekt - Cykelloppssimulator

Ambassadör
League of Legends
Sommarprojekt - Cykelloppssimulator

Efter att jag gjorde en spel-prototyp till FZ Game Jam har jag lekt runt med olika programmeringsuppgifter utan något specifikt projekt i tankarna. För några dagar sedan kom jag dock på en idé som tilltalade mig tillräckligt för att intressera mig mer än för stunden. Idén kom efter att jag donerade bort min upplaga av Tour de France 2018. För snart ett år sedan recenserade jag spelet här på FZ. Jag var allt annat än nöjd med spelet och sågade det med fotknölarna. Jag tror mig inte kunna göra ett bättre spel själv men konceptet att göra en cykelrace-simulator satte direkt igång tankar på problem som var redo att lösas.

PROBLEM 1 - MATEMATISKT MODELLERING AV BANAN

För att simulera ett cykellopp behöver dess bansträckning modelleras i spelet. Modelleringen behöver både markera distans och höjdprofil vilket till en början kändes komplicerat att utföra. Jag är dock en flitig användare av diverse kartjänster på internet och vet ett par som erbjuder en gratis, grov höjdprofil vid streckdragning. I Sverige bistår Lantmäteriet med en sådan karta men jag var ute efter en som möjliggjorde modellering av sträckor över hela världen. Den jag fann erhölls via arcgis.com. Med kartans verktyg markerade jag en sträcka någonstans i de Franska Alperna och en höjdprofil för sträckan laddas i samma fönster. För att importera det till simulatorn kopierade jag endast kartan och profilen som PNG-filer. Väl inne i simulatorn markerade jag linjerna återigen för att ge banan och profilen koordinater i simulatorns “miljö”. Koordinatpunkterna sparade jag i två listor som skalades med de verkliga måtten samt kontrollerades om några orimliga punkter dök upp i listorna. Den importerade kartan är endast ~35 km och motsvarar inte något verkligt lopp. Jag vet inte ens om det är möjligt att cykla på den sträckan jag har markerat. Den får dock räcka för tillfället. Att importera en ny karta borde inte ta mer än 30 minuter om sträckan motsvarar ett full-långt cykellopp, ca 200-300 km.

Som representation av en cykelklunga infogade jag en röd cirkel som jag programmerade att följa banan och profilen. Hastigheten som cirkeln rör sig ut med sträckan skalade jag så att den motsvarade en verklig hastighet på 35 km/h. Men en konstant hastighet är inte verklighetstroget, den bör variera beroende på lutning, vind, olika sektioner av loppet och cyklisternas val längs vägen.

PROBLEM 2 – HASTIGHET

Något som ofta nämns inom cykelvärlden är ”effekt”. Både amatörer och proffs använder effekt som en måttstock för att ta reda på hur tufft ett pass är eller för att optimera sin åkning. En snabb sökning gav mig olika källor på vilken effekt som krävs för att hänga med i olika moment i ett professionellt race. Exempelvis vilken effekt krävs för att hänga med huvudklungan under ett lopp, för att vinna en bergsetapp eller för att vinna en sprint. Helt enkelt ett bra och rimligt sätt att dela in loppet i olika moment. I testloppet på 35 km bestämde jag en konstant effekt på 300 W. Den kommer dock ändras i ett senare skede.

Så varför är allt detta snack om effekt intressant? Jo, med mekanikens lagar vet vi att effekten beräknas genom formeln:

P = F * v

Där P är effekt i Watt (W), F är kraften i Newton (N) och v är hastigheten i meter per sekund (m/s). Alltså en formel som vi kan beräkna hastigheten från. Dock är kraften inte känd och måste beräknas innan vi kan få fram hastigheten. Ett bra sätt att härleda vilka krafter som påverkar ett objekt är att ”frilägga” objektet och alla krafter som påverkar det. Av de krafter som har betydelse bedömer jag att gravitation, kraft från vind och rullmotstånd utgör de mest påtagliga. Bilden nedan visar dessa tre krafter. Formeln för kraften F blir:

F = Fv + Fg + Fr

Där Fv är kraft från vind, Fg är gravitation och Fr är kraften från rullmotståndet.

Som vi kan se i bilden pekar gravitationen, Fg, rakt ner medan cyklisten åker rakt åt vänster i bilden. Det betyder att gravitationskraften inte spelar direkt roll om lutningen är noll. Dock kommer gravitation alltid att vara riktad rakt ner, så när lutningen är skild från noll kommer en del av gravitationen att påverka cyklisten. Denna påverkan blir:

Fg = m * g * sin(α)

Där m är massan på cyklisten med all utrustning, α är lutningen och g är gravitationsaccelerationen g~= 9.8, som varierar beroende på vart man är. Anledningen till att sinus används är för att vi är intressanta av den horisontella vektorn av gravitationskraften.

Att gravitationen inte påverkar när lutningen är noll är inte riktigt korrekt, för gravitationen kommer hela tiden att trycka ner cyklisten mot marken. Dock motverkas kraften av cykelns däck som i sin tur kommer få det svårare att rulla med beroende på hur tung cyklisten är, vilket underlag som man cyklar på och vilka däck man använder. Detta kallas rullmotstånd och kan formuleras som:

Fr = m * g * cos(α) *Crr

Där “m * g * cos(α)” är den vertikala gravitationskraften och Crr är en rullmotståndskonstant som kan erhållas via internet. Jag använder mig av informationen jag hittade på hemsidan OmniCalculator.com. Där hittade jag även en formel för den sista delen av kraftsumman, det vill säga kraften från vind. Denna formel är:

Fv = 0.5 * Cd * A * ρ * (v + w)²

Där Cd är en konstant beroende på formen av föremålet som påverkas av ”drag”-kraften från vinden, A är arean på den form som Cd motsvarar, ρ är luftdensitet som i sin tur varierar på lufttryck och höjd över havet, v är fastigheten på det föremål som påverkas av vind och w är vindhastigheten (positiv vid motvind och negativ vid medvind). I ovan nämnd källa fanns tal för Cd * A beroende på vilken position cyklisten har på styret.

Med detta har vi nu de mest betydande krafterna och kan lösa ut hastigheten v… eller? Tyvärr kan vi se att kraften från vind påverkas av ett kvadratiskt förhållande till cyklistens hastighet, v. När vi sen sätter in det i formeln för effekt blir det ett kubiskt förhållande. Det går alltså inte att lösa ut hastigheten, så länge man inte använder sig av metoder som faktorisering. Efter som beräkningen uppdateras hela tiden som simuleringen körs är det inte aktuellt att lösa ut v direkt.

Så är det kört? Var allt i onödan?

Nej. Det finns säkert massvis av sätt att lösa det på men metoden jag använder kallas Newton-metoden. Eftersom vi vet allt förutom just hastigheten kan vi gissa oss fram till vad hastigheten blir. För att göra det tydligare och lättare skriver jag om formeln:

P = F * v -> P = (Fv + Fg + Fr) * v -> P = (0.5 * Cd * A * ρ * (v + w)² + m * g * sin(α) + m * g * cos(α) *Crr) * v ->

Låt oss saga att:

a = 0.5 * Cd * A * ρ

och

b = m * g * sin(α) + m * g * cos(α) * Crr

Det ger:

P = (a * (v + w)² + b) * v -> P = (a * (v² + 2 * v * w + w²) + b) * v -> P = a * (v² + 2 * v * w + w²) * v + b * v -> P = a * v^3 + a * 2 * v² * w + a * w² * v + b * v -> a * v^3 + a * 2 * w * v² + a * w² * v + b * v – P = 0 ->

Låt oss nu kalla denna formel för f(v) och derivera den med avseende på v:

f(v) = a * v^3 + a * 2 * w * v² + a * w² * v + b * v – P f´(v) = 3 * a * v² + 2 * a * 2 * w * v + a * w² + b

Newton-metoden säger att det bästa sättet att hitta f(v) = 0 är att man gissar ett tal v1, om det inte är korrekt så bör nästa ”gissning” vara v2, som fås av följande formel:

v2 = v1 - f(v1) / f´(v1)

Detta återupprepas tills man når resultatet.

Troligtvis kommer man inte hitta f(v) = 0. Men en viss felmarginal får man acceptera och upprepar man det tillräckligt många gånger kommer marginalen vara försumbar. I min simulering tillåter jag en felmarginal på 0,1 m/s då jag uppdaterar beräkningarna väldigt ofta. Varje gång jag uppdaterar metoden så använder jag resultatet från föregående metod som gissning. Detta gör att beräkningarna inte behöver uppdateras så länge förutsättningarna inte ändras. Dock om v2 > v1 så kommer resultatet att bli negativt, vilket inte är rimligt, cyklisten cyklar ju inte baklänges. Vid det fallet adderar jag 10 m/s på föregående resultat och börjar om beräkningarna. Med en felmarginal på 0,1 behöver beräkningarna göras om cirka 5 iterationer som mest. Jag har satt en begränsning på 10 iterationer men det lär inte behöva användas.

Nedanstående klipp visar resultatet av min lösning av problem 1 och 2. I klippet är det konstant sydvind på 2 m/s. 1 minut i verkligheten = 1 sekund i simuleringen.

PROBLEM 3 – INOM GRUPPEN

Beräkningarna och förfarandet jag gick igenom ovan har jag tänkt ska ske på ”grupp”-nivå. Det vill säga som ett medeltal för en specifik grupp, vare sig det är huvudklungan, grupputbrytning eller soloutbrytning. Därefter görs beräkningar på ”energinivån” hos de individuella cyklisterna inom gruppen för att se om de orkar hänga med eller hur mycket energi dom har vid en eventuell spurt eller attack. Detta kombineras sedan med olika uppdrag som cyklisterna har. Exempel på uppdrag kan vara att hålla tempo i klungan, spara sig till spurten eller göra ett utbrytningsförsök. En viktig del i hur ett cykellopp avgörs och hur de olika cyklisterna sparar energi är hur de beter sig i en klunga. Detta vill jag simulera vid sidan av den simulering som görs från problem 1 och 2.

Det är hit jag har hunnit komma sen semestern började. Jag försöker hitta sätt att få cyklisterna att reagera dels på vad som händer runt omkring men också på vilken uppgift dom har. Hittills har jag fått dom att utföra några simpla uppgifter men planen är att utveckla det. I nedanstående klipp visar jag hur en grupp cyklister går ihop för att hjälpas åt att hålla uppe tempot. Grafiken är väldigt simpel, ellipsen representerar cyklisten och triangeln avser cyklistens ”synfält”.

Framöver har jag olika idéer jag vill testa. Bland annat att koppla ihop cyklisterna i lag, ge varje enskild cyklist speciella attribut så att någon är bättre i bergen, någon är bättre på att spurta och så vidare. Vi får se om jag presenterar något mer av simulatorn här.

Har ni frågor eller om ni hittar fel i formlerna ovan är det bara att lämna en kommentar.

Orginaltexten skrev jag på min hemsida Gonzobulletinen

Frilansare

Kul! Jag förstår ingenting, men är ändå mäkta imponerad.

Medlem
Fragtjuv
Skrivet av Joakim Bennet:

Kul! Jag förstår ingenting, men är ändå mäkta imponerad.

Samma här!


signatur

Xbox Series X
Playstation 5
AMD Ryzen 7 7700 CPU
MSI GeForce RTX 4060Ti VENTUS 2X OC
Kingston M.2 NV2 PCIe 4.0 NVMe SSD 2TB

1
Skriv svar