-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontroller.py
More file actions
86 lines (64 loc) · 2.52 KB
/
Copy pathcontroller.py
File metadata and controls
86 lines (64 loc) · 2.52 KB
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
"""
controller.py
A simple PID controller. Tune the gains below and run this file to save C3PO's life.
The final answer would be the name showing on the correct hyperlink.
"""
import base64
import hashlib
import time
from cryptography.fernet import Fernet, InvalidToken
# ==================== TUNE YOUR CONTROLLER ====================
Kp = 0.0
Ki = 0.0
Kd = 0.0
# ================================================================
# ==================== BUILD-TIME EMBEDDED CONFIG ====================
_SALT_B64 = "eShUEgQx+m80w0XCKTvDZA=="
_TOKEN = "gAAAAABqm2zReLhMDeHo2O1PfZK1I33AXZaTZPqouHtQMOwVkejM7wAYRVcj-Ma5Ie9nmVklqg_63s5ymi0IKfMJFSnU_yni_Kzz-9GmZHpm629UKwD0nKg="
_PRECISION = 4
_SCRYPT_N = 262144
_SCRYPT_R = 8
_SCRYPT_P = 1
_WRONG_KEY_B64 = "DC3SfDrdUmKuRje4-zcNkDYTmFaOfkThpd77vihB63M="
_WRONG_TOKEN = "gAAAAABqm2zQdQ8KTlAXZywW5RVKSilyDBAMurTfEVxmnpMdjoJlsdSjToYmDIan0X6NW8nHsILHifz4qsV1C9Xnao9kw5int_P892Sg1Jpmf_vTeGbWdCw="
# ======================================================================
def _canonical(p: float, i: float, d: float, precision: int) -> str:
return f"{p:.{precision}f}|{i:.{precision}f}|{d:.{precision}f}"
def _derive_key(secret_str: str, salt: bytes) -> bytes:
raw = hashlib.scrypt(
secret_str.encode(),
salt=salt,
n=_SCRYPT_N,
r=_SCRYPT_R,
p=_SCRYPT_P,
dklen=32,
maxmem=_SCRYPT_N * _SCRYPT_R * 256,
)
return base64.urlsafe_b64encode(raw)
def _resolve_output(p: float, i: float, d: float):
salt = base64.b64decode(_SALT_B64)
secret_str = _canonical(p, i, d, _PRECISION)
key = _derive_key(secret_str, salt)
try:
return Fernet(key).decrypt(_TOKEN.encode()).decode()
except InvalidToken:
return None
def _resolve_wrong_link() -> str:
return Fernet(_WRONG_KEY_B64.encode()).decrypt(_WRONG_TOKEN.encode()).decode()
def simulate_step(error, integral, prev_error, dt=1.0):
"""One PID update step — output, updated integral, and error."""
integral += error * dt
derivative = (error - prev_error) / dt
output = Kp * error + Ki * integral + Kd * derivative
return output, integral, error
def run_controller():
error, integral, prev_error = 1.0, 0.0, 0.0
for _ in range(5):
output, integral, prev_error = simulate_step(error, integral, prev_error)
error = max(0.0, error - 0.15)
time.sleep(0.05)
result = _resolve_output(Kp, Ki, Kd)
print("Controller output:")
print(result if result else _resolve_wrong_link())
if __name__ == "__main__":
run_controller()