id changes through motor panel work now (was sending new id as target

node_mode
Jake 2025-11-02 14:22:00 +08:00
parent 9036014e21
commit 5a9eee688b
5 changed files with 103 additions and 47 deletions

View File

@ -143,7 +143,7 @@ export class CurveEditor {
endPoint: { x: this.timelineLength * this.pixelsPerSecond, y: this.canvas.height / 2 } endPoint: { x: this.timelineLength * this.pixelsPerSecond, y: this.canvas.height / 2 }
} }
]); ]);
console.log("TL LENGTH: " + this.timelineLength); //console.log("TL LENGTH: " + this.timelineLength);
this.curveSets[motorID] = this.curves; this.curveSets[motorID] = this.curves;
} }

View File

@ -31,7 +31,7 @@ export class ServoMotor {
this.CURRENT_CURRENT = (payload[30] << 8) | payload[31]; this.CURRENT_CURRENT = (payload[30] << 8) | payload[31];
this.VOLTAGE = payload[32]; this.VOLTAGE = payload[32];
} else { } else {
// Simplified constructor // Simplified constructor used by robot config loader
this.CHANNEL = arg1; this.CHANNEL = arg1;
this.ID = arg2; this.ID = arg2;
@ -44,7 +44,7 @@ export class ServoMotor {
// Takes Motor object and updates simulated value, returns packet for real device // Takes Motor object and updates simulated value, returns packet for real device
export function writeData(motor, key) { export function writeData(targetID, motor, key) {
const entry = DataMap[key]; const entry = DataMap[key];
if (!entry) { if (!entry) {
throw new Error(`Invalid data key: ${key}`); throw new Error(`Invalid data key: ${key}`);
@ -68,7 +68,7 @@ export function writeData(motor, key) {
} }
} }
const packet = [motor.CHANNEL, motor.ID, address, length]; // channel, id, address, value const packet = [motor.CHANNEL, targetID, address, length]; // channel, id, address, value
if (length === 2) { if (length === 2) {
packet.push(value & 0xFF); packet.push(value & 0xFF);

View File

@ -27,8 +27,8 @@ export class NodeEditor {
} }
generateDefaultNodes(curveSets, motorIDs) { generateDefaultNodes(curveSets, motorIDs) {
console.log("Generating Default Nodes"); //console.log("Generating Default Nodes");
console.log(curveSets, motorIDs); //console.log(curveSets, motorIDs);
for (var i = 0; i < motorIDs.length; i++) { for (var i = 0; i < motorIDs.length; i++) {
let inputNode = this.addCurveNode(200, 20 + i * 140, "Curve", motorIDs[i]); let inputNode = this.addCurveNode(200, 20 + i * 140, "Curve", motorIDs[i]);

View File

@ -1,4 +1,4 @@
import { ServoMotor } from './feetechDefinitions.js'; import { getModelType, ServoMotor } from './feetechDefinitions.js';
export class Robot { export class Robot {
constructor(name, firmwareVersionId) { constructor(name, firmwareVersionId) {
@ -6,7 +6,8 @@ export class Robot {
this.firmwareVersion = { major: 0, minor: 0 }; this.firmwareVersion = { major: 0, minor: 0 };
// Map of position ID → ServoMotor // Map of position ID → ServoMotor
this.positionMap = new Map(); //this.positionMap = new Map();
this.motors = [];
} }
// Assign a motor to a position // Assign a motor to a position
@ -14,39 +15,38 @@ export class Robot {
if (!(motor instanceof ServoMotor)) { if (!(motor instanceof ServoMotor)) {
throw new Error('Assigned motor must be a ServoMotor instance'); throw new Error('Assigned motor must be a ServoMotor instance');
} }
this.positionMap.set(positionId, motor); //this.positionMap.set(positionId, motor);
this.motors.push(motor);
} }
// Get motor assigned to a position getMotor(motorID) {
getMotor(positionId) { for (let i = 0; i < this.motors.length; i++) {
return this.positionMap.get(positionId); console.log(motorID, this.motors[i].ID);
if (String(this.motors[i].ID) === String(motorID)) {
return this.motors[i];
}
} }
return null;
}
// Remove motor from a position // Remove motor from a position
removeMotor(positionId) { removeMotor(motorID) {
this.positionMap.delete(positionId); this.motors = this.motors.filter(motor => motor.ID !== motorID);
} }
// Get all position assignments
getAllAssignments() {
const assignments = [];
for (const [position, motor] of this.positionMap.entries()) {
assignments.push({ position, motor });
}
return assignments;
}
// Optional: Find position by motor ID // Optional: Find position by motor ID
findPositionByMotorId(id) { // findPositionByMotorId(id) {
for (const [position, motor] of this.positionMap.entries()) { // for (const [position, motor] of this.positionMap.entries()) {
if (motor.ID === id) return position; // if (motor.ID === id) return position;
} // }
return null; // return null;
} // }
static fromBytes(bytes) { static fromBytes(bytes) {
console.log("Loading Robot from:"); console.log("Loading Robot from:");
console.log(bytes); //console.log(bytes);
const data = bytes instanceof Uint8Array ? bytes : Uint8Array.from(bytes); const data = bytes instanceof Uint8Array ? bytes : Uint8Array.from(bytes);
let offset = 0; let offset = 0;
@ -73,8 +73,12 @@ export class Robot {
const name = String.fromCharCode(...data.slice(offset, offset + nameLen)); const name = String.fromCharCode(...data.slice(offset, offset + nameLen));
offset += nameLen; offset += nameLen;
const modelMajor = data[offset++];
const modelMinor = data[offset++];
const modelType = getModelType(modelMajor, modelMinor);
const position = (data[offset++] << 8) | data[offset++]; const position = (data[offset++] << 8) | data[offset++];
const motor = new ServoMotor(0, motorID, null, name); const motor = new ServoMotor(0, motorID, modelType, name);
robot.assignMotor(motorID, motor); // motorID used as position ID robot.assignMotor(motorID, motor); // motorID used as position ID
} }

View File

@ -34,7 +34,42 @@ window.onload = () => {
const dialColors = ['red', 'green', 'blue', 'orange', 'purple']; const dialColors = [
'#F50057', // Raspberry
'#6200EA', // Deep Violet
'#FFB400', // Bright Amber
'#2979FF', // Royal Blue
'#FF5252', // Coral Red
'#00C853', // Vivid Green
'#FF80AB', // Bubblegum
'#00B8D4', // Sky Cyan
'#FF9100', // Neon Orange
'#651FFF', // Electric Indigo
'#FF4F81', // Vibrant Pink
'#AEEA00', // Chartreuse
'#FFAB40', // Sunset Orange
'#00E5FF', // Aqua
'#FF6F00', // Vivid Orange
'#64DD17', // Leaf Green
'#FFEA00', // Vivid Yellow
'#C51162', // Deep Rose
'#40C4FF', // Sky Blue
'#D500F9', // Vivid Purple
'#76FF03', // Lime Green
'#FF4081', // Hot Pink
'#00B0FF', // Electric Blue
'#FF1744', // Crimson
'#B388FF', // Soft Violet
'#1DE9B6', // Minty Teal
'#AA00FF', // Vivid Lavender
'#FFB347', // Pastel Orange
'#00C1D4', // Bright Cyan
'#7C4DFF' // Neon Purple
];
let dials = []; let dials = [];
const frameSlider = document.getElementById('frameSlider'); const frameSlider = document.getElementById('frameSlider');
@ -44,7 +79,7 @@ window.onload = () => {
const curveCanvas = document.getElementById('curveCanvas'); const curveCanvas = document.getElementById('curveCanvas');
const curveEditor = new CurveEditor(curveCanvas, 6, frameSlider); const curveEditor = new CurveEditor(curveCanvas, 10, frameSlider);
// Animation File List // Animation File List
@ -77,13 +112,14 @@ window.onload = () => {
console.log(connectedRobot); console.log(connectedRobot);
let motorIDList = [] let motorIDList = []
clearDials(); clearDials();
for (const [position, motor] of connectedRobot.positionMap.entries()) { for (const motor of connectedRobot.motors) {
console.log(`Assigning ${position} motor with ID ${motor.ID}`);
curveEditor.addChannel(motor.ID); curveEditor.addChannel(motor.ID);
motorIDList.push(motor.ID); motorIDList.push(motor.ID);
addDial(motor.ID, motor.NAME); addDial(motor.ID, motor.NAME);
} }
setSelectedMotor(10); if (connectedRobot.motors.length > 0){
setSelectedMotor(connectedRobot.motors[0].ID);
}
nodeEditor = new NodeEditor(nodeCanvas, { nodeEditor = new NodeEditor(nodeCanvas, {
@ -95,7 +131,7 @@ window.onload = () => {
function setSelectedMotor(motorID) { function setSelectedMotor(motorID) {
console.log(motorID); //console.log(motorID);
curveEditor.selectMotor(motorID); curveEditor.selectMotor(motorID);
selectedDial = motorID; selectedDial = motorID;
@ -109,7 +145,7 @@ window.onload = () => {
} }
}); });
console.log("Selected motor:", motorID); //console.log("Selected motor:", motorID);
// Any other logic you want to run // Any other logic you want to run
@ -134,8 +170,7 @@ window.onload = () => {
// Retrieve motor by position // Retrieve motor by position
//console.log(robot.getMotor('eyelids')); //console.log(robot.getMotor('eyelids'));
// List all assignments
console.log(robot.getAllAssignments());
return robot; return robot;
} }
@ -417,12 +452,15 @@ window.onload = () => {
case 0x06: // CMD_MESSAGE case 0x06: // CMD_MESSAGE
console.log(`Message Recieved`); //console.log(`Message Recieved`);
const decoder = new TextDecoder(); const decoder = new TextDecoder();
console.log(payload); //console.log(payload);
const stringPayload = decoder.decode(new Uint8Array(payload)); const stringPayload = decoder.decode(new Uint8Array(payload));
console.log(stringPayload); //console.log(stringPayload);
document.getElementById('log').value += "MSG: " + stringPayload + `\n`; document.getElementById('log').value += "MSG: " + stringPayload + `\n`;
const logBox = document.getElementById('log');
logBox.value += "MSG: " + stringPayload + `\n`;
logBox.scrollTop = logBox.scrollHeight;
// 🔹 Do something with the file // 🔹 Do something with the file
//handleLoadedFile(fileData); //handleLoadedFile(fileData);
break; break;
@ -479,15 +517,21 @@ window.onload = () => {
}); });
function handlePositionStreamPacket(data) { function handlePositionStreamPacket(data) {
for (let i = 0; i < 5; i++) { const motorCount = Math.floor(data.length / 2); // Each motor uses 2 bytes
const high = data[i * 2]; // High byte
const low = data[i * 2 + 1]; // Low byte
const value = (high << 8) | low; // Combine into uint16_t
for (let i = 0; i < motorCount; i++) {
const high = data[i * 2]; // High byte
const low = data[i * 2 + 1]; // Low byte
const value = (high << 8) | low; // Combine into uint16_t
if (dials[i]) {
dials[i].value = value; dials[i].value = value;
} }
} }
console.log(data);
}
function handleLoadedFile(data) { function handleLoadedFile(data) {
const raw = new Uint8Array(data); const raw = new Uint8Array(data);
const view = new DataView(raw.buffer); const view = new DataView(raw.buffer);
@ -1033,7 +1077,9 @@ window.onload = () => {
let dataKey = packets[i].title; let dataKey = packets[i].title;
let value = packets[i].value; let value = packets[i].value;
servoMotor[dataKey] = value; servoMotor[dataKey] = value;
let dataPacket = writeData(servoMotor, dataKey); let dataPacket = writeData(packets[i].id, servoMotor, dataKey);
//dataPacket[1] = packets[i].id;
console.log(dataPacket);
serial.requestWriteData(dataPacket); serial.requestWriteData(dataPacket);
} }
console.log(servoMotors); console.log(servoMotors);
@ -1073,6 +1119,12 @@ window.onload = () => {
console.log(motor.MODEL, motor.POSITION, motor.CURRENT_SPEED); console.log(motor.MODEL, motor.POSITION, motor.CURRENT_SPEED);
servoMotors[motor.CHANNEL].push(motor); servoMotors[motor.CHANNEL].push(motor);
// If motor is in robot config already, grab the name
let configMotor = connectedRobot.getMotor(motor.ID);
if (configMotor != null){
motor.NAME = configMotor.NAME;
}
insertTableRow(motor); insertTableRow(motor);
} }