Cleanup helper scripts. Closes #7
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
const fs = require('fs');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
try {
|
||||
const output = execSync('git log -p -3 src/main.cpp', { cwd: 'm:/Nextcloud/IoT/esp32s3-wiji' });
|
||||
fs.writeFileSync('m:/Nextcloud/IoT/esp32s3-wiji/git_history.txt', output);
|
||||
console.log('Success');
|
||||
} catch (e) {
|
||||
console.log('Error', e.message);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
svg_lines = [
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 175">',
|
||||
' <!-- Background -->',
|
||||
' <rect width="300" height="175" fill="#fdf6e3"/>',
|
||||
' <!-- Decoration on left -->',
|
||||
' <circle cx="75" cy="87.5" r="60" fill="none" stroke="#eee8d5" stroke-width="4" stroke-dasharray="10,5"/>',
|
||||
' <circle cx="75" cy="87.5" r="40" fill="none" stroke="#eee8d5" stroke-width="2" />',
|
||||
' <text x="75" y="87.5" fill="#93a1a1" font-family="sans-serif" font-size="12" text-anchor="middle" font-weight="bold">MECHANISM</text>',
|
||||
' <text x="75" y="102.5" fill="#93a1a1" font-family="sans-serif" font-size="10" text-anchor="middle">CLEARANCE</text>',
|
||||
]
|
||||
|
||||
# X from 150 to 300
|
||||
for row in range(9):
|
||||
y_base = 25 + row * 16
|
||||
svg_lines.append(f' <line x1="155" y1="{y_base}" x2="295" y2="{y_base}" stroke="#e0e0e0" stroke-width="1"/>')
|
||||
svg_lines.append(f' <line x1="155" y1="{y_base-5}" x2="295" y2="{y_base-5}" stroke="#e0e0e0" stroke-width="0.5" stroke-dasharray="2,2"/>')
|
||||
svg_lines.append(f' <line x1="155" y1="{y_base-10}" x2="295" y2="{y_base-10}" stroke="#e0e0e0" stroke-width="1"/>')
|
||||
|
||||
spots = []
|
||||
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
||||
for i, letter in enumerate(alphabet):
|
||||
col = i % 3
|
||||
row = i // 3
|
||||
|
||||
svg_x = 175 + col * 50
|
||||
svg_y = 25 + row * 16
|
||||
|
||||
phys_x = svg_x - 150
|
||||
phys_y = 145 - svg_y
|
||||
|
||||
spots.append({
|
||||
"id": letter,
|
||||
"label": f"{letter.upper()}{letter.lower()}",
|
||||
"x": phys_x,
|
||||
"y": phys_y
|
||||
})
|
||||
|
||||
text_str = f' <text x="{svg_x}" y="{svg_y}" fill="#268bd2" font-family="cursive, \'Comic Sans MS\', sans-serif" font-size="14" font-style="italic" text-anchor="middle">{letter.upper()}{letter.lower()}</text>'
|
||||
svg_lines.append(text_str)
|
||||
|
||||
svg_lines.append('</svg>')
|
||||
|
||||
with open('web/assets/backgrounds/portrait-right/bg.svg', 'w') as f:
|
||||
f.write('\n'.join(svg_lines))
|
||||
|
||||
with open('web/assets/backgrounds/portrait-right/spots.json', 'w') as f:
|
||||
json.dump({
|
||||
"bounds": { "xMin": -150, "xMax": 150, "yMin": -30, "yMax": 145 },
|
||||
"spots": spots
|
||||
}, f, indent=2)
|
||||
@@ -0,0 +1,7 @@
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
|
||||
try {
|
||||
const log = execSync('git log -p -n 10 src/main.cpp', { encoding: 'utf8' });
|
||||
fs.writeFileSync('git_log.txt', log);
|
||||
} catch(e) {}
|
||||
@@ -0,0 +1,20 @@
|
||||
const d2 = 12.9, l1 = 85.0, l2 = 110.0;
|
||||
for(let t1=0; t1<360; t1++){
|
||||
for(let t2=0; t2<360; t2++){
|
||||
let th1 = t1 * Math.PI/180; let th2 = t2 * Math.PI/180;
|
||||
let e1x = -d2 + l1*Math.cos(th1); let e1y = l1*Math.sin(th1);
|
||||
let e2x = d2 + l1*Math.cos(th2); let e2y = l1*Math.sin(th2);
|
||||
let dx = e2x - e1x; let dy = e2y - e1y;
|
||||
let dist = Math.sqrt(dx*dx + dy*dy);
|
||||
if(dist < 1e-6 || dist > 2*l2) continue;
|
||||
let a = dist/2; let h = Math.sqrt(Math.max(0, l2*l2 - a*a));
|
||||
let mx = (e1x+e2x)/2; let my = (e1y+e2y)/2;
|
||||
let px1 = mx + h*(dy/dist); let py1 = my + h*(-dx/dist);
|
||||
let px2 = mx - h*(dy/dist); let py2 = my - h*(-dx/dist);
|
||||
let useFirst = py1 >= py2;
|
||||
let ex = useFirst ? px1 : px2; let ey = useFirst ? py1 : py2;
|
||||
if(Math.abs(ex - 114.4) < 1.0 && Math.abs(ey - 112.7) < 1.0){
|
||||
console.log('Match: t1=' + t1 + ' t2=' + t2 + ' -> ' + ex.toFixed(1) + ', ' + ey.toFixed(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import math
|
||||
|
||||
d2 = 12.9
|
||||
l1 = 85.0
|
||||
l2 = 110.0
|
||||
|
||||
for t1 in range(360):
|
||||
for t2 in range(360):
|
||||
th1 = math.radians(t1)
|
||||
th2 = math.radians(t2)
|
||||
|
||||
e1x = -d2 + l1 * math.cos(th1)
|
||||
e1y = l1 * math.sin(th1)
|
||||
|
||||
e2x = d2 + l1 * math.cos(th2)
|
||||
e2y = l1 * math.sin(th2)
|
||||
|
||||
dx = e2x - e1x
|
||||
dy = e2y - e1y
|
||||
dist = math.sqrt(dx*dx + dy*dy)
|
||||
|
||||
if dist < 1e-6 or dist > 2*l2:
|
||||
continue
|
||||
|
||||
a = dist / 2
|
||||
h2 = l2*l2 - a*a
|
||||
if h2 < 0:
|
||||
h2 = 0
|
||||
h = math.sqrt(h2)
|
||||
|
||||
mx = (e1x + e2x) / 2
|
||||
my = (e1y + e2y) / 2
|
||||
|
||||
px1 = mx + h * (dy / dist)
|
||||
py1 = my + h * (-dx / dist)
|
||||
|
||||
px2 = mx - h * (dy / dist)
|
||||
py2 = my - h * (-dx / dist)
|
||||
|
||||
if py1 >= py2:
|
||||
ex = px1
|
||||
ey = py1
|
||||
else:
|
||||
ex = px2
|
||||
ey = py2
|
||||
|
||||
if abs(ex - 114.4) < 1.0 and abs(ey - 112.7) < 1.0:
|
||||
print(f"Match: t1={t1} t2={t2} -> {ex:.1f}, {ey:.1f}")
|
||||
@@ -0,0 +1,55 @@
|
||||
import asyncio
|
||||
import sys
|
||||
try:
|
||||
from bleak import BleakScanner, BleakClient
|
||||
except ImportError:
|
||||
print("Please install bleak first: pip install bleak")
|
||||
sys.exit(1)
|
||||
|
||||
DEVICE_NAME = "WijiBoard"
|
||||
SERVICE_UUID = "18f3b235-9831-4c75-8ec0-210469b820a0"
|
||||
CMD_UUID = "cd083b06-4447-4cf3-a7c3-322ecf802ce4"
|
||||
STATUS_UUID = "82e38c5b-d3ab-41d1-861c-b84dc6bb1e03"
|
||||
|
||||
async def main():
|
||||
print(f"Scanning for {DEVICE_NAME}...")
|
||||
devices = await BleakScanner.discover(timeout=5.0)
|
||||
|
||||
target_device = None
|
||||
for d in devices:
|
||||
if d.name == DEVICE_NAME:
|
||||
target_device = d
|
||||
break
|
||||
|
||||
if not target_device:
|
||||
print(f"Could not find {DEVICE_NAME}. Make sure it is powered on and advertising.")
|
||||
return
|
||||
|
||||
print(f"Found {DEVICE_NAME} at {target_device.address}. Connecting...")
|
||||
|
||||
async with BleakClient(target_device.address) as client:
|
||||
print(f"Connected: {client.is_connected}")
|
||||
|
||||
# Setup notifications
|
||||
def notification_handler(sender, data):
|
||||
print(f"[STATUS UPDATE] {data.decode('utf-8')}")
|
||||
|
||||
print("Subscribing to status characteristic...")
|
||||
try:
|
||||
await client.start_notify(STATUS_UUID, notification_handler)
|
||||
print("Successfully subscribed!")
|
||||
except Exception as e:
|
||||
print(f"Failed to subscribe: {e}")
|
||||
|
||||
# Send a test command
|
||||
test_cmd = "S1+100"
|
||||
print(f"Sending test command: '{test_cmd}'...")
|
||||
await client.write_gatt_char(CMD_UUID, test_cmd.encode('utf-8'), response=False)
|
||||
|
||||
print("Waiting 5 seconds to receive any status updates...")
|
||||
await asyncio.sleep(5.0)
|
||||
|
||||
print("Disconnecting...")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,41 @@
|
||||
import math
|
||||
|
||||
d2 = 12.9
|
||||
l1 = 85.0
|
||||
l2 = 110.0
|
||||
|
||||
t1_deg = 474 / 2048.0 * 360.0
|
||||
t2_deg = 530 / 2048.0 * 360.0
|
||||
|
||||
th1 = math.radians(t1_deg)
|
||||
th2 = math.radians(t2_deg)
|
||||
|
||||
e1x = -d2 + l1 * math.cos(th1)
|
||||
e1y = l1 * math.sin(th1)
|
||||
|
||||
e2x = d2 + l1 * math.cos(th2)
|
||||
e2y = l1 * math.sin(th2)
|
||||
|
||||
dx = e2x - e1x
|
||||
dy = e2y - e1y
|
||||
dist = math.sqrt(dx*dx + dy*dy)
|
||||
|
||||
a = dist / 2
|
||||
h = math.sqrt(l2*l2 - a*a)
|
||||
|
||||
mx = (e1x + e2x) / 2
|
||||
my = (e1y + e2y) / 2
|
||||
|
||||
px1 = mx + h * (dy / dist)
|
||||
py1 = my + h * (-dx / dist)
|
||||
|
||||
px2 = mx - h * (dy / dist)
|
||||
py2 = my - h * (-dx / dist)
|
||||
|
||||
ex = px1 if py1 >= py2 else px2
|
||||
ey = py1 if py1 >= py2 else py2
|
||||
|
||||
with open("output.txt", "w") as f:
|
||||
f.write(f"End Effector: {ex:.1f}, {ey:.1f}\n")
|
||||
f.write(f"Elbow 1: {e1x:.1f}, {e1y:.1f}\n")
|
||||
f.write(f"Elbow 2: {e2x:.1f}, {e2y:.1f}\n")
|
||||
@@ -0,0 +1,39 @@
|
||||
const ARM = { d2: 12.9, l1: 85.0, l2: 110.0, STEPS_PER_REV: 2048 };
|
||||
const HOME_STEPS = { m1: 1024, m2: 0 };
|
||||
|
||||
function solve(x, y) {
|
||||
const { d2, l1, l2 } = ARM;
|
||||
const xpd = x + d2;
|
||||
const t = Math.sqrt(xpd * xpd + y * y);
|
||||
const cosW2 = (l2 * l2 - t * t - l1 * l1) / (-2 * l1 * t);
|
||||
const r = Math.atan2(y, xpd);
|
||||
const w2 = Math.acos(cosW2);
|
||||
const theta1 = r + w2;
|
||||
|
||||
const xmd = x - d2;
|
||||
const s = Math.sqrt(xmd * xmd + y * y);
|
||||
const cosW1 = (l2 * l2 - s * s - l1 * l1) / (-2 * l1 * s);
|
||||
const q = Math.atan2(y, xmd);
|
||||
const w1 = Math.acos(cosW1);
|
||||
const theta2 = q - w1;
|
||||
return { theta1, theta2 };
|
||||
}
|
||||
|
||||
function radToSteps(rad) { return Math.round((rad / (2 * Math.PI)) * ARM.STEPS_PER_REV); }
|
||||
|
||||
const targetX = 115, targetY = 113;
|
||||
const { theta1, theta2 } = solve(targetX, targetY);
|
||||
console.log(`Target: (${targetX}, ${targetY})`);
|
||||
console.log(`theta1: ${theta1 * 180 / Math.PI} deg`);
|
||||
console.log(`theta2: ${theta2 * 180 / Math.PI} deg`);
|
||||
|
||||
const newSteps1 = radToSteps(theta1);
|
||||
const newSteps2 = radToSteps(theta2);
|
||||
console.log(`newSteps1: ${newSteps1}`);
|
||||
console.log(`newSteps2: ${newSteps2}`);
|
||||
|
||||
console.log(`delta1 from HOME_STEPS.m1 (1024): ${newSteps1 - HOME_STEPS.m1}`);
|
||||
console.log(`delta2 from HOME_STEPS.m2 (0): ${newSteps2 - HOME_STEPS.m2}`);
|
||||
|
||||
const delta1_old = newSteps1 - (-1024);
|
||||
console.log(`delta1 from OLD_HOME_STEPS.m1 (-1024): ${delta1_old}`);
|
||||
@@ -0,0 +1,47 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const d2 = 12.9;
|
||||
const l1 = 85;
|
||||
const l2 = 110;
|
||||
|
||||
function stepsToRad(steps) {
|
||||
return (steps / 2048) * 2 * Math.PI;
|
||||
}
|
||||
|
||||
function render(steps1, steps2) {
|
||||
const t1 = stepsToRad(steps1);
|
||||
const t2 = stepsToRad(steps2);
|
||||
|
||||
const e1x = -d2 + l1 * Math.cos(t1);
|
||||
const e1y = l1 * Math.sin(t1);
|
||||
|
||||
const e2x = d2 + l1 * Math.cos(t2);
|
||||
const e2y = l1 * Math.sin(t2);
|
||||
|
||||
const dx = e2x - e1x;
|
||||
const dy = e2y - e1y;
|
||||
const dist = Math.sqrt(dx*dx + dy*dy);
|
||||
|
||||
let endX = 0, endY = 0;
|
||||
if (dist <= 2*l2 && dist >= 1e-6) {
|
||||
const a = dist / 2;
|
||||
const h = Math.sqrt(l2*l2 - a*a);
|
||||
const mx = (e1x + e2x) / 2;
|
||||
const my = (e1y + e2y) / 2;
|
||||
const px1 = mx + h * (dy / dist);
|
||||
const py1 = my + h * (-dx / dist);
|
||||
const px2 = mx - h * (dy / dist);
|
||||
const py2 = my - h * (-dx / dist);
|
||||
if (py1 >= py2) { endX = px1; endY = py1; }
|
||||
else { endX = px2; endY = py2; }
|
||||
}
|
||||
|
||||
console.log(`steps1=${steps1}, steps2=${steps2}`);
|
||||
console.log(`t1=${(t1*180/Math.PI).toFixed(1)}°, t2=${(t2*180/Math.PI).toFixed(1)}°`);
|
||||
console.log(`e1=(${e1x.toFixed(1)}, ${e1y.toFixed(1)})`);
|
||||
console.log(`e2=(${e2x.toFixed(1)}, ${e2y.toFixed(1)})`);
|
||||
console.log(`end=(${endX.toFixed(1)}, ${endY.toFixed(1)})`);
|
||||
}
|
||||
|
||||
render(854, 41);
|
||||
render(-41, 967);
|
||||
Reference in New Issue
Block a user