RoboidControl-cpp/NetworkSync.cpp
2024-12-28 11:15:43 +01:00

331 lines
8.8 KiB
C++

#include "NetworkSync.h"
// #define RC_DEBUG 1
#ifdef RC_DEBUG
#include <Arduino.h>
#if ESP32
#define SERIALPORT Serial
#else
#define SERIALPORT Serial
#endif
#endif
#include "ControlCore/Messages.h"
#include "LinearAlgebra/Angle.h"
#include "LinearAlgebra/AngleUsing.h"
#include "LinearAlgebra/Spherical.h"
#include <string.h>
NetworkSync::NetworkSync(Roboid *roboid) {
this->roboid = roboid;
this->networkId = 0;
}
// #include <Arduino.h>
void NetworkSync::ReceiveMessage(Roboid *roboid, unsigned char bytecount) {
// printf("Received msgId %d, length %d\n", buffer[0], bytecount);
ReceiveData(bytecount);
}
void NetworkSync::PublishClient() {
ClientMsg msg = ClientMsg(this->networkId);
msg.Publish(this);
#ifdef RC_DEBUG
SERIALPORT.printf("Publish Device\n");
#endif
}
void NetworkSync::ProcessNetworkIdMsg(Passer::Control::NetworkIdMsg msg) {
#ifdef RC_DEBUG
SERIALPORT.printf("Received network Id %d\n", msg.networkId);
#endif
this->networkId = msg.networkId;
SendThingInfo(roboid, true);
printf("completed\n");
}
void NetworkSync::ReceiveNetworkId() {
this->networkId = buffer[1];
#ifdef RC_DEBUG
SERIALPORT.printf("Received network Id %d\n", this->networkId);
#endif
SendThingInfo(roboid, true);
printf("completed\n");
}
void NetworkSync::ProcessInvestigateMsg(InvestigateMsg msg) {
#if RC_DEBUG
printf("Received InvestigateMsg [%d/%d]\n", msg.networkId, msg.thingId);
#endif
if (msg.networkId != this->networkId)
// We only respond to investigation requests for our own objects
return;
Thing *thing = (Thing *)Thing::Get(0, msg.thingId);
if (thing != nullptr)
this->SendThingInfo(thing, true);
}
void NetworkSync::ProcessThingMsg(ThingMsg msg) {
if (msg.networkId == roboid->networkSync->networkId)
// Do not process messages for you own things
return;
printf("Received Thing message [%d/%d]\n", msg.networkId, msg.thingId);
InterestingThing *thing =
roboid->perception->FindTrackedObject(msg.networkId, msg.thingId);
if (thing != nullptr) {
thing->type = msg.thingType;
}
printf("complete\n");
}
void NetworkSync::ProcessPoseMsg(PoseMsg msg) {}
void NetworkSync::PublishState(Roboid *roboid) {
SendPose(roboid);
PublishPerception(roboid);
}
void NetworkSync::SendThingInfo(Thing *thing, bool recurse) {
if (thing == nullptr)
return;
SendThing(thing);
SendName(thing);
SendModel(thing);
SendCustom(thing);
SendPose(thing, true, false);
if (recurse) {
for (unsigned char childIx = 0; childIx < thing->childCount; childIx++) {
Thing *child = (Thing *)thing->GetChildByIndex(childIx);
if (child != nullptr)
SendThingInfo(child, true);
}
}
}
void NetworkSync::SendThing(Thing *thing) {
if (thing == nullptr)
return;
Thing *parent = (Thing *)thing->GetParent();
ThingMsg msg = ThingMsg(this->networkId, thing->id, thing->type,
parent == nullptr ? 0 : parent->id);
msg.SendTo(this);
#ifdef RC_DEBUG
printf("Sent Thing [%d/%d] %d\n", networkId, thing->id, (byte)thing->type);
#endif
}
void NetworkSync::SendName(Thing *thing) {
if (thing->name == nullptr)
return;
unsigned char len = strlen(thing->name);
if (len > 255)
return;
NameMsg msg = NameMsg(this->networkId, thing->id, thing->name, len);
msg.SendTo(this);
#ifdef RC_DEBUG
SERIALPORT.printf("Sent Name [%d/%d] %s\n", networkId, buffer[1],
thing->name);
#endif
}
void NetworkSync::SendModel(Thing *thing) {
if (thing->modelUrl == nullptr)
return;
unsigned char len = strlen(thing->modelUrl);
if (len > 255)
return;
ModelUrlMsg msg = ModelUrlMsg(this->networkId, thing->id, len,
thing->modelUrl, thing->modelScale);
msg.SendTo(this);
}
void NetworkSync::SendCustom(Thing *thing) {
CustomMsg msg = CustomMsg(this->networkId, thing);
msg.SendTo(this);
}
void NetworkSync::SendDestroy(Thing *thing) {
DestroyMsg msg = DestroyMsg(this->networkId, thing);
msg.SendTo(this);
#if RC_DEBUG
printf("Sent DestroyMsg [%d/%d]\n", thing->networkId, thing->id);
#endif
}
#include <iostream>
void NetworkSync::ProcessCustomMsg(CustomMsg msg) {
// we assume networkId == 0 as custom messages are intended for my things
Thing *thing = (Thing *)roboid->GetChild(msg.thingId, true);
if (thing != nullptr)
thing->ProcessBytes(msg.data);
}
void NetworkSync::SendPose(Thing *thing, bool force, bool recurse) {
if (this->networkId == 0) // We're not connected to a site yet
return;
thing->positionUpdated |= thing->GetLinearVelocity().distance > 0;
thing->orientationUpdated |= thing->GetAngularVelocity().distance > 0;
if (force || thing->positionUpdated || thing->orientationUpdated) {
unsigned char poseType = 0;
if (force || thing->positionUpdated)
poseType |= PoseMsg::Pose_Position;
if (force || thing->orientationUpdated)
poseType |= PoseMsg::Pose_Orientation;
if (thing->linearVelocity.distance > 0)
poseType |= PoseMsg::Pose_LinearVelocity;
if (thing->angularVelocity.distance > 0)
poseType |= PoseMsg::Pose_AngularVelocity;
PoseMsg msg = PoseMsg(this->networkId, thing->id, poseType,
thing->GetPosition(), thing->GetOrientation(),
thing->linearVelocity, thing->angularVelocity);
msg.SendTo(this);
thing->positionUpdated = false;
thing->orientationUpdated = false;
#if RC_DEBUG
if (thing->id != 0) {
Vector3 v = thing->position.ToVector3();
printf("Sent PoseMsg Thing [%d/%d] %f(%f)-(%f %f %f) %f\n",
this->networkId, thing->id, thing->position.distance,
thing->position.direction.horizontal.InDegrees(), v.Right(),
v.Up(), v.Forward(),
thing->orientation.swing.horizontal.InDegrees());
}
#endif
}
if (recurse) {
for (unsigned char childIx = 0; childIx < thing->childCount; childIx++) {
Thing *child = (Thing *)thing->GetChildByIndex(childIx);
if (child != nullptr)
SendPose(child, force, recurse);
}
}
}
void NetworkSync::PublishPerception(Roboid *roboid) {
// Perception *perception = roboid->perception;
// if (perception == nullptr)
// return;
// for (unsigned int sensorIx = 0; sensorIx < perception->sensorCount;
// sensorIx++) {
// Sensor *sensor = perception->sensors[sensorIx];
// if (sensor == nullptr)
// continue;
// }
PublishTrackedObjects(roboid, roboid->perception->GetTrackedObjects());
}
void NetworkSync::PublishTrackedObjects(Roboid *roboid,
InterestingThing **objects) {
if (networkId == 0) // We're not connected to a site yet
return;
int n = 0;
for (unsigned char objIx = 0; objIx < Perception::maxObjectCount; objIx++) {
InterestingThing *obj = objects[objIx];
if (obj == nullptr)
continue;
if (obj->confidence > 0)
PublishTrackedObject(roboid, obj);
n++;
}
}
void NetworkSync::PublishTrackedObject(Roboid *roboid,
InterestingThing *thing) {
if (thing == nullptr || thing->updated == false || thing->networkId != 0x00) {
return;
}
SwingTwist16 inv_originOrientation;
Spherical16 originPosition;
if (roboid->worldOrigin == nullptr) {
inv_originOrientation = SwingTwist16::identity;
originPosition = Spherical16::zero;
} else {
inv_originOrientation =
SwingTwist16::Inverse(roboid->worldOrigin->GetOrientation());
originPosition = roboid->worldOrigin->GetPosition();
}
// SwingTwist16 inv_originOrientation =
// SwingTwist16::Inverse(roboid->worldOrigin->orientation);
// Spherical16 originPosition = roboid->worldOrigin->position;
SwingTwist16 worldOrientation =
inv_originOrientation * thing->GetOrientation();
Spherical16 worldPosition =
inv_originOrientation * (thing->GetPosition() - originPosition);
PoseMsg msg = PoseMsg(this->networkId, thing->id,
PoseMsg::Pose_Position | PoseMsg::Pose_Orientation,
worldPosition, worldOrientation);
SendBuffer(msg.Serialize(this->buffer));
#if RC_DEBUG
printf("Sent Thing PoseMsg [%d/%d] %d\n", networkId, buffer[1], thing->type);
#endif
thing->updated = false;
}
void NetworkSync::SendText(const char *s) {
unsigned char length;
for (length = 0; length < 253; length++) {
if (s[length] == '\0')
break;
}
if (length >= 253)
return;
unsigned char ix = 0;
buffer[ix++] = 0xB0;
buffer[ix++] = length;
for (int urlIx = 0; urlIx < length; urlIx++)
buffer[ix++] = s[urlIx];
SendBuffer(ix);
#ifdef RC_DEBUG
printf("Sent Text %s\n", s);
#endif
}
#if ESP32
#include <Arduino.h>
#endif
void NetworkSync::SendInt(const int x) {
#if ESP32
String s = String(x);
char length = s.length();
unsigned char ix = 0;
buffer[ix++] = 0xB0;
buffer[ix++] = length;
for (int urlIx = 0; urlIx < length; urlIx++)
buffer[ix++] = s[urlIx];
SendBuffer(ix);
#endif
}