Skip to content

Commit 1ede64b

Browse files
adding vizard broadcast mode
1 parent 2228a55 commit 1ede64b

3 files changed

Lines changed: 119 additions & 34 deletions

File tree

src/simulation/vizard/vizInterface/vizInterface.cpp

Lines changed: 86 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,21 @@ VizInterface::VizInterface() {
2121
this->opNavMode = 0;
2222
this->saveFile = false;
2323
this->liveStream = false;
24+
this->broadcastStream = false;
2425
this->FrameNumber = -1;
2526

27+
this->lastSettingsSendTime = time(0); // current system time in seconds
28+
this->broadcastSettingsSendDelay = 2; // real-time seconds
29+
2630
this->firstPass = 0;
2731

28-
this->comProtocol = "tcp";
29-
this->comAddress = "localhost";
30-
this->comPortNumber = "5556";
32+
this->reqComProtocol = "tcp";
33+
this->reqComAddress = "localhost";
34+
this->reqPortNumber = "5556";
35+
36+
this->pubComProtocol = "tcp";
37+
this->pubComAddress = "localhost";
38+
this->pubPortNumber = "5570";
3139

3240
return;
3341
}
@@ -46,22 +54,51 @@ VizInterface::~VizInterface() {
4654
@param currentSimNanos The current sim time in nanoseconds
4755
*/
4856
void VizInterface::reset(uint64_t currentSimNanos) {
57+
if (this->broadcastStream) {
58+
// Setup ZMQ for broadcast socket
59+
this->publisher_context = zmq_ctx_new();
60+
this->publisher_socket = zmq_socket(this->publisher_context, ZMQ_PUB);
61+
assert(this->publisher_socket);
62+
// Build address
63+
std::string text = this->pubComProtocol + "://" + this->pubComAddress + ":" + this->pubPortNumber;
64+
int broadcastConnect = zmq_bind(this->publisher_socket, text.c_str());
65+
// Error if bind failure
66+
if (broadcastConnect != 0) {
67+
int error_code = zmq_errno();
68+
text = "Broadcast socket did not connect correctly. ZMQ error code: " + std::to_string(error_code);
69+
bskLogger.bskLog(BSK_ERROR, text.c_str());
70+
return;
71+
}
72+
text = "Broadcasting at " + this->pubComProtocol + "://" + this->pubComAddress + ":" + this->pubPortNumber;
73+
bskLogger.bskLog(BSK_INFORMATION, text.c_str());
74+
}
75+
4976
if (this->opNavMode > 0 || this->liveStream) {
50-
/* setup zeroMQ */
77+
// Reset cameras
5178
for (size_t camCounter = 0; camCounter < this->cameraConfInMsgs.size(); camCounter++) {
5279
this->bskImagePtrs[camCounter] = NULL;
5380
}
54-
this->context = zmq_ctx_new();
55-
this->requester_socket = zmq_socket(this->context, ZMQ_REQ);
56-
zmq_connect(this->requester_socket,
57-
(this->comProtocol + "://" + this->comAddress + ":" + this->comPortNumber).c_str());
81+
// Setup ZMQ for 2-way socket
82+
this->requester_context = zmq_ctx_new();
83+
this->requester_socket = zmq_socket(this->requester_context, ZMQ_REQ);
84+
assert(this->requester_socket);
85+
// Build address
86+
std::string text = this->reqComProtocol + "://" + this->reqComAddress + ":" + this->reqPortNumber;
87+
int twoWayConnect = zmq_connect(this->requester_socket, text.c_str());
88+
// Error if connection failure
89+
if (twoWayConnect != 0) {
90+
int error_code = zmq_errno();
91+
text = "2-way socket did not connect correctly. ZMQ error code: " + std::to_string(error_code);
92+
bskLogger.bskLog(BSK_ERROR, text.c_str());
93+
return;
94+
}
5895

5996
void* message = malloc(4 * sizeof(char));
6097
memcpy(message, "PING", 4);
6198
zmq_msg_t request;
6299

63-
std::string text;
64-
text = "Waiting for Vizard at " + this->comProtocol + "://" + this->comAddress + ":" + this->comPortNumber;
100+
text =
101+
"Waiting for Vizard at " + this->reqComProtocol + "://" + this->reqComAddress + ":" + this->reqPortNumber;
65102
bskLogger.bskLog(BSK_INFORMATION, text.c_str());
66103

67104
zmq_msg_init_data(&request, message, 4, message_buffer_deallocate, NULL);
@@ -424,8 +461,10 @@ void VizInterface::ReadBSKMessages() {
424461
void VizInterface::WriteProtobuffer(uint64_t currentSimNanos) {
425462
vizProtobufferMessage::VizMessage* message = new vizProtobufferMessage::VizMessage;
426463

427-
/*! Send the Vizard settings once */
428-
if (this->settings.dataFresh) {
464+
/*! Send the Vizard settings according to interval set by broadcastSettingsSendDelay field */
465+
this->now = time(0);
466+
if (this->settings.dataFresh ||
467+
(this->broadcastStream && (this->now - this->lastSettingsSendTime) >= this->broadcastSettingsSendDelay)) {
429468
vizProtobufferMessage::VizMessage::VizSettingsPb* vizSettings;
430469
vizSettings = new vizProtobufferMessage::VizMessage::VizSettingsPb;
431470

@@ -721,6 +760,7 @@ void VizInterface::WriteProtobuffer(uint64_t currentSimNanos) {
721760
message->set_allocated_settings(vizSettings);
722761

723762
this->settings.dataFresh = false;
763+
this->lastSettingsSendTime = now;
724764
}
725765

726766
/*! Send the Vizard live settings */
@@ -1044,13 +1084,40 @@ void VizInterface::WriteProtobuffer(uint64_t currentSimNanos) {
10441084
}
10451085

10461086
{
1047-
google::protobuf::uint8 varIntBuffer[4];
1087+
// Serialize message (as is)
10481088
uint32_t byteCount = (uint32_t)message->ByteSizeLong();
1049-
google::protobuf::uint8* end =
1050-
google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(byteCount, varIntBuffer);
1051-
unsigned long varIntBytes = (unsigned long)(end - varIntBuffer);
1052-
if (this->saveFile) {
1053-
this->outputStream->write(reinterpret_cast<char*>(varIntBuffer), (int)varIntBytes);
1089+
void* serialized_message = malloc(byteCount);
1090+
message->SerializeToArray(serialized_message, (int)byteCount);
1091+
1092+
// BROADCAST MODE
1093+
if (this->broadcastStream) {
1094+
// Send serialized message to BROADCAST (PUBLISHER) socket */
1095+
int sendStatus = zmq_send(this->publisher_socket, "SIM_UPDATE", 10, ZMQ_SNDMORE);
1096+
if (sendStatus == -1) {
1097+
bskLogger.bskLog(BSK_ERROR, "Broadcast header did not send to socket.");
1098+
}
1099+
sendStatus = zmq_send(this->publisher_socket, serialized_message, byteCount, 0);
1100+
if (sendStatus == -1) {
1101+
bskLogger.bskLog(BSK_ERROR, "Broadcast protobuffer did not send to socket.");
1102+
}
1103+
}
1104+
1105+
/* If settings were broadcast, remove from message before saving & sending to 2-way socket to reduce message
1106+
size. Message must be re-serialized here as its contents have changed. */
1107+
if (this->liveStream && (this->firstPass != 0) && (this->lastSettingsSendTime == this->now)) {
1108+
// Zero-out settings to reduce message size if not at first timestep
1109+
message->set_allocated_settings(nullptr);
1110+
// Re-serialize
1111+
google::protobuf::uint8 varIntBuffer[4];
1112+
byteCount = (uint32_t)message->ByteSizeLong();
1113+
google::protobuf::uint8* end =
1114+
google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(byteCount, varIntBuffer);
1115+
unsigned long varIntBytes = (unsigned long)(end - varIntBuffer);
1116+
if (this->saveFile) {
1117+
this->outputStream->write(reinterpret_cast<char*>(varIntBuffer), (int)varIntBytes);
1118+
}
1119+
serialized_message = malloc(byteCount);
1120+
message->SerializeToArray(serialized_message, (int)byteCount);
10541121
}
10551122

10561123
/*! Enter in lock-step with the vizard to simulate a camera */
@@ -1078,10 +1145,7 @@ void VizInterface::WriteProtobuffer(uint64_t currentSimNanos) {
10781145
zmq_msg_t receive_buffer;
10791146
zmq_msg_init(&receive_buffer);
10801147
zmq_msg_recv(&receive_buffer, requester_socket, 0);
1081-
1082-
/*! - send protobuffer raw over zmq_socket */
1083-
void* serialized_message = malloc(byteCount);
1084-
message->SerializeToArray(serialized_message, (int)byteCount);
1148+
zmq_msg_close(&receive_buffer);
10851149

10861150
/*! - Normal sim step by sending protobuffers */
10871151
zmq_msg_t request_header;

src/simulation/vizard/vizInterface/vizInterface.h

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "vizMessage.pb.h"
99
#include <zmq.h>
10+
#include <ctime>
1011
#include <fstream>
1112
#include <map>
1213
#include <vector>
@@ -45,11 +46,13 @@ class VizInterface : public SysModel {
4546
std::vector<LocationPbMsg*> locations; //!< [] vector of ground or spacecraft locations
4647
std::vector<GravBodyInfo> gravBodyInformation; //!< [-] vector of gravitational body info
4748
std::vector<Message<CameraImageMsgPayload>*>
48-
opnavImageOutMsgs; //!< vector of vizard instrument camera output messages
49-
int opNavMode; /*!< [int] Set non-zero positive value if Unity/Viz couple in direct
50-
communication. (1 - regular opNav, 2 - performance opNav) */
51-
bool saveFile; //!< [Bool] Set True if Vizard should save a file of the data.
52-
bool liveStream; //!< [Bool] Set True if Vizard should receive a live stream of BSK data.
49+
opnavImageOutMsgs; //!< vector of vizard instrument camera output messages
50+
int opNavMode; /*!< [int] Set non-zero positive value if Unity/Viz couple in direct
51+
communication. (1 - regular opNav, 2 - performance opNav) */
52+
bool saveFile; //!< [Bool] Set True if Vizard should save a file of the data.
53+
54+
bool liveStream; //!< [Bool] Set True if Vizard should receive a live stream of BSK data.
55+
bool broadcastStream; //!< [Bool] Set True if messages should be broadcast for listener Vizards to pick up.
5356
std::vector<void*> bskImagePtrs; /*!< [RUN] vector of permanent pointers for the images to be used in BSK
5457
without relying on ZMQ because ZMQ will free it (whenever, who knows) */
5558

@@ -62,9 +65,13 @@ class VizInterface : public SysModel {
6265
VizSettings settings; //!< [-] container for the Viz settings that can be specified from BSK
6366
LiveVizSettings liveSettings; //!< [-] container for Viz settings that are updated on each time step
6467

65-
std::string comProtocol; //!< Communication protocol to use when connecting to Vizard
66-
std::string comAddress; //!< Communication address to use when connecting to Vizard
67-
std::string comPortNumber; //!< Communication port number to use when connecting to Vizard
68+
std::string reqComProtocol; //!< Communication protocol to use when connecting to 2-way Vizard
69+
std::string reqComAddress; //!< Communication address to use when connecting to 2-way Vizard
70+
std::string reqPortNumber; //!< Communication port number to use when connecting to 2-way Vizard
71+
std::string pubComProtocol; //!< Communication protocol to use when connecting to broadcast Vizard
72+
std::string pubComAddress; //!< Communication address to use when connecting to broadcast Vizard
73+
std::string pubPortNumber; //!< Communication port number to use when connecting to broadcast Vizard
74+
double broadcastSettingsSendDelay; //!< Real-time delay between sending Viz settings to broadcast socket
6875

6976
ReadFunctor<EpochMsgPayload> epochInMsg; //!< [-] simulation epoch date/time input msg
7077
MsgCurrStatus epochMsgStatus; //!< [-] ID of the epoch msg
@@ -74,13 +81,18 @@ class VizInterface : public SysModel {
7481

7582
private:
7683
// ZeroMQ State
77-
void* context;
78-
void* requester_socket;
79-
int firstPass; //!< Flag to intialize the viz at first timestep
84+
void* requester_context; //!< 2-way context pointer (container for socket management)
85+
void* requester_socket; //!< 2-way socket pointer (ZMQ_REQ)
86+
void* publisher_context; //!< Broadcast context pointer (container for socket management)
87+
void* publisher_socket; //!< Broadcast socket pointer (ZMQ_PUB)
88+
int firstPass; //!< Flag to intialize the viz at first timestep
8089

8190
std::vector<MsgCurrStatus> spiceInMsgStatus; //!< [-] status of the incoming planets' spice data messages
8291
std::vector<SpicePlanetStateMsgPayload> spiceMessage; //!< [-] Spice message copies
8392
std::ofstream* outputStream; //!< [-] Output file stream opened in reset
93+
int64_t now; //!< Current system time stamp
94+
int64_t lastSettingsSendTime; //!< System time stamp when settings message was last sent to broadcast socket
95+
8496
void requestImage(size_t camCounter,
8597
uint64_t currentSimNanos); //!< request image from Vizard and store it in output img msg
8698
};

src/utilities/vizSupport.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,8 @@ def enableUnityVisualization(scSim, simTaskName, scList, **kwargs):
11011101
flag if opNaveMode should be used
11021102
liveStream: bool
11031103
flag if live data streaming to Vizard should be used
1104+
broadcastStream: bool
1105+
flag if messages should be broadcast for listener Vizards to pick up.
11041106
genericStorageList:
11051107
list of lists of ``GenericStorage`` structures. The outer list length must match ``scList``.
11061108
lightList:
@@ -1140,7 +1142,7 @@ def enableUnityVisualization(scSim, simTaskName, scList, **kwargs):
11401142
global firstSpacecraftName
11411143

11421144
unitTestSupport.checkMethodKeyword(
1143-
['saveFile', 'opNavMode', 'rwEffectorList', 'thrEffectorList', 'thrColors', 'liveStream', 'cssList',
1145+
['saveFile', 'opNavMode', 'rwEffectorList', 'thrEffectorList', 'thrColors', 'cssList', 'liveStream', 'broadcastStream',
11441146
'genericSensorList', 'transceiverList', 'genericStorageList', 'lightList', 'spriteList',
11451147
'modelDictionaryKeyList', 'oscOrbitColorList', 'trueOrbitColorList', 'logoTextureList',
11461148
'msmInfoList', 'ellipsoidList', 'trueOrbitColorInMsgList'],
@@ -1531,6 +1533,13 @@ def enableUnityVisualization(scSim, simTaskName, scList, **kwargs):
15311533
exit(1)
15321534

15331535
vizMessenger.opNavMode = 0
1536+
if 'broadcastStream' in kwargs:
1537+
val = kwargs['broadcastStream']
1538+
if not isinstance(val, bool):
1539+
print('ERROR: vizSupport: broadcastStream must be True or False')
1540+
exit(1)
1541+
vizMessenger.broadcastStream = val
1542+
15341543
if 'opNavMode' in kwargs:
15351544
val = kwargs['opNavMode']
15361545
if not isinstance(val, int):

0 commit comments

Comments
 (0)