0

I have a ball class defined in Python, as follows, which is initialised with a mass = 1, radius = 1, and then we can set its position and velocity vectors as 2d numpy arrays.

class Ball():
    
    def __init__(self, pos = np.array([0,0]), vel = np.array([0,0]), mass = 1, radius = 1):
        self.mass = mass
        self.radius = radius
        self.pos = pos
        self.vel = vel

I also have a daughter class of Ball, called Container, which is essentially a large ball of radius 10, as follows:

class Container(Ball):
    def __init__(self, radius = 10):
        self.radius = radius

The ball class also has three methods which I would like to use in a new class, called Simulation. These methods are defined in the ball class, as follows (with the parameter other simply being another ball that the self ball collides with):

    def move(self, dt):
        self.dt = dt
        return np.add((self.pos),(np.dot((self.vel),self.dt)))
    
    def time_to_collision(self, other):
        self.other = other
        self.posdif = np.subtract(self.pos, other.pos)
        self.veldif = np.subtract(self.vel, other.vel)
        self.posdif = np.subtract(self.pos, other.pos)
        self.veldif = np.subtract (self.vel, other.vel)
        self.raddif = self.radius - other.radius
        return (-2*np.dot(self.posdif, self.veldif) + np.sqrt(4*(np.dot(self.posdif, self.veldif)**2)-4*np.dot(self.veldif, self.veldif)*(np.dot(self.posdif, self.posdif)-np.dot(self.raddif, self.raddif))))/(2*np.dot(self.veldif, self.veldif))

    def collide(self, other):
        self.other = other
        return self.vel - (np.dot(self.veldif, self.posdif)*self.posdif)/(np.dot(self.posdif,self.posdif))

Apologies for the long calculation, but I do not think that calculation line is relevant to the problem necessarily, just included it for completeness. These methods, move, time_to_collision and collide are to be used in another class, Simulation. The simulation class is defined as follows:

class Simulation():
    def __init__(self, ball = Ball(), container = Container()):
        self._container = container
        self._ball = ball

    def next_collision(self):
        return self._ball.move(self._ball.time_to_collision(self._ball, self._container)) 

The simulation class aims to be initialised with a Ball object, and a Container object. It then has a method, next_collision, (with the only parameter being self) which uses the methods time_to_collision to work out the time between the collision of the ball and the container, and then it will use move to move the system to that moment in time, and then perform the collision using collide. The situation looks like this if a visualisation might help: enter image description here

I have tried to achieve this in my next_collision(self): method, but I am always getting the same type error:

TypeError: time_to_collision() takes 2 positional arguments but 3 were given
sid2001
  • 33
  • 7
  • In `next_collision()` you are calling `self._ball.time_to_collision()` with two arguments `self._ball` and `self._container`, while you should use only the second one: `self._ball.time_to_collision(self._container)`. – bb1 Nov 11 '21 at 00:38
  • Will that account for a collision between the container AND the ball? – sid2001 Nov 11 '21 at 00:44
  • `self._ball.time_to_collision()` is a bound method. When you call it the argument `self` in the definition of `time_to_collision()` automatically becomes `self._ball`. – bb1 Nov 11 '21 at 00:48
  • Beyond the issue you're asking about, here are some other problems I see that will cause you trouble later: You're not initializing all of the attributes that `Ball` methods will expect in `Container.__init__`. You probably want to be calling `super().__init__` with some set of arguments, so that `Ball.__init__` can take care of them for you. A further issue is that you're using mutable default arguments, which is usually a bad idea in Python (see [this question and its answers](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument) for details). – Blckknght Nov 11 '21 at 01:00

1 Answers1

0

Your next_collision method takes just two arguments and you are passing three, just like an error says.

The self argument is passed automatically when you call the method on an object. So you should use it as self._ball.time_to_collision(self._container) to achieve what you want.

Gtzzy
  • 519
  • 4
  • 18