#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 "float16/float16.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); switch (buffer[0]) { case CustomMsg::id: ReceiveCustom(bytecount); break; } } 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 (networkId != roboid->networkSync->networkId) // We only response to investigation requests for our own objects return; if (msg.thingId == 0x00) { // They are investigating the roboid itself! if (roboid->modelUrl != nullptr) // roboid->networkSync->SendModel(roboid); roboid->networkSync->SendThingInfo(roboid); } else { Thing *thing = roboid->FindChild(msg.thingId, true); if (thing != nullptr) roboid->networkSync->SendThingInfo(thing); else { InterestingThing *interestingThing = roboid->perception->FindTrackedObject(0x00, msg.thingId); if (interestingThing == nullptr) return; roboid->networkSync->SendThingInfo(interestingThing, false); } } } 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::ReceiveCustom(unsigned char packetSize) { unsigned char ix = 1; // first byte is the msgId unsigned char networkId = buffer[ix++]; unsigned char thingId = buffer[ix++]; // unsigned char len = buffer[ix++]; unsigned char len = packetSize - 3; printf("Custom size = %d\n", len); if (len > 0) { unsigned char *bytes = new unsigned char[len]; // printf("Received %d bytes for [%d/%d]\n", len, networkId, thingId); for (unsigned char bytesIx = 0; bytesIx < len; bytesIx++) bytes[bytesIx] = buffer[ix++]; // networkId is not used right now, we assume networkId == 0 Thing *thing = roboid->FindChild(thingId); printf("Found thing %s\n", thing->name); if (thing != nullptr) thing->ProcessBytes(bytes); delete bytes; } } 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->GetChild(childIx); if (child != nullptr) SendThingInfo(child, true); } } } void NetworkSync::SendThing(Thing *thing) { if (thing == nullptr) return; Thing *parent = thing->GetParent(); ThingMsg msg = ThingMsg(this->networkId, thing->id, thing->type, parent == nullptr ? 0 : parent->id); msg.Send(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.Send(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.Send(this); } void NetworkSync::SendCustom(Thing *thing) { unsigned char ix = 0; buffer[ix++] = CustomMsg::id; buffer[ix++] = this->networkId; buffer[ix++] = thing->id; thing->SendBytes(buffer, &ix); if (ix > 3) // When ix <= 3 then there is no custom data SendBuffer(ix); } void NetworkSync::SendDestroyThing(InterestingThing *thing) { if (networkId == 0) // We're not connected to a site yet return; unsigned char ix = 0; buffer[ix++] = DestroyMsg; buffer[ix++] = this->networkId; buffer[ix++] = thing->id; SendBuffer(ix); #if RC_DEBUG printf("Sent DestroyMsg [%d/%d]\n", thing->networkId, thing->id); #endif } 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; PoseMsg msg = PoseMsg(this->networkId, thing->id, poseType, thing->position, thing->orientation); msg.Send(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->GetChild(childIx); if (child != nullptr) SendPose(thing->GetChild(childIx), 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->orientation); originPosition = roboid->worldOrigin->position; } // SwingTwist16 inv_originOrientation = // SwingTwist16::Inverse(roboid->worldOrigin->orientation); // Spherical16 originPosition = roboid->worldOrigin->position; SwingTwist16 worldOrientation = inv_originOrientation * thing->orientation; Spherical16 worldPosition = inv_originOrientation * (thing->position - 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); }