nodegraph and nodes defined and receiveable from web interface packet
parent
9e3979f4d6
commit
29758d8abf
|
|
@ -2,6 +2,7 @@
|
|||
#include <base64.h>
|
||||
#include "feetech.h"
|
||||
#include "animation.h"
|
||||
#include "nodegraph.h"
|
||||
|
||||
#define DEVICE_NAME "Little Sophia"
|
||||
#define FIRMWARE_VERSION "0.0.1"
|
||||
|
|
@ -101,6 +102,7 @@ const uint16_t testPayloadLength = sizeof(testPayload);
|
|||
|
||||
void setup() {
|
||||
Serial.begin(1000000);
|
||||
Serial.setRxBufferSize(1024);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Serial.println(i);
|
||||
delay(500);
|
||||
|
|
@ -137,11 +139,11 @@ void setup() {
|
|||
|
||||
// anim.saveToFile("/scurve.anim");
|
||||
// Serial.println("SAVED");
|
||||
//handleSaveFile(testPayload, testPayloadLength);
|
||||
Serial.println("Loading test.anim");
|
||||
anim.loadFromFile("/test.anim");
|
||||
Serial.println(anim.header.frameCount);
|
||||
anim.printCurves();
|
||||
//handleSaveFile(testPayload, testPayloadLength);
|
||||
Serial.println("Loading test.anim");
|
||||
anim.loadFromFile("/test.anim");
|
||||
Serial.println(anim.header.frameCount);
|
||||
anim.printCurves();
|
||||
// Serial.print("CurveSegment size: ");
|
||||
// Serial.println(sizeof(CurveSegment));
|
||||
//anim.createBasicSCurve();
|
||||
|
|
@ -682,6 +684,25 @@ bool parseAnimationPayload(const uint8_t* payload, uint16_t length, Animation& a
|
|||
ptr += sizeof(CurveSegment);
|
||||
}
|
||||
|
||||
// ✅ Advance ptr to node graph payload
|
||||
//ptr += curveCount * sizeof(CurveSegment);
|
||||
|
||||
// 🔹 Parse node graph
|
||||
uint8_t nodeCount = ptr[0];
|
||||
Serial.print("Node count: ");
|
||||
Serial.println(nodeCount);
|
||||
sendMessage(String("Node count: ") + String(nodeCount));
|
||||
sendMessage(String("ptr offset: ") + String(ptr - payload));
|
||||
|
||||
|
||||
uint16_t remainingLength = length - (ptr - payload);
|
||||
if (remainingLength > 0) {
|
||||
loadNodeGraph(ptr, remainingLength, animation.nodeGraph);
|
||||
} else {
|
||||
Serial.println("No node graph data found");
|
||||
}
|
||||
sendMessage(printNodeGraph(animation.nodeGraph));
|
||||
|
||||
// 🔹 Save using received filename
|
||||
animation.saveToFile(("/" + String(filename)).c_str());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef ANIMATION_FILE_H
|
||||
#define ANIMATION_FILE_H
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "FS.h"
|
||||
#include "FFat.h"
|
||||
#include <unordered_map>
|
||||
#include "nodegraph.h"
|
||||
|
||||
|
||||
#define NUM_CHANNELS 5
|
||||
|
|
@ -60,6 +60,8 @@ public:
|
|||
void createBasicSCurve();
|
||||
void createEaseOutCurve();
|
||||
AnimationHeader header;
|
||||
NodeGraph nodeGraph;
|
||||
|
||||
|
||||
private:
|
||||
//uint16_t data[MAX_FRAMES][NUM_CHANNELS];
|
||||
|
|
@ -67,4 +69,3 @@ private:
|
|||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,137 @@
|
|||
#include "nodegraph.h"
|
||||
#include <cstring>
|
||||
|
||||
// CurveNode evaluation
|
||||
void CurveNode::evaluate(uint32_t tick) {
|
||||
//outputValue = getCurveValue(curveID, tick);
|
||||
}
|
||||
|
||||
// ServoNode evaluation
|
||||
void ServoNode::evaluate(uint32_t tick) {
|
||||
//setMotorPWM(motorID, inputValue);
|
||||
}
|
||||
|
||||
// NodeGraph tick
|
||||
void NodeGraph::tick(uint32_t currentTick) {
|
||||
// First pass: evaluate all nodes
|
||||
for (Node* node : nodes) {
|
||||
node->evaluate(currentTick);
|
||||
}
|
||||
|
||||
// Optional: if you want to simulate wiring between nodes,
|
||||
// you could add a second pass here to propagate values
|
||||
}
|
||||
|
||||
void loadNodeGraph(const uint8_t* packet, size_t length, NodeGraph& graph) {
|
||||
size_t offset = 0;
|
||||
|
||||
// Read node count
|
||||
uint16_t nodeCount = packet[offset];
|
||||
offset += 1;
|
||||
|
||||
// Parse nodes
|
||||
for (uint16_t i = 0; i < nodeCount; ++i) {
|
||||
if (offset + 6 > length) break; // safety check
|
||||
|
||||
uint8_t type = packet[offset++];
|
||||
uint8_t id = packet[offset++];
|
||||
uint16_t x = packet[offset] | (packet[offset + 1] << 8); offset += 2;
|
||||
uint16_t y = packet[offset] | (packet[offset + 1] << 8); offset += 2;
|
||||
|
||||
Node* node = nullptr;
|
||||
|
||||
switch (type) {
|
||||
case TYPE_CURVENODE: { // CurveNode
|
||||
if (offset + 1 > length) break;
|
||||
uint8_t curveID = packet[offset++];
|
||||
auto* curve = new CurveNode();
|
||||
curve->id = id;
|
||||
curve->type = type;
|
||||
curve->x = x;
|
||||
curve->y = y;
|
||||
curve->curveID = curveID;
|
||||
node = curve;
|
||||
break;
|
||||
}
|
||||
case TYPE_SERVONODE: { // ServoNode
|
||||
if (offset + 1 > length) break;
|
||||
uint8_t motorID = packet[offset++];
|
||||
auto* servo = new ServoNode();
|
||||
servo->id = id;
|
||||
servo->type = type;
|
||||
servo->x = x;
|
||||
servo->y = y;
|
||||
servo->motorID = motorID;
|
||||
node = servo;
|
||||
break;
|
||||
}
|
||||
case TYPE_NOISENODE: { // NoiseNode
|
||||
if (offset + 17 > length) break;
|
||||
offset += 17; // skip for now
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
|
||||
graph.nodes.push_back(node);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse connections
|
||||
if (offset + 2 > length) return;
|
||||
uint16_t connectionCount = packet[offset];
|
||||
offset += 1;
|
||||
|
||||
for (uint16_t i = 0; i < connectionCount; ++i) {
|
||||
if (offset + 2 > length) break;
|
||||
uint8_t fromID = packet[offset++];
|
||||
uint8_t toID = packet[offset++];
|
||||
|
||||
graph.connections.push_back({fromID, toID});
|
||||
}
|
||||
}
|
||||
|
||||
String printNodeGraph(const NodeGraph& graph) {
|
||||
String output = "📦 NodeGraph Dump\n";
|
||||
|
||||
output += "Nodes:\n";
|
||||
for (const Node* node : graph.nodes) {
|
||||
output += " ID " + String(node->id);
|
||||
output += " | Type " + String(node->type);
|
||||
output += " | Pos (" + String(node->x) + ", " + String(node->y) + ")";
|
||||
|
||||
switch (node->type) {
|
||||
case TYPE_CURVENODE: { // CurveNode
|
||||
const CurveNode* curve = static_cast<const CurveNode*>(node);
|
||||
output += " | CurveID " + String(curve->curveID);
|
||||
break;
|
||||
}
|
||||
case TYPE_SERVONODE: { // ServoNode
|
||||
const ServoNode* servo = static_cast<const ServoNode*>(node);
|
||||
output += " | MotorID " + String(servo->motorID);
|
||||
break;
|
||||
}
|
||||
// case 2: { // NoiseNode
|
||||
// const NoiseNode* noise = static_cast<const NoiseNode*>(node);
|
||||
// output += " | Noise a=" + String(noise->a, 2);
|
||||
// output += " b=" + String(noise->b, 2);
|
||||
// output += " c=" + String(noise->c, 2);
|
||||
// output += " d=" + String(noise->d, 2);
|
||||
// output += " seed=" + String(noise->seed);
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
output += "\n";
|
||||
}
|
||||
|
||||
output += "Connections:\n";
|
||||
for (const auto& conn : graph.connections) {
|
||||
output += " " + String(conn.fromID) + " → " + String(conn.toID) + "\n";
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <Arduino.h>
|
||||
|
||||
#define TYPE_NODE 0x01
|
||||
#define TYPE_SERVONODE 0x02
|
||||
#define TYPE_CURVENODE 0x03
|
||||
#define TYPE_NOISENODE 0x04
|
||||
|
||||
|
||||
|
||||
// Base Node class
|
||||
struct Node {
|
||||
uint8_t id;
|
||||
uint8_t type;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
virtual void evaluate(uint32_t tick) = 0;
|
||||
virtual ~Node() {}
|
||||
};
|
||||
|
||||
// CurveNode: evaluates a curve at a given tick
|
||||
struct CurveNode : public Node {
|
||||
uint8_t curveID;
|
||||
uint16_t outputValue;
|
||||
|
||||
void evaluate(uint32_t tick) override;
|
||||
};
|
||||
|
||||
// ServoNode: sends a value to a motor
|
||||
struct ServoNode : public Node {
|
||||
uint8_t motorID;
|
||||
uint16_t inputValue;
|
||||
|
||||
void evaluate(uint32_t tick) override;
|
||||
};
|
||||
|
||||
// NodeGraph container
|
||||
struct NodeConnection {
|
||||
uint8_t fromID;
|
||||
uint8_t toID;
|
||||
};
|
||||
|
||||
class NodeGraph {
|
||||
public:
|
||||
std::vector<Node*> nodes;
|
||||
std::vector<NodeConnection> connections;
|
||||
|
||||
void tick(uint32_t currentTick);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Loader function
|
||||
void loadNodeGraph(const uint8_t* packet, size_t length, NodeGraph& graph);
|
||||
String printNodeGraph(const NodeGraph& graph);
|
||||
Loading…
Reference in New Issue