Spaces:
Build error
Build error
File size: 4,825 Bytes
4fa8bcb |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
import math
import numpy as np
class PhysicsSimulator:
def __init__(self, gravity=9.8, dt=0.1):
"""
Initialize the physics simulator environment.
Args:
gravity (float): Gravitational acceleration (m/s^2)
dt (float): Time step size in seconds
"""
self.gravity = gravity
self.dt = dt
def simulate_ball_motion(self, mass, angle, friction, time_steps=50, height=64, width=64):
"""
Simulate ball rolling down a ramp.
Args:
mass (float): Mass of ball (currently not affecting result)
angle (float): Angle of ramp in degrees
friction (float): Coefficient of friction
time_steps (int): Number of timesteps
Returns:
List of positions over time.
"""
acc = self.gravity * math.sin(math.radians(angle)) - friction * self.gravity * math.cos(math.radians(angle))
velocity = 0
s = 0
coords = []
# Start from top-left of the frame
ramp_start = (0, 0)
# Compute ramp end point based on angle and frame size
rad = math.radians(angle)
dx = math.cos(rad) # → right
dy = math.sin(rad)
# Normalize the ramp to fill the diagonal range of the frame
length_scale = min(width / abs(dx) if dx != 0 else float('inf'),
height / abs(dy) if dy != 0 else float('inf'))
ramp_end = (
ramp_start[0] + dx * length_scale,
ramp_start[1] + dy * length_scale
)
ramp_length = math.hypot(ramp_end[0] - ramp_start[0], ramp_end[1] - ramp_start[1])
for _ in range(time_steps):
velocity += acc * self.dt
s += velocity * self.dt
s = max(0, min(s, ramp_length))
normalized = s / ramp_length
# Compute current position along the ramp
x = ramp_start[0] + normalized * (ramp_end[0] - ramp_start[0])
y = ramp_start[1] + normalized * (ramp_end[1] - ramp_start[1])
# Draw position in a blank image
coord = np.zeros((height, width), dtype=np.float32)
# Convert to integer coordinates and ensure they're within bounds
xi = int(round(min(max(x, 0), width - 1)))
yi = int(round(min(max(y, 0), height - 1)))
coord[yi, xi] = 1.0
coords.append(coord)
return coords
def simulate_projectile_motion(self, initial_velocity, angle, gravity, time_steps):
"""
Simulate projectile motion of a particle launched with an initial velocity and angle.
Args:
initial_velocity (float): initial speed in m/s
angle (float): launch angle in degrees
gravity (float): gravitational constant (usually 9.8)
time_steps (int): number of simulation steps
Returns:
List of coordinates where each coordinate is a 2D array with a single point marked as 1.0
"""
angle_rad = np.deg2rad(angle)
v_x = initial_velocity * np.cos(angle_rad)
v_y = initial_velocity * np.sin(angle_rad)
coords = []
x, y = 0.0, 0.0
for t in range(time_steps):
# Debug
# print(f"t={t}: BEFORE x={x:.2f}, y={y:.2f}")
# Normalize to fit in 64x64 frame (arbitrary scaling)
x_norm = min(max(x / 100.0, 0.0), 1.0) # scale x max to ~100 meters
y_norm = min(max(y / 100.0, 0.0), 1.0) # scale y max to ~100 meters
# stop when object hits the an edge of the frame
if y_norm < 0 or x_norm > 1.0 or x_norm < 0.0 or y_norm > 1.0:
break
# Create a coordinate frame with the point marked
coord = np.zeros((64, 64), dtype=np.float32)
xi = int(round(x_norm * 63))
yi = int(round((1.0 - y_norm) * 63)) # invert y for image coordinates
if 0 <= xi < 64 and 0 <= yi < 64:
coord[yi, xi] = 1.0
coords.append(coord)
# Debug
# print(f"t={t}: x={x:.2f}, y={y:.2f}, v_x={v_x:.2f}, v_y={v_y:.2f}")
# Update position
x += v_x * self.dt
y += v_y * self.dt
v_y -= gravity * self.dt # gravity reduces vertical velocity
# Pad to maintain consistent sequence length
while len(coords) < time_steps:
coords.append(np.zeros((64, 64), dtype=np.float32))
return coords
if __name__ == "__main__":
simulator = PhysicsSimulator(gravity=9.8, dt=0.1)
positions = simulator.simulate_ball_motion(mass=0.15, angle=30, friction=0.05, time_steps=50)
print(positions) |