mvsim-cli-topic.cpp
Go to the documentation of this file.
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2023 Jose Luis Blanco Claraco |
5  | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) |
6  | Distributed under 3-clause BSD License |
7  | See COPYING |
8  +-------------------------------------------------------------------------+ */
9 
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>
14 #include <mvsim/Comms/Client.h>
15 #include <mvsim/mvsim-msgs/ObservationLidar2D.pb.h>
16 #include <mvsim/mvsim-msgs/TimeStampedPose.pb.h>
17 
18 #include "mvsim-cli.h"
19 
20 static int printCommandsTopic(bool showErrorMsg);
21 static int topicList();
22 static int topicEcho();
23 static int topicHz();
24 
25 const std::map<std::string, cmd_t> cliTopicCommands = {
26  {"list", cmd_t(&topicList)},
27  {"echo", cmd_t(&topicEcho)},
28  {"hz", cmd_t(&topicHz)},
29 };
30 
32 {
33  const auto& lstCmds = cli->argCmd.getValue();
34  if (cli->argHelp.isSet()) return printCommandsTopic(false);
35  if (lstCmds.size() != 2 && lstCmds.size() != 3)
36  return printCommandsTopic(true);
37 
38  // Take second unlabeled argument:
39  const std::string subcommand = lstCmds.at(1);
40  auto itSubcmd = cliTopicCommands.find(subcommand);
41 
42  if (itSubcmd == cliTopicCommands.end()) return printCommandsTopic(true);
43 
44  // Execute command:
45  return (itSubcmd->second)();
46 
47  return 0;
48 }
49 
50 int topicList()
51 {
53 
54  client.setMinLoggingLevel(
55  mrpt::typemeta::TEnumType<mrpt::system::VerbosityLevel>::name2value(
56  cli->argVerbosity.getValue()));
57 
58  std::cout << "# Connecting to server...\n";
59  client.connect();
60  std::cout << "# Connected.\n";
61  std::cout << "# Querying list of topics to server...\n";
62  const auto lstTopics = client.requestListOfTopics();
63 
64  std::cout << "# Done. Found " << lstTopics.size() << " topics:\n";
65 
66  for (const auto& n : lstTopics)
67  {
68  if (cli->argDetails.isSet())
69  {
70  std::cout << "- name: \"" << n.name << "\"\n"
71  << " type: \"" << n.type << "\"\n"
72  << " publishers:\n";
73 
74  ASSERT_EQUAL_(n.endpoints.size(), n.publishers.size());
75 
76  for (size_t i = 0; i < n.endpoints.size(); i++)
77  {
78  std::cout << " - endpoint: \"" << n.endpoints[i] << "\"\n"
79  << " - publisherNode: \"" << n.publishers[i]
80  << "\"\n";
81  }
82  }
83  else
84  {
85  std::cout << n.name << " [" << n.type << "] from node ";
86  if (n.publishers.size() != 1)
87  std::cout << n.publishers.size() << " publishers.\n";
88  else
89  std::cout << n.publishers.at(0) << "\n";
90  }
91  }
92  return 0;
93 }
94 
95 static void echo_TimeStampedPose(const std::string& data)
96 {
97  mvsim_msgs::TimeStampedPose out;
98  if (bool ok = out.ParseFromString(data); !ok)
99  {
100  std::cerr << "ERROR: Protobuf could not parse message.\n";
101  return;
102  }
103  out.PrintDebugString();
104 }
105 static void echo_ObservationLidar2D(const std::string& data)
106 {
107  mvsim_msgs::ObservationLidar2D out;
108  if (bool ok = out.ParseFromString(data); !ok)
109  {
110  std::cerr << "ERROR: Protobuf could not parse message.\n";
111  return;
112  }
113  out.PrintDebugString();
114 }
115 
116 static void callbackSubscribeTopicGeneric(const zmq::message_t& msg)
117 {
118  const auto [typeName, serializedData] =
119  mvsim::internal::parseMessageToParts(msg);
120  std::cout << "[" << mrpt::system::dateTimeLocalToString(mrpt::Clock::now())
121  << "] Received data : \n";
122  std::cout << " - typeName: " << typeName << "\n";
123  std::cout << " - data: " << serializedData.size() << " bytes\n";
124 
125  if (typeName == mvsim_msgs::TimeStampedPose().GetTypeName())
126  echo_TimeStampedPose(serializedData);
127  else if (typeName == mvsim_msgs::ObservationLidar2D().GetTypeName())
128  echo_ObservationLidar2D(serializedData);
129 
130  std::cout << std::endl;
131 }
132 
134 {
136 
137  client.setMinLoggingLevel(
138  mrpt::typemeta::TEnumType<mrpt::system::VerbosityLevel>::name2value(
139  cli->argVerbosity.getValue()));
140 
141  const auto& lstCmds = cli->argCmd.getValue();
142  if (lstCmds.size() != 3) return printCommandsTopic(true);
143 
144  const auto& topicName = lstCmds.at(2);
145 
146  std::cout << "# Connecting to server...\n";
147  client.connect();
148  std::cout << "# Connected.\n";
149 
150  std::cout << "# Subscribing to topic '" << topicName
151  << "'. Press CTRL+C to stop.\n";
153 
154  // loop until user does a CTRL+C
155  for (;;)
156  {
157  }
158 
159  return 0;
160 }
161 
162 int topicHz()
163 {
165 
166  client.setMinLoggingLevel(
167  mrpt::typemeta::TEnumType<mrpt::system::VerbosityLevel>::name2value(
168  cli->argVerbosity.getValue()));
169 
170  const auto& lstCmds = cli->argCmd.getValue();
171  if (lstCmds.size() != 3) return printCommandsTopic(true);
172 
173  const auto& topicName = lstCmds.at(2);
174 
175  std::cout << "# Connecting to server...\n";
176  client.connect();
177  std::cout << "# Connected.\n";
178 
179  const double WAIT_SECONDS = 5.0;
180 
181  std::cout << "# Subscribing to topic '" << topicName
182  << "'. Will listen for " << WAIT_SECONDS << " seconds...\n";
183 
184  int numMsgs = 0;
185  std::optional<double> lastMsgTim;
186  std::vector<double> measuredPeriods;
187 
188  client.subscribe_topic_raw(topicName, [&](const zmq::message_t&) {
189  numMsgs++;
190  const double t = mrpt::Clock::nowDouble();
191  if (lastMsgTim)
192  {
193  const double dt = t - lastMsgTim.value();
194  measuredPeriods.push_back(dt);
195  }
196  lastMsgTim = t;
197  });
198 
199  std::this_thread::sleep_for(
200  std::chrono::milliseconds(static_cast<size_t>(WAIT_SECONDS * 1000)));
201 
202  const double rate = numMsgs / WAIT_SECONDS;
203 
204  std::cout << std::endl;
205  std::cout << "- ReceivedMsgs: " << numMsgs << std::endl;
206  std::cout << "- Rate: " << rate << " # Hz" << std::endl;
207 
208  if (numMsgs > 0)
209  {
210  double periodMean = 0, periodStd = 0;
211  mrpt::math::meanAndStd(measuredPeriods, periodMean, periodStd);
212 
213  std::cout << "- MeanPeriod: " << periodMean
214  << " # [sec] 1/T = " << 1.0 / periodMean << " Hz"
215  << std::endl;
216 
217  std::cout << "- PeriodStdDev: " << periodStd << " # [sec]" << std::endl;
218 
219  double periodMin = 0, periodMax = 0;
220  mrpt::math::minimum_maximum(measuredPeriods, periodMin, periodMax);
221 
222  std::cout << "- PeriodMin: " << periodMin << " # [sec]" << std::endl;
223  std::cout << "- PeriodMax: " << periodMax << " # [sec]" << std::endl;
224 
225  const double conf = 0.05;
226  double tMean, tLow, tHigh;
227 
228  mrpt::math::CVectorDouble x;
229  for (size_t i = 0; i < measuredPeriods.size(); i++)
230  x.push_back(measuredPeriods[i]);
231 
232  mrpt::math::confidenceIntervals(x, tMean, tLow, tHigh, conf, 100);
233 
234  std::cout << "- Period_05percent: " << tLow << " # [sec]" << std::endl;
235  std::cout << "- Period_95percent: " << tHigh << " # [sec]" << std::endl;
236  }
237 
238  return 0;
239 }
240 
241 int printCommandsTopic(bool showErrorMsg)
242 {
243  if (showErrorMsg)
244  {
246  std::cerr << "Error: missing or unknown subcommand.\n";
248  }
249 
250  fprintf(
251  stderr,
252  R"XXX(Usage:
253 
254  mvsim topic --help Show this help
255  mvsim topic list [--details] List all advertised topics in the server
256  mvsim topic echo <topicName> Subscribe and print a topic
257  mvsim topic hz <topicName> Estimate topic publication rate (in Hz)
258 
259 )XXX");
260 
261  return showErrorMsg ? 1 : 0;
262 }
const std::map< std::string, cmd_t > cliTopicCommands
static int topicEcho()
static int topicHz()
std::function< int(void)> cmd_t
Definition: mvsim-cli.h:74
Definition: conf.py:1
static int printCommandsTopic(bool showErrorMsg)
void setConsoleErrorColor()
static void echo_ObservationLidar2D(const std::string &data)
geometry_msgs::TransformStamped t
std::vector< InfoPerTopic > requestListOfTopics()
ROSCPP_DECL bool ok()
static void callbackSubscribeTopicGeneric(const zmq::message_t &msg)
static void echo_TimeStampedPose(const std::string &data)
static int topicList()
std::unique_ptr< cli_flags > cli
void setConsoleNormalColor()
int commandTopic()
void subscribe_topic_raw(const std::string &topicName, const topic_callback_t &callback)


mvsim
Author(s):
autogenerated on Tue Jul 4 2023 03:08:21