how to put an object under circular motion using centripetal acceleration and tangential velocity?

Viewed 36

I am trying to simulate circular motion in pygame by using centripetal acceleration and the tangential velocity that a revolving object have.

Each frame the program increments a given angle and uses it to find the components of velocity and acceleration.Also the initial velocity of object is towards the right direction.

The problem is that when i run the code the point around which the object is rotating seems to move slightly up each frame .

Here's the code i am using.

from math import cos, sin, radians, pi

import pygame as pg

width, height = 1400, 700

dis = pg.display.set_mode((width, height))

run = True

clk = pg.time.Clock()

fps = 50

gravity = 30/fps
bounse_constant = 0.9
friction = 0.999


class body:
    k = []

    def __init__(self, x, y, vel, ang, radius):

        self.x = x
        self.y = y

        self.vel = vel
        self.xvel = vel
        self.yvel = 0
        self.angle = ang
        self.radius = radius
        self.acc = 0
        print(self.angle)

    def update(self):
        self.angle += (self.vel)/self.radius# updating the angle by the angular velocity 
        self.acc = self.vel**2/self.radius
        self.yvel += self.acc*sin(self.angle + pi/2)
        self.xvel += self.acc*cos(self.angle + pi/2)
        self.x += self.xvel
        self.y += self.yvel
        
        

        self.k.append((self.x, self.y))
        if len(self.k) > 20:
            self.k.pop(0)

    def draw(self):
        pg.draw.circle(dis, (255, 255, 255), (self.x, self.y), 1)
        pg.draw.line(dis, (255, 255, 255), (self.x, self.y),
                     ((self.x+self.xvel*4), (self.y+self.yvel*4)))
        
        for i in range(1, len(self.k)):
            pg.draw.line(dis, (255*i/len(self.k), 255*i/len(self.k),
                         255), self.k[i], self.k[i-1], round(i/4))


obj = body(600, 300, 10, 0, 100)
while run:
    for eve in pg.event.get():
        if eve.type == pg.QUIT:
            run = False
    obj.update()
    obj.draw()
    clk.tick(fps)
    pg.display.flip()#comment out this whole line if you want to see the object's path
    dis.fill((0, 0, 0))
pg.quit()
1 Answers

By changing the following lines from using += to =, seems to fix the problem -:

self.x += self.xvel
self.y += self.yvel

to -:

self.x = self.xvel
self.y = self.yvel

Further, the full code becomes this now(Also note I changed the radius and vel to see the motion clearly and confirm the fix) -:

from math import cos, sin, radians, pi

import pygame as pg

width, height = 1400, 700

dis = pg.display.set_mode((width, height))

run = True

clk = pg.time.Clock()

fps = 50

gravity = 30/fps
bounse_constant = 0.9
friction = 0.999


class body:
    k = []

    def __init__(self, x, y, vel, ang, radius):

        self.x = x
        self.y = y

        self.vel = vel
        self.xvel = vel
        self.yvel = 0
        self.angle = ang
        self.radius = radius
        self.acc = 0
        print(self.angle)

    def update(self):
        self.angle += (self.vel)/self.radius# updating the angle by the angular velocity 
        self.acc = self.vel**2/self.radius
        self.yvel = self.acc*sin(self.angle + pi/2) # Changed += to =
        self.xvel = self.acc*cos(self.angle + pi/2) # Changed += to =
        self.x += self.xvel
        self.y += self.yvel
        
        

        self.k.append((self.x, self.y))
        if len(self.k) > 20:
            self.k.pop(0)

    def draw(self):
        pg.draw.circle(dis, (255, 255, 255), (self.x, self.y), 1)
        pg.draw.line(dis, (255, 255, 255), (self.x, self.y),
                     ((self.x+self.xvel*4), (self.y+self.yvel*4)))
        
        for i in range(1, len(self.k)):
            pg.draw.line(dis, (255*i/len(self.k), 255*i/len(self.k),
                         255), self.k[i], self.k[i-1], round(i/4))


obj = body(600, 300, 100, 0, 1000) # Changed the dimensions..
while run:
    for eve in pg.event.get():
        if eve.type == pg.QUIT:
            run = False
    obj.update()
    obj.draw()
    clk.tick(fps)
    pg.display.flip()#comment out this whole line if you want to see the object's path
    dis.fill((0, 0, 0))
pg.quit()

Why this works?

This is because, at all points the velocity components are what they are being set to and they are not their previous values incremented by the current values.

Related