def test_get_distance(self): for tup in self.dot_value: checked_vector = Vector(tup[0]) helping_vector = Vector(tup[1]) result = checked_vector.get_distance(helping_vector) self.assertAlmostEqual(sqrt((tup[0][0] - tup[1][0]) ** 2 + (tup[0][1] - tup[1][1]) ** 2), result)
class PhysicsObject(object): COEFFICIENT_OF_FRICTION = 0.99 COEFFICIENT_OF_BORDER_COLLISION = 0.8 MAX_MALLET_VELOCITY = 25 MAX_DISC_VELOCITY = 50 STOPPING_VELOCITY = 0.1 def __init__(self, x_init, y_init, mass, radius, borders): Logger.debug("KINEMATICS: PhysicsObject init(x_init=%s, y_init=%s, mass=%s, radius=%s, borders=%s)", str(x_init), str(y_init), str(mass), str(radius), str(borders)) self._pos = Vector(x_init, y_init) self._mass = mass self._radius = radius self._vel = Vector(0, 0) self._borders = borders # TODO: Add unittests def friction(self): Logger.debug("KINEMATICS: friction vel before = %s", str(self._vel)) self._vel.length *= self.COEFFICIENT_OF_FRICTION self._vel.length = 0 if self._vel.length < self.STOPPING_VELOCITY else self._vel.length Logger.debug("KINEMATICS: friction vel after = %s", str(self._vel)) def collision_effect(self): # TODO: a proper calculation of momentum and change in speed after collisions Logger.debug("KINEMATICS: collision_effect vel before = %s", str(self._vel)) self._vel.length *= self.COEFFICIENT_OF_BORDER_COLLISION Logger.debug("KINEMATICS: collision_effect vel after = %s", str(self._vel)) def correct_position_in_borders(self): """ Dislodges objects stuck in the pitch borders """ x_min, x_max = self._borders[0] y_min, y_max = self._borders[1] log = False if self.pos.x - self.radius < x_min: self.pos.x = x_min+self.radius log = True if self.pos.x + self.radius > x_max: self.pos.x = x_max-self.radius log = True if self.pos.y - self.radius < y_min: self.pos.y = y_min+self.radius log = True if self.pos.y + self.radius > y_max: self.pos.y = y_max-self.radius log = True if log: Logger.debug("KINEMATICS: correct_position_in_borders pos.x=%s pos.y=%s", str(self.pos.x), str(self.pos.y)) def correct_position_post_collision(self, obj): """ Dislodges objects stuck in each other. """ distance_vector = self.pos - obj.pos if distance_vector.length < self.radius + obj.radius: distance_vector.length = self.radius + obj.radius self._pos = obj.pos + distance_vector self.correct_position_in_borders() Logger.debug("KINEMATICS: correct_position_post_collision distance_vector=%s self.radius=%s obj.radius=%s", str(distance_vector), str(self.radius), str(obj.radius)) distance_vector = obj.pos - self.pos if distance_vector.length < obj.pos - self.pos: distance_vector.length = self.radius + obj.radius obj._pos = self._pos + distance_vector obj.correct_position_in_borders() Logger.debug("KINEMATICS: correct_position_post_collision distance_vector=%s self.radius=%s obj.radius=%s", str(distance_vector), str(self.radius), str(obj.radius)) # TODO: Add common move_to and move methods for mallet and disc def apply_speed_limit(self): from data.Disc import Disc from data.Mallet import Mallet Logger.debug("KINEMATICS: apply_speed_limit MAX_DISC_VELOCITY=%s MAX_MALLET_VELOCITY=%s vel=%s", str(self.MAX_DISC_VELOCITY), str(self.MAX_MALLET_VELOCITY), str(self._vel.length)) if isinstance(self, Disc) and self._vel.length > self.MAX_DISC_VELOCITY: Logger.debug("KINEMATICS: apply_speed_limit is a Disc") self._vel.length = self.MAX_DISC_VELOCITY if isinstance(self, Mallet) and self._vel.length > self.MAX_MALLET_VELOCITY: Logger.debug("KINEMATICS: apply_speed_limit is a Mallet") self._vel.length = self.MAX_MALLET_VELOCITY # TODO: Add unittests def border_collision(self, axis): from data.Disc import Disc Logger.debug("KINEMATICS: border_collision axis=%s _vel=%s", str(axis), str(self._vel)) if isinstance(self, Disc): if axis == 'x': self._vel.x = -self._vel.x self.collision_effect() self.correct_position_in_borders() if axis == 'y': self._vel.y = -self._vel.y self.collision_effect() self.correct_position_in_borders() Logger.debug("KINEMATICS: _vel=%s", str(self._vel)) # TODO: Add unittests def circle_collision(self, object): from data.Disc import Disc if self._pos.get_distance(object.pos) <= self._radius+object.radius: Logger.debug("KINEMATICS: border_collision distance=%s self.radius=%s object.radius=%s", str(self._pos.get_distance(object.pos)), str(self._radius), str(object.radius)) vec_pos_diff = object.pos - self._pos vec_to = self._vel.projection(vec_pos_diff) obj_vec_to = object._vel.projection(vec_pos_diff) vec_side = self._vel - vec_to obj_vec_side = object._vel - obj_vec_to after_vec_to = (vec_to*(self._mass-object._mass) + (2 * object._mass * obj_vec_to))/(self._mass + object._mass) after_obj_vec_to = (obj_vec_to*(object._mass - self._mass) + (2 * self._mass * vec_to))/(self._mass + object._mass) # Change velocity only if it is Disc if isinstance(self, Disc): self._vel = after_vec_to + vec_side if isinstance(object, Disc): object._vel = after_obj_vec_to + obj_vec_side self.apply_speed_limit() self.correct_position_post_collision(object)