#include "NetworkSync.h" // #define RC_DEBUG 1 #ifdef RC_DEBUG #include #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 NetworkSync::NetworkSync(Roboid *roboid) { this->roboid = roboid; this->networkId = 0; } #include 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 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 #endif void NetworkSync::SendInt(const int x) { 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); }