import sys
import numpy as np
class Kinematics:
def __init__(self, *, initial_position: np.ndarray, initial_velocity: np.ndarray):
self._position = initial_position # meters
self._velocity = initial_velocity # meters per second
@property
def position(self) -> np.ndarray:
return self._position
@position.setter
def position(self, val: np.ndarray):
self._position = val
@property
def velocity(self) -> np.ndarray:
return self._velocity
@velocity.setter
def velocity(self, val: np.ndarray):
self._velocity = val
def update_shows_bug(self, *, delta_t: float):
# Tries to combine the getter and setter for self.position
# with the += operator, which will not work.
# Will cause this error:
# Exception has occurred: _UFuncOutputCastingError
# Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
self.position += self.velocity * delta_t
def update_fixes_bug(self, *, delta_t: float):
# Fixes the bug exibited in the 'update_shows_bug' method.
self._position = self.velocity * delta_t + self.position
def main(argv):
# after an elapsed time of 2 seconds, calucate the new position
dt = 2.0 # seconds, elapsed time step
# construct a Kinematics object
x0, y0 = 1000, 2000 # meters
xdot0, ydot0 = 20, 30 # meters per second
k1 = Kinematics(
initial_position=np.array([x0, y0]), initial_velocity=np.array([xdot0, ydot0])
) # m and m/s
k2 = Kinematics(
initial_position=np.array([x0, y0]), initial_velocity=np.array([xdot0, ydot0])
) # m and m/s
# expected updated position is rate * time + initial_position
#
# x-direction
# = (20 m/s) * (2 s) + 1000 m
# = 40 m + 1000 m
# = 1040 m
#
# y-direction
# = (30 m/s) * (2 s) + 2000 m
# = 60 m + 2000 m
# = 2060 m
xf, yf = 1040, 2060 # meters
# k1.update_shows_bug(delta_t=dt) # will trigger error
# new_position_with_bug = k1.position
# assert new_position_with_bug[0] == xf # meters, succeeds
# assert new_position_with_bug[1] == yf # meters, succeeds
k2.update_fixes_bug(delta_t=dt)
new_position_without_bug = k2.position
assert new_position_without_bug[0] == xf # meters, succeeds
assert new_position_without_bug[1] == yf # meters, succeeds
print("Finished.")
if __name__ == "__main__":
main(sys.argv[1:])
|