Compare commits

..

1 Commits

Author SHA1 Message Date
e6ce15aee9 Formatting 2026-01-15 18:36:56 +01:00
7 changed files with 43 additions and 40 deletions

2
.gitignore vendored
View File

@@ -1 +1 @@
__pycache__/ __pycache__

View File

@@ -5,6 +5,7 @@ unit_x = np.array([1, 0, 0])
unit_y = np.array([0, 1, 0]) unit_y = np.array([0, 1, 0])
unit_z = np.array([0, 0, 1]) unit_z = np.array([0, 0, 1])
def get_axis(axis): def get_axis(axis):
"Axis are numbered from 1 to 3 from x to z." "Axis are numbered from 1 to 3 from x to z."
match axis: match axis:
@@ -18,11 +19,13 @@ def get_axis(axis):
ax = unit_x ax = unit_x
return ax return ax
def proj(vec, axis: int = 1): def proj(vec, axis: int = 1):
"""Simple vector projection onto an axis.""" """Simple vector projection onto an axis."""
ax = get_axis(axis) ax = get_axis(axis)
return np.dot(vec, ax) * ax return np.dot(vec, ax) * ax
def rotate(v, angle=90, axis=1): def rotate(v, angle=90, axis=1):
"Rotate a vector with an angle around a axis with the right hand rule." "Rotate a vector with an angle around a axis with the right hand rule."
angle = angle / 180 * np.pi angle = angle / 180 * np.pi
@@ -34,9 +37,15 @@ def rotate(v, angle=90, axis=1):
+ k * np.dot(k, v) * (1 - np.cos(angle)) + k * np.dot(k, v) * (1 - np.cos(angle))
) )
def agl(a, b): def agl(a, b):
"Get the angle between two vectors. This is always between 0 and 180 degree." "Get the angle between two vectors. This is always between 0 and 180 degree."
return np.round(np.acos(np.dot(a, b)/(np.linalg.norm(a) * np.linalg.norm(b)))/(2 * np.pi) * 360) return np.round(
np.acos(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
/ (2 * np.pi)
* 360
)
def get_angles(source, target): def get_angles(source, target):
"""Main function to get the phi and theta angles for a source and a target vector. Both vectors must lie on the front half sphere. """Main function to get the phi and theta angles for a source and a target vector. Both vectors must lie on the front half sphere.

9
helpers.py Normal file
View File

@@ -0,0 +1,9 @@
from objects.world import World
def print_status(world: World):
for i, mirror in enumerate(world.mirrors):
phi, theta = mirror.get_angles()
print(
f"Mirror {i} ({mirror.cluster_x}, {mirror.cluster_y}) angles -> phi: {phi:.2f}°, theta: {theta:.2f}°"
)

View File

@@ -1,3 +1,8 @@
"""
When theta motor is at 0 then mirror is up and when at 180 then mirror is front.
Phi 0 equals right and phi 180 equals left by 45 degrees.
"""
import numpy as np import numpy as np
from objects.generic import Source, Target from objects.generic import Source, Target
@@ -5,9 +10,10 @@ from objects.motor import Motor
from calculator import get_angles from calculator import get_angles
class Mirror: class Mirror:
def __init__(self, world, cluster_x=0, cluster_y=0): def __init__(self, world, cluster_x=0, cluster_y=0):
self.world = world self.world = world # TODO: Fix this cyclic reference
self.cluster_x = cluster_x self.cluster_x = cluster_x
self.cluster_y = cluster_y self.cluster_y = cluster_y
@@ -32,7 +38,7 @@ class Mirror:
rel_source = source.pos - rot_pos rel_source = source.pos - rot_pos
rel_target = target.pos - rot_pos rel_target = target.pos - rot_pos
phi, theta = get_angles(rel_source, rel_target) # ty:ignore[unresolved-reference] phi, theta = get_angles(rel_source, rel_target)
# Update the angles based on the normals in rotated positions # Update the angles based on the normals in rotated positions
self.motor_phi.set_angle(phi) self.motor_phi.set_angle(phi)

View File

@@ -53,3 +53,4 @@ class World:
y_rot = y y_rot = y
z_rot = -x * sin_t + z * cos_t z_rot = -x * sin_t + z * cos_t
return np.array([x_rot, y_rot, z_rot]) return np.array([x_rot, y_rot, z_rot])

View File

@@ -1,3 +1,4 @@
from helpers import print_status
import time import time
from objects.generic import Source, Target from objects.generic import Source, Target
@@ -6,42 +7,21 @@ from objects.mirror import Mirror
from objects.board import Board from objects.board import Board
# Solar module for simulation of world # Solar module for simulation of world
STEP = 10
LOOP_DELAY = 0.005 # In seconds LOOP_DELAY = 0.005 # In seconds
# Testing embedding the mirrors in the world # Testing embedding the mirrors in the world
board = Board() board = Board()
world = World(board, tilt_deg=0) world = World(board, tilt_deg=0)
HEIGHT = 30
source = Source(world, pos=(0, 50, 0)) source = Source(world, pos=(0, 50, 0))
target = Target(world, pos=(0, 50, 0)) target = Target(world, pos=(0, 50, 0))
# Create mirrors in a 3x2 grid # Create mirrors in a grid
for x in range(2): for x in range(2):
for y in range(1): for y in range(1):
mirror = Mirror(world, cluster_x=x, cluster_y=y) mirror = Mirror(world, cluster_x=x, cluster_y=y)
world.add_mirror(mirror) world.add_mirror(mirror)
world.update_mirrors_from_source_target(source, target)
def print_status():
for i, mirror in enumerate(world.mirrors):
phi, theta = mirror.get_angles()
print(f"Mirror {i} ({mirror.cluster_x}, {mirror.cluster_y}) angles -> phi: {phi:.2f}°, theta: {theta:.2f}°")
a = 1
t = time.time()
world.mirrors[0].motor_theta.set_angle(180)
world.mirrors[0].motor_phi.set_angle(180)
world.mirrors[1].motor_phi.set_angle(0)
world.mirrors[1].motor_theta.set_angle(0)
print_status()
# Main # Main
try: try:
while True: while True:
@@ -51,11 +31,9 @@ try:
#print(target.pos) #print(target.pos)
world.update_mirrors_from_source_target(source, target) world.update_mirrors_from_source_target(source, target)
print_status() print_status(world)
time.sleep(LOOP_DELAY) time.sleep(LOOP_DELAY)
t = time.time()
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass

2
uv.lock generated
View File

@@ -516,7 +516,7 @@ wheels = [
[[package]] [[package]]
name = "solarmotor" name = "solarmotor"
version = "0.1.0" version = "0.1.1"
source = { virtual = "." } source = { virtual = "." }
dependencies = [ dependencies = [
{ name = "adafruit-blinka" }, { name = "adafruit-blinka" },