10 #include <mrpt/core/exceptions.h>
11 #include <mrpt/math/distributions.h>
12 #include <mrpt/math/ops_containers.h>
13 #include <mrpt/system/datetime.h>
15 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
17 #include <mvsim/mvsim-msgs/ObservationLidar2D.pb.h>
18 #include <mvsim/mvsim-msgs/TimeStampedPose.pb.h>
36 const auto& lstCmds =
cli->argCmd.getValue();
41 const std::string subcommand = lstCmds.at(1);
47 return (itSubcmd->second)();
54 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
57 client.setMinLoggingLevel(mrpt::typemeta::TEnumType<mrpt::system::VerbosityLevel>::name2value(
58 cli->argVerbosity.getValue()));
60 std::cout <<
"# Connecting to server...\n";
62 std::cout <<
"# Connected.\n";
63 std::cout <<
"# Querying list of topics to server...\n";
64 const auto lstTopics =
client.requestListOfTopics();
66 std::cout <<
"# Done. Found " << lstTopics.size() <<
" topics:\n";
68 for (
const auto& n : lstTopics)
70 if (
cli->argDetails.isSet())
72 std::cout <<
"- name: \"" << n.name <<
"\"\n"
73 <<
" type: \"" << n.type <<
"\"\n"
76 ASSERT_EQUAL_(n.endpoints.size(), n.publishers.size());
78 for (
size_t i = 0; i < n.endpoints.size(); i++)
80 std::cout <<
" - endpoint: \"" << n.endpoints[i] <<
"\"\n"
81 <<
" - publisherNode: \"" << n.publishers[i] <<
"\"\n";
86 std::cout << n.name <<
" [" << n.type <<
"] from node ";
87 if (n.publishers.size() != 1)
88 std::cout << n.publishers.size() <<
" publishers.\n";
90 std::cout << n.publishers.at(0) <<
"\n";
97 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
98 static void echo_TimeStampedPose(
const std::string& data)
100 mvsim_msgs::TimeStampedPose out;
101 if (
bool ok = out.ParseFromString(data); !ok)
103 std::cerr <<
"ERROR: Protobuf could not parse message.\n";
106 out.PrintDebugString();
108 static void echo_ObservationLidar2D(
const std::string& data)
110 mvsim_msgs::ObservationLidar2D out;
111 if (
bool ok = out.ParseFromString(data); !ok)
113 std::cerr <<
"ERROR: Protobuf could not parse message.\n";
116 out.PrintDebugString();
119 static void callbackSubscribeTopicGeneric(
const zmq::message_t& msg)
121 const auto [typeName, serializedData] = mvsim::internal::parseMessageToParts(msg);
122 std::cout <<
"[" << mrpt::system::dateTimeLocalToString(mrpt::Clock::now())
123 <<
"] Received data : \n";
124 std::cout <<
" - typeName: " << typeName <<
"\n";
125 std::cout <<
" - data: " << serializedData.size() <<
" bytes\n";
127 if (typeName == mvsim_msgs::TimeStampedPose().GetTypeName())
128 echo_TimeStampedPose(serializedData);
129 else if (typeName == mvsim_msgs::ObservationLidar2D().GetTypeName())
130 echo_ObservationLidar2D(serializedData);
132 std::cout << std::endl;
138 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
141 client.setMinLoggingLevel(mrpt::typemeta::TEnumType<mrpt::system::VerbosityLevel>::name2value(
142 cli->argVerbosity.getValue()));
144 const auto& lstCmds =
cli->argCmd.getValue();
147 const auto& topicName = lstCmds.at(2);
149 std::cout <<
"# Connecting to server...\n";
151 std::cout <<
"# Connected.\n";
153 std::cout <<
"# Subscribing to topic '" << topicName <<
"'. Press CTRL+C to stop.\n";
154 client.subscribe_topic_raw(topicName, &callbackSubscribeTopicGeneric);
167 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
170 client.setMinLoggingLevel(mrpt::typemeta::TEnumType<mrpt::system::VerbosityLevel>::name2value(
171 cli->argVerbosity.getValue()));
173 const auto& lstCmds =
cli->argCmd.getValue();
176 const auto& topicName = lstCmds.at(2);
178 std::cout <<
"# Connecting to server...\n";
180 std::cout <<
"# Connected.\n";
182 const double WAIT_SECONDS = 5.0;
184 std::cout <<
"# Subscribing to topic '" << topicName <<
"'. Will listen for " << WAIT_SECONDS
188 std::optional<double> lastMsgTim;
189 std::vector<double> measuredPeriods;
191 client.subscribe_topic_raw(
193 [&](
const zmq::message_t&)
196 const double t = mrpt::Clock::nowDouble();
199 const double dt =
t - lastMsgTim.value();
200 measuredPeriods.push_back(dt);
205 std::this_thread::sleep_for(
206 std::chrono::milliseconds(
static_cast<size_t>(WAIT_SECONDS * 1000)));
208 const double rate = numMsgs / WAIT_SECONDS;
210 std::cout << std::endl;
211 std::cout <<
"- ReceivedMsgs: " << numMsgs << std::endl;
212 std::cout <<
"- Rate: " << rate <<
" # Hz" << std::endl;
216 double periodMean = 0, periodStd = 0;
217 mrpt::math::meanAndStd(measuredPeriods, periodMean, periodStd);
219 std::cout <<
"- MeanPeriod: " << periodMean <<
" # [sec] 1/T = " << 1.0 / periodMean
220 <<
" Hz" << std::endl;
222 std::cout <<
"- PeriodStdDev: " << periodStd <<
" # [sec]" << std::endl;
224 double periodMin = 0, periodMax = 0;
225 mrpt::math::minimum_maximum(measuredPeriods, periodMin, periodMax);
227 std::cout <<
"- PeriodMin: " << periodMin <<
" # [sec]" << std::endl;
228 std::cout <<
"- PeriodMax: " << periodMax <<
" # [sec]" << std::endl;
230 const double conf = 0.05;
231 double tMean, tLow, tHigh;
233 mrpt::math::CVectorDouble x;
234 for (
size_t i = 0; i < measuredPeriods.size(); i++) x.push_back(measuredPeriods[i]);
236 mrpt::math::confidenceIntervals(x, tMean, tLow, tHigh,
conf, 100);
238 std::cout <<
"- Period_05percent: " << tLow <<
" # [sec]" << std::endl;
239 std::cout <<
"- Period_95percent: " << tHigh <<
" # [sec]" << std::endl;
251 std::cerr <<
"Error: missing or unknown subcommand.\n";
259 mvsim topic --help Show this help
260 mvsim topic list [--details] List all advertised topics in the server
261 mvsim topic echo <topicName> Subscribe and print a topic
262 mvsim topic hz <topicName> Estimate topic publication rate (in Hz)
266 return showErrorMsg ? 1 : 0;