Seite 1 von 2

Beschleunigte Bewegung in Ebene/Raum

Verfasst: 21.05.2009 19:36
von gnasen
Hi,

ich versuche folgendes:
Ein Objekt im 2d/3d Raum (2d wäre ein guter Anfang, 3d das Ziel) soll durch folgende Daten beschrieben werden:

-Position
-Geschwindigkeitsvektor

und besitzt eine Beschleunigung.

Nun bestimmt der Nutzer einen weiteren, frei wählbaren Punkt. Das Objekt soll definitiv diesen Punkt erreichen.

Bild

Abhängig von der Beschleunigung und der Geschwindigkeit kann das Objekt verschieden große Bahnen beschreiten.
Erreicht es zB mit max. "Lenkeinschlag" ziel a), so könnte es ziel b) nur erreichen, wenn das Objekt abbremst und somit die Wendefähigkeit (welche unter anderem von der Geschwindigkeit abhängt) erhöht.

Ich suche nach einem generellen Modell um soetwas zu beschreiben. Ich möchte dann quasi einem Objekt sagen: Gehe zu a) und es erreicht diesen Punkt physikalisch korrekt.

Ich hoffe ihr versteht wie ich das meine, sonst kann ich gerne noch skizzen o.Ä. nachreichen.

Danke schonmal an alle, die sich die Mühe machen ;)

Verfasst: 21.05.2009 20:14
von STARGÅTE
Nur noch mal zum verständnis:

Dein Objekt soll eine Kreisbahn beschreiben ja ?
würde Bedueten das der Beschleunigungsvektor immer zum Zentrum dieser Bahn zeigen muss, also nicht konstant ist (nur im betrag).

Mögliche Lösung:

Mittelpunkt zwischen Start und Ziel berechnen, und dann in Echtzeit den Beschleunigungsvektor errechnen, welcher den Geschwindigkeitsvektor ändert ...
Der Betrag der Beschl. ist abhängig von der Geschw. und des Radiuses der Kreisbahn ...

Falls ich das richtig verstanden habe, kannst du probieren es mit meinen Ideen zu lösen, oder ich schreib dir schnell n Beispiel ...

Was ist dir lieber ^^

Verfasst: 21.05.2009 20:29
von gnasen
Nochmal etwas genauer:

Man hat Anfangs eine bestimmte Geschwindigkeit in eine beliebige Richtung. Das würde bewirken, dass der Punkt auf den die Beschleunigung zeigen muss, wahrscheinlich nicht mehr die Mitte ist.

Ausserdem würde man so stets eine Kurve fliegen, auch zu weit entfernten Objekten. Es wäre hingegen schöner, könnte man erst den Geschwindigkeitsvektor aufs Ziel drehen und nach dem Kurvenflug in eine gerade übergehen.

Zur besseren Vorstellung: Es soll ein Objekt (Raumschiff) im Raum zu einem Punkt fliegen. Dabei soll die Geschwindigkeit und Beschleunigung korrekt genutzt werden. Rotation lassen wir ersteinmal aussen vor.

Ein beispiel wäre prima, allerdings sollte sichergestellt sein, dass wir das gleiche meinen. Sonst entsteht unnötige Arbeit, falls wir aneinander vorbeireden sollten ;)

Verfasst: 21.05.2009 20:35
von STARGÅTE
Wenns nur darum geht zu einem Punkt "schön" zu fliegen, ohne ein Kreisbahn zu wahren dann wäre das hier was für dich:
Mausverfolgender Bot + Anhänger

Dort könntest du dem Objekt anfangswerte zuordnen und das Ziel.
Musst halt die Anhänger entfernen und das Ziel fixieren und nicht die Maus nehmen ...

Verfasst: 21.05.2009 20:50
von Kaeru Gaman
um es ganz einfach zu machen:

dein Objekt hat eine Richtung und eine Geschwindigkeit.
sowohl Richtungs-Änderung und Geschwindigkeits-Änderung haben einen Höchstwert,
bzw. werden um einen festen Wert pro GameTic geändert.

der Fall den du betrachtest, betrifft ja nur den spezialfall, wenn das ziel SO nah dran ist,
dass das Vessel bremsen müßte, um den Punkt erreichen zu können.

die Minimalentfernung kann man berechnen:
die Momentangeschwindigkeit ist praktisch eine Wegstrecke, sagen wir mal 8 pixel/tic.
und sagen wir mal, die maximale Richtungsänderung wären 6°/tic.
um einen Halbkreis zu fliegen, brauchst du also 180°/6° = 30tics,
legst dabei also eine (Halbkreis)-Strecke von 30*8 = 240pix zurück,
die hat einen Durchmesser von 240/#pi ≈ 76.4pix

für ein Ziel, dass 76pix oder näher ist, müßtest du also abbremsen.

Die Formel kann man auch standartisieren, dass du direkt aus der Momentangeschwindigkeit
den Mindest-Flugbogendurchmesser berechnen kannst.


mal davon ab, dass du ja sowieso bremsen müsstest, da du ja wohl kaum mit Vollgas in die Station rasseln willst...

Verfasst: 21.05.2009 20:53
von gnasen
Das kommt dem ganzen schon sehr nahe.
Spontan ist mir aufgefallen, dass bei starken Richtungsänderungen (zB in die entgegengesetzte Richtung) der Bot stark abbremst, teilweise sogar stehen bleibt.
Aber der Stillstand sollte nicht sein, er könnte ja den Punkt trotzdem mit der vorherigen Geschwindigkeit noch erreichen (wäre ebend ein größerer Bogen). Nur wenn der Punkt nicht erreichbar wäre sollte er abbremsen, damit er erreicht werden kann.

Verfasst: 21.05.2009 23:21
von Batze
Fand das interessant und habe daher mal nen Code gemacht. Funktioniert zwar nich besonders, ist dafür aber 3D ;)

Code: Alles auswählen

Structure Point3D
  X.f
  Y.f
  Z.f
EndStructure
Structure Vector3D
  Len.f                  ; Länge
  AngleZ.f               ; Winkel um die Z-Achse
  AngleY.f               ; Winkel um die Y-Achse          
EndStructure

Global Ship.Point3D           ; Schiffskoordinaten
Global Speed.Vector3D         ; Schiffsbeschleunigung
Global Goal.Point3D           ; Zielpunkt
Global NewList Spur.Point3D() ; Ein hübscher Kondensstreifen
  

Procedure ReDraw()
  Protected A.f
  
  StartDrawing(ImageOutput(0))
    Box(0,0,400,400, $000000)
    Circle(Goal\X, Goal\Z, 5, $FFFF00)       ; Ziel anzeigen
    
    LineXY(Ship\X + Sin(Speed\AngleY)*4,  Ship\Z - Cos(Speed\AngleY)*4, Ship\X - Sin(Speed\AngleY)*4,   Ship\Z + Cos(Speed\AngleY)*4,  $00FFFF)
    LineXY(Ship\X + Sin(Speed\AngleY)*4,  Ship\Z - Cos(Speed\AngleY)*4, Ship\X + Cos(Speed\AngleY)*11,  Ship\Z + Sin(Speed\AngleY)*11, $00FFFF)
    LineXY(Ship\X - Sin(Speed\AngleY)*4,  Ship\Z + Cos(Speed\AngleY)*4, Ship\X + Cos(Speed\AngleY)*11,  Ship\Z + Sin(Speed\AngleY)*11, $00FFFF)
    
  
  StopDrawing()
  
  StartDrawing(ImageOutput(1))
    Box(0,0,400,400, $000000)
    Circle(Goal\X, Goal\Y, 5, $FFFF00)       ; Ziel anzeigen
  
    LineXY(Ship\X + Sin(Speed\AngleZ)*4,  Ship\Y - Cos(Speed\AngleZ)*4, Ship\X - Sin(Speed\AngleZ)*4,   Ship\Y + Cos(Speed\AngleZ)*4,  $00FFFF)
    LineXY(Ship\X + Sin(Speed\AngleZ)*4,  Ship\Y - Cos(Speed\AngleZ)*4, Ship\X + Cos(Speed\AngleZ)*11,  Ship\Y + Sin(Speed\AngleZ)*11, $00FFFF)
    LineXY(Ship\X - Sin(Speed\AngleZ)*4,  Ship\Y + Cos(Speed\AngleZ)*4, Ship\X + Cos(Speed\AngleZ)*11,  Ship\Y + Sin(Speed\AngleZ)*11, $00FFFF)
  
  
  StopDrawing()
  
  SetGadgetState(0, ImageID(0))
  SetGadgetState(1, ImageID(1))
  
EndProcedure

Procedure SetGoal(X, Y, Z)
  If X <> #PB_Ignore
    Goal\X = X
  EndIf  
  If Y <> #PB_Ignore
    Goal\Y = Y
  EndIf
  If Z <> #PB_Ignore
    Goal\Z = Z
  EndIf
  
  ReDraw()
    
EndProcedure

Macro VekLen(AY, AZ)
  (AY*AY + AZ*AZ)
EndMacro

#DAngle = 0.01

Procedure FlyToGoal()
  Protected T.f, GoalAngleY.f, GoalAngleZ.f
   
  T = VekLen(Cos(Speed\AngleY), Cos(Speed\AngleZ))
  
  Ship\X + (Cos(Speed\AngleY) + Cos(Speed\AngleZ))* Speed\Len / T
  Ship\Y + Sin(Speed\AngleZ)                      * Speed\Len
  Ship\Z + Sin(Speed\AngleY)                      * Speed\Len
  
  If Abs(Goal\X - Ship\X) < Speed\Len And Abs(Goal\Y - Ship\Y) < Speed\Len
    Speed\Len = 0
  EndIf
  
  If (Goal\X - Ship\X) > 0                                         ; Mach ich so seltsam, da es floats sind!
    GoalAngleY = ATan( (Goal\Z - Ship\Z) / (Goal\X - Ship\X) )     ; Winkel zum Ziel
    GoalAngleZ = ATan( (Goal\Y - Ship\Y) / (Goal\X - Ship\X) )     ; Winkel zum Ziel
  ElseIf (Goal\X - Ship\X) < 0                                     ; Mach ich so seltsam, da es floats sind!
    GoalAngleY = ATan( (Goal\Z - Ship\Z) / (Goal\X - Ship\X) ) + #PI  ; Winkel zum Ziel
    GoalAngleZ = ATan( (Goal\Y - Ship\Y) / (Goal\X - Ship\X) ) + #PI  ; Winkel zum Ziel
  Else  
    GoalAngleY = #PI/2
    GoalAngleZ = #PI/2
  EndIf  
  
  If (Speed\AngleY - GoalAngleY) > #DAngle              ; Wenn der Winkel zu groß ist
    Speed\AngleY - #DAngle                              ; Winkel verringern
  ElseIf (Speed\AngleY - GoalAngleY) < -#DAngle         ; Wenn der Winkel zu klein ist
    Speed\AngleY + #DAngle                              ; Winkel erhöhen
  Else                                                  ; Wenn der Winkel (fast) passt
    Speed\AngleY = GoalAngleY                           ; Näher kommt man eh nicht dran -> muss reichen
  EndIf

  If (Speed\AngleZ - GoalAngleZ) > #DAngle              ; Wenn der Winkel zu groß ist
    Speed\AngleZ - #DAngle                              ; Winkel verringern
  ElseIf (Speed\AngleZ - GoalAngleZ) < -#DAngle         ; Wenn der Winkel zu klein ist
    Speed\AngleZ + #DAngle                              ; Winkel erhöhen
  Else                                                  ; Wenn der Winkel (fast) passt
    Speed\AngleZ = GoalAngleZ                           ; Näher kommt man eh nicht dran -> muss reichen
  EndIf
  
  
  
  ReDraw()     ; Neu anzeigen  
EndProcedure

CreateImage(0, 400,400)  ; Aufsicht:      x * z
CreateImage(1, 400,400)  ; Seitenansicht: x * y

OpenWindow  (0,   0,   0, 805, 430, "Flugbahn", #PB_Window_MinimizeGadget)
ImageGadget (0,   0,   0, 1,1, ImageID(0))
ImageGadget (1, 405,   0, 1,1, ImageID(1))
ButtonGadget(2, 300, 405, 210, 20, "Flieg an den angegebenen Punkt")
SpinGadget  (3,   5, 405,  50, 20, 0, 5000, #PB_Spin_Numeric)

SetGadgetState(3, 100)

Ship\X = 200        ; Mitte
Ship\Y = 200
Ship\Z = 200

Speed\Len = 0       ; Noch nicht fliegen
Speed\AngleZ = 0    ; Standardrichtung
Speed\AngleY = 0

ReDraw()

Repeat
  WEvent = WaitWindowEvent(10)
  
  If WEvent = #PB_Event_Gadget
    Select EventGadget()
      Case 0 : SetGoal(WindowMouseX(0),     #PB_Ignore,      WindowMouseY(0))
      Case 1 : SetGoal(WindowMouseX(0)-405, WindowMouseY(0), #PB_Ignore     )
      Case 2 : If Speed\Len > 0
                 Speed\Len = 0        ; Speed aus
                 SetGadgetText(2, "Flieg an den angegebenen Punkt")
               Else
                 Speed\Len = GetGadgetState(3) / 1000        ; Speed ermitteln und losfliegen
                 SetGadgetText(2, "Flug stoppen")
               EndIf
    EndSelect
  EndIf
  
  If Speed\Len > 0
    FlyToGoal()
  EndIf

Until WEvent = #PB_Event_CloseWindow

Verfasst: 22.05.2009 10:46
von gnasen
@batze:

Sagen wir so: Faszinierend... Aber leider nicht funktioniered :cry:

Wenigstens weiss ich jetzt, dass das Problem nicht ganz so trivial ist, wie ich anfangs dachte. Folgenden Ansatz habe ich:

Ortsvektor s' = s0 + t * v0 * (Matrix)

mit der Matrix:

Code: Alles auswählen

sin theta cos phi
sin theta sin phi
cos theta
mit:
theta = theta(v0,t)
phi = phi(v0,t)

Allerdings weiss ich nicht, wann der Radius zu klein wird, und wie ich darauf reagieren soll. Ausserdem ist die Beschleunigung ein Problem.

Verfasst: 22.05.2009 12:27
von Kaeru Gaman
/:-> ... ist dir da vielleicht ein Beitrag entgangen?

Verfasst: 22.05.2009 18:12
von gnasen
Kaeru Gaman hat geschrieben:/:-> ... ist dir da vielleicht ein Beitrag entgangen?
Jetzt wo du es sagst: Ja. Ich schaue immer, ob was neues unter meinem letzten Beitrag erschienen ist. Du musst deinen wohl abgeschickt haben, als ich noch am tippen war. Mein Fehler :oops:

Leider hilft dein Ansatz nicht wirklich weiter. Mal ein Beispiel, wo man merkt dass es schwierig wird:
Objekt ist in der Bewegung einer Linkskurve mit max. seitlicher Geschwindigkeit (angenommen es kann vorwärts schneller als seitwärts). Nun setze ich 90° rechts vom Objekt den Punkt. Nun muss berechnet werden: Wo landet das Objekt, während der Schub von max. Links nach max. Rechts umverteilt wird? Müsste es in dieser Zeit schon langsamer sein, um das Ziel noch zu erreichen?

Man merkt schnell, dass das äußerst komplex ist. Ich zerbreche mir jetzt seit 2 Tagen den Kopf darüber :D