Need nice way to create parabolic trajectory
Hi all,
I have made basic parabolic paths (by subtracting from a pre-set Y-amount), but I am looking for something more elaborate.
I'm using this to create a trajectory for a mortar/projectile. I would really like a function which takes three parameters: the launching position(Vector), the landing position(Vector), and the angle of arc (float).
Anyone have a function like this sitting on their hard drive?
I also wouldn't mind finding a Class which does this and offers more features; this is something I do fairly often and would love more flexibility.
I am happy to answer any questions if it helps to convey what I'm looking for.
Thanks in advance!! Regards,
-joshua
joshua >>at<< spaceweather.com
You could take a look at my two responses here for a couple of trajectory equations and functions, you could also do it iteratively (as you seem to be currently) as was also suggested there.
Unfortunately neither method I presented uses the angle of the arc, although im sure you could use the angle to calculate an initial speed/direction vector, but you did say you were interested in alternatives [smile]
Good luck
Unfortunately neither method I presented uses the angle of the arc, although im sure you could use the angle to calculate an initial speed/direction vector, but you did say you were interested in alternatives [smile]
Good luck
Hey DMatter,
That's a helpful thread, but of course it's not exactly what I'm looking for. I really want a function with this signature:
Vector3 calculateTrajectory(Vector3 orgin, Vector3 destination, double arc);
Any ideas :-)
Thanks!!!!! Best,
-joshua
That's a helpful thread, but of course it's not exactly what I'm looking for. I really want a function with this signature:
Vector3 calculateTrajectory(Vector3 orgin, Vector3 destination, double arc);
Any ideas :-)
Thanks!!!!! Best,
-joshua
R = horizontal difference of points
H = altitude difference to target
A = arc angle from ground
G = gravity constant
S = initial speed of the projectile
t = R / cos(A)
solve for S:
H = G * t * t / 2 + sin(A) * S * t
S = (H - G * t * t / 2) / (sin(A) * t)
Now that you have S, just make a new vector in the direction of the target, at the arc angle with magnitude of S.
I just did this now, there may be errors. But this should get you started.
H = altitude difference to target
A = arc angle from ground
G = gravity constant
S = initial speed of the projectile
t = R / cos(A)
solve for S:
H = G * t * t / 2 + sin(A) * S * t
S = (H - G * t * t / 2) / (sin(A) * t)
Now that you have S, just make a new vector in the direction of the target, at the arc angle with magnitude of S.
I just did this now, there may be errors. But this should get you started.
Quote:Original post by meteors
Hey DMatter,
That's a helpful thread, but of course it's not exactly what I'm looking for. I really want a function with this signature:
Vector3 calculateTrajectory(Vector3 orgin, Vector3 destination, double arc);
I'm afraid that's not well-defined. If 'arc' defines the angle at the origin, then the (function) parameter set will uniquely define a parabola. To determine a point on the trajectory you'd also need to pass an input (mathematical) parameter, most likely time-from-launch or current-angle-from-some-give-point.
But yes, the best way to proceed would be to solve the quadratic equations of motion to describe the parabola as an appropriate polynomial, then evaluate it using the passed parameter.
Think carefully about exactly what inputs will be available and what form you want the output to be in, then report back.
Admiral
Hi Admiral,
Argh...math...
Do you not know of any library which makes this sort of thing easy?
Cheers!
-joshua
Argh...math...
Do you not know of any library which makes this sort of thing easy?
Cheers!
-joshua
Quote:Original post by meteors
Do you not know of any library which makes this sort of thing easy?
The mathematics isn't too tricky. I'm sure there are a few of us who'd be happy to walk you through the calculation and corresponding code. But first we need to know exactly what you're trying to achieve, 'cause it's not clear at the moment.
Take a step back and describe your goal (rather than your method) and we'll see how we can help.
Admiral
Here's a way to do that's alot simpler since I cheated a bit with the equations:
""" turretGrav.py Side view of turrent gun Jaime Moreno 4/13/07 """ import pygame, mathpygame.init()class Label(pygame.sprite.Sprite): """ Label Class (simplest version) Properties: font: any pygame font object text: text to display center: desired position of label center (x, y) """ def __init__(self): pygame.sprite.Sprite.__init__(self) self.font = pygame.font.SysFont("None", 30) self.text = "" self.center = (320, 240) def update(self): self.image = self.font.render(self.text, 1, (0, 0, 0)) self.rect = self.image.get_rect() self.rect.center = self.centerclass Turret(pygame.sprite.Sprite): def __init__(self, shell): self.shell = shell pygame.sprite.Sprite.__init__(self) self.imageMaster = pygame.image.load("turret.gif") self.imageMaster = self.imageMaster.convert() self.imageMaster = pygame.transform.scale2x(self.imageMaster) self.rect = self.imageMaster.get_rect() self.rect.center = (100, 300) self.turnRate = 10 self.dir = 0 self.charge = 5 def update(self): self.checkKeys() self.rotate() def checkKeys(self): keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: self.dir += self.turnRate if self.dir > 360: self.dir = self.turnRate if keys[pygame.K_RIGHT]: self.dir -= self.turnRate if self.dir < 0: self.dir = 360 - self.turnRate if keys[pygame.K_UP]: self.charge += 1 if self.charge > 20: self.charge = 20 if keys[pygame.K_DOWN]: self.charge -= 1 if self.charge < 0: self.charge = 0 if keys[pygame.K_SPACE]: self.shell.x = self.rect.centerx self.shell.y = self.rect.centery self.shell.speed = self.charge self.shell.dir = self.dir self.shell.calcVector() def rotate(self): oldCenter = self.rect.center self.image = pygame.transform.rotate(self.imageMaster, self.dir) self.rect = self.image.get_rect() self.rect.center = oldCenterclass Shell(pygame.sprite.Sprite): def __init__(self, screen, background): # add background to draw path pygame.sprite.Sprite.__init__(self) self.screen = screen self.background = background self.image = pygame.Surface((10, 10)) self.image.fill((0xff, 0xff, 0xff)) self.image.set_colorkey((0xff, 0xff, 0xff)) pygame.draw.circle(self.image, (0, 0, 0), (5, 5), 5) self.image = pygame.transform.scale(self.image, (5, 5)) self.rect = self.image.get_rect() self.rect.center = (-100, -100) self.gravity = .5 # modify gravity as needed self.speed = 0 self.dir =0 self.dx = 0 self.dy = 0 self.reset() def update(self): # self.calcVector() # since we commented out calcVector() need to add self.dx,dy above! self.calcPos() self.checkBounds() self.rect.center = (self.x, self.y) def calcVector(self): radians = self.dir * math.pi / 180 self.dx = self.speed * math.cos(radians) self.dy = self.speed * math.sin(radians) self.dy *= -1 # clear the background each time we fire so old paths don't show up #self.background.fill((0x00,0xcc,0x00)) def calcPos(self): # compensate for gravity self.dy += self.gravity # draw shell path # get old position for drawing oldx = self.x oldy = self.y self.x += self.dx self.y += self.dy pygame.draw.line(self.background, (0,0,0), (oldx, oldy),(self.x,self.y)) def checkBounds(self): screen = self.screen if self.x > screen.get_width(): self.reset() if self.x < 0: self.reset() if self.y > screen.get_height(): self.reset() if self.y < 0: self.reset() def reset(self): """ move off stage and stop""" self.x = -100 self.y = -100 self.speed = 0def main(): screen = pygame.display.set_mode((640, 480)) pygame.display.set_caption ("Firing a Shell") background = pygame.Surface(screen.get_size()) background.fill((0x00, 0xCC, 0x00)) screen.blit(background, (0, 0)) shell = Shell(screen, background) turret = Turret(shell) lblOutput = Label() lblOutput.center = (100, 20) allSprites = pygame.sprite.Group(shell, turret, lblOutput) clock = pygame.time.Clock() keepGoing = True while keepGoing: clock.tick(30) for event in pygame.event.get(): if event.type == pygame.QUIT: keepGoing = False #update label lblOutput.text = "dir: %d speed %d" % (turret.dir, turret.charge) # blit background for drawings screen.blit(background, (0,0)) #allSprites.clear(screen, background) allSprites.update() allSprites.draw(screen) pygame.display.flip()if __name__ == "__main__": main()
TheAdmiral,
Later today (when I have free time), I will explain in detail what I want to do. I really appreciate your offer to help :-)
Best,
-joshua
Later today (when I have free time), I will explain in detail what I want to do. I really appreciate your offer to help :-)
Best,
-joshua
Alright. Consider the following. You have a generic parabola which would be expressed as
y(x) = Ax^2 + Bx + C
You also have two points, and initial point (x0, y0) and a final point (x1, y1). This gives us two equations:
y0 = A(x0)^2+B(x0)+C
y1 = A(x1)^2+B(x1)+C
But with 3 unknowns (A,B,C) we don't have a solution yet. But we also have an initial angle theta. This corresponds to a slope of tan(theta). We can evaluate the slope of the parabola by taking a derivative so:
y'(x) = 2A*x+B
y' is our slope which we know at the initial point x=x0 so a third equation is
tan(theta) = 2*A*(x0)+B
This gives three equations:
tan(theta) = 2*A*(x0)+B
y0 = A(x0)^2+B(x0)+C
y1 = A(x1)^2+B(x1)+C
Which can be solved in the usual ways for A, B, and C.
At this point we have the equation we need for the parabola based off the initial point, final point and initial slope.
y(x) = Ax^2 + Bx + C
You also have two points, and initial point (x0, y0) and a final point (x1, y1). This gives us two equations:
y0 = A(x0)^2+B(x0)+C
y1 = A(x1)^2+B(x1)+C
But with 3 unknowns (A,B,C) we don't have a solution yet. But we also have an initial angle theta. This corresponds to a slope of tan(theta). We can evaluate the slope of the parabola by taking a derivative so:
y'(x) = 2A*x+B
y' is our slope which we know at the initial point x=x0 so a third equation is
tan(theta) = 2*A*(x0)+B
This gives three equations:
tan(theta) = 2*A*(x0)+B
y0 = A(x0)^2+B(x0)+C
y1 = A(x1)^2+B(x1)+C
Which can be solved in the usual ways for A, B, and C.
At this point we have the equation we need for the parabola based off the initial point, final point and initial slope.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement