YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
yarpRerun.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025-2025 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include <yarp/os/Log.h>
7#include <yarp/os/LogStream.h>
8#include <yarp/os/Port.h>
9#include <yarp/os/Stamp.h>
11#include <yarp/os/Network.h>
12
13#include <yarp/os/RFModule.h>
14#include <yarp/os/Portable.h>
15
16#include <yarp/dev/all.h>
21#include <yarp/sig/PointCloud.h>
22
23#include <rerun.hpp>
24
25
26using namespace yarp::os;
27
28
30{
31 public:
32 rerun::RecordingStream* m_rec = nullptr;
34
36 {
37 }
38
40 {
41 if (m_rec)
42 {
43 delete m_rec;
44 m_rec = nullptr;
45 }
46 m_port.close();
47 }
48
49 bool process_RGBImage (const Bottle* pbot);
51 bool process_Bottle (const Bottle* pbot);
52 bool process_Vector (const Bottle* pbot);
53 bool process_RobotState (const Bottle* pbot);
54 bool process_DepthImage (const Bottle* pbot);
55 bool process_Lidar2D (const Bottle* pbot);
56 bool process_PointCloud (const Bottle* pbot);
57 void process_Bottle_nested (const Bottle* pbot, std::vector<size_t> path);
58
59 bool configure(yarp::os::ResourceFinder& rf) override;
60
61 bool interruptModule() override;
62
63 double getPeriod() override
64 { return 1.0; }
65
66 bool updateModule() override;
67
68
69 private:
70 bool m_isRunning = true;
71 std::string m_localPortname = "/yarprerun:i";
72 std::string m_remotePortname;
73 std::string m_datatype = "Bottle";
74 std::string m_session_name = "yarprerun";
75
76};
77
79{
81 m_isRunning = false;
82 return true;
83}
84
86{
87 if (rf.check("help"))
88 {
89 yInfo();
90 yInfo() << "yarpRerun --data <dataType> [--local <local_portname>] [--remote <remote_portname>] [--session_name <session_name>]";
91 yInfo() << "<dataType> : Supported types are: SensorStreamingData, Bottle, RGBImage, DepthImage, Vector, RobotState, Lidar2D, Pointcloud ";
92 yInfo() << "<local_portname> : Optional. Sets the name of the input port. By default: /yarprerun:i";
93 yInfo() << "<remote_portname> : Optional. If set, it automatically tries to connect the specified port";
94 yInfo() << "<session_name> : Optional. Sets the name of the rerun session. By default: yarprerun";
95 yInfo();
96 return false;
97 }
98
99 if (rf.check("local"))
100 {
101 m_localPortname = rf.find("local").asString();
102 }
103
104 if (rf.check("remote"))
105 {
106 m_remotePortname = rf.find("remote").asString();
107 }
108
109 if (rf.check("data"))
110 {
111 m_datatype = rf.find("data").asString();
112 }
113 yInfo() << "Selected " << m_datatype << " data type";
114
115 bool b = m_port.open(m_localPortname);
116 if (!b)
117 {
118 yError() << "Unable to open port" << m_localPortname;
119 return false;
120 }
121
122 if (rf.check("session_name"))
123 {
124 m_session_name = rf.find("session_name").asString();
125 }
126 m_rec = new rerun::RecordingStream(m_session_name);
127 m_rec->spawn().exit_on_failure();
128
129 if (m_remotePortname != "")
130 {
131 b = yarp::os::Network::connect(m_remotePortname,m_localPortname);
132 if (!b)
133 {
134 yError() << "Unable to connect to remote port: " << m_remotePortname;
135 return false;
136 }
137 else
138 {
139 yInfo() << "Connected to: " << m_remotePortname;
140 }
141 }
142 else
143 {
144 yInfo() << "Waiting for connection..";
145 }
146
147 return true;
148
149}
150
152{
153 while (m_isRunning)
154 {
156 if (prt == nullptr) { return true; }
157
158 yarp::os::Stamp envelope;
159 bool env_ok = m_port.getEnvelope(envelope);
160 if (env_ok)
161 {m_rec->set_time_seconds("time", envelope.getTime());}
162 else
163 {m_rec->set_time_seconds("time", yarp::os::Time::now());}
164
165 if (m_datatype == "SensorStreamingData")
166 {
168 }
169 else if (m_datatype == "Bottle")
170 {
172 }
173 else if (m_datatype == "RGBImage")
174 {
176 }
177 else if (m_datatype == "DepthImage")
178 {
180 }
181 else if (m_datatype == "Vector")
182 {
184 }
185 else if (m_datatype == "RobotState")
186 {
188 }
189 else if (m_datatype == "Lidar2D")
190 {
192 }
193 else if (m_datatype == "Pointcloud")
194 {
196 }
197 else
198 {
199 yError() << "Unknown datatype " << m_datatype;
200 return false;
201 }
202 }
203
204 return true;
205}
206
208{
211 if (b_cp)
212 {
213 m_rec->log("camera", rerun::Image(
214 img.getRawImage(),
215 rerun::WidthHeight(img.width(), img.height()),
216 rerun::datatypes::ColorModel::RGB
217 ));
218 return true;
219 }
220 return false;
221}
222
224{
227 if (b_cp)
228 {
229 std::vector<rerun::Position2D> positions;
230 for (size_t i=0; i<las.scans.size(); i++)
231 {
232 double step = (las.angle_max - las.angle_min) / double(las.scans.size());
233 double angle = double(i)*step;
234 double y = las.scans[i]*sin(angle*3.14159265359/180.0);
235 double x = las.scans[i]*cos(angle*3.14159265359/180.0);
236 positions.push_back(rerun::Position2D(x,y));
237 }
238 m_rec->log("laserscan",
239 rerun::Points2D(positions));
240 return true;
241 }
242 return false;
243}
244
246{
249 if (b_cp)
250 {
251 std::vector<rerun::Position3D> positions;
252 for (size_t x=0; x<pcl.width(); x++)
253 {
254 for (size_t y=0; y<pcl.height(); y++)
255 {
256 positions.push_back(rerun::Position3D(pcl(x,y).x,
257 pcl(x,y).y,
258 pcl(x,y).z));
259 }
260 }
261 m_rec->log("pointcloud",
262 rerun::Points3D(positions));
263 return true;
264 }
265 return false;
266}
267
268
270{
273 if (b_cp)
274 {
275 size_t sz = 0;
276 sz=data.EncoderArrays.measurements.size();
277 for (size_t i=0; i< sz; i++)
278 {
279 std::string name = "EncoderArray_" + std::to_string(i);
280 for (size_t j = 0; j < data.EncoderArrays.measurements[i].measurement.size(); j++)
281 m_rec->log(name + "_" + std::to_string(j), rerun::Scalars(data.EncoderArrays.measurements[i].measurement[j]));
282 }
283
285 for (size_t i=0; i< sz; i++)
286 {
287 std::string name = "LinearVelocitySensors_" + std::to_string(i);
288 m_rec->log(name + "_x", rerun::Scalars(data.LinearVelocitySensors.measurements[i].measurement[0]));
289 m_rec->log(name + "_y", rerun::Scalars(data.LinearVelocitySensors.measurements[i].measurement[1]));
290 m_rec->log(name + "_z", rerun::Scalars(data.LinearVelocitySensors.measurements[i].measurement[2]));
291 }
292
294 for (size_t i=0; i< sz; i++)
295 {
296 std::string name = "OrientationSensors_" + std::to_string(i);
297 m_rec->log(name + "_x", rerun::Scalars(data.OrientationSensors.measurements[i].measurement[0]));
298 m_rec->log(name + "_y", rerun::Scalars(data.OrientationSensors.measurements[i].measurement[1]));
299 m_rec->log(name + "_z", rerun::Scalars(data.OrientationSensors.measurements[i].measurement[2]));
300 }
301
302 sz=data.PositionSensors.measurements.size();
303 for (size_t i=0; i< sz; i++)
304 {
305 std::string name = "PositionSensors_" + std::to_string(i);
306 m_rec->log(name + "_x", rerun::Scalars(data.PositionSensors.measurements[i].measurement[0]));
307 m_rec->log(name + "_y", rerun::Scalars(data.PositionSensors.measurements[i].measurement[1]));
308 m_rec->log(name + "_z", rerun::Scalars(data.PositionSensors.measurements[i].measurement[2]));
309 }
310
312 for (size_t i=0; i< sz; i++)
313 {
314 std::string name = "SixAxisForceTorqueSensors_" + std::to_string(i);
315 m_rec->log(name + "_Fx", rerun::Scalars(data.PositionSensors.measurements[i].measurement[0]));
316 m_rec->log(name + "_Fy", rerun::Scalars(data.PositionSensors.measurements[i].measurement[1]));
317 m_rec->log(name + "_Fz", rerun::Scalars(data.PositionSensors.measurements[i].measurement[2]));
318 m_rec->log(name + "_Tx", rerun::Scalars(data.PositionSensors.measurements[i].measurement[3]));
319 m_rec->log(name + "_Ty", rerun::Scalars(data.PositionSensors.measurements[i].measurement[4]));
320 m_rec->log(name + "_Tz", rerun::Scalars(data.PositionSensors.measurements[i].measurement[5]));
321 }
322
324 for (size_t i=0; i< sz; i++)
325 {
326 std::string name = "TemperatureSensors_" + std::to_string(i);
327 for (size_t j = 0; j < data.TemperatureSensors.measurements[i].measurement.size(); j++)
328 m_rec->log(name + "_" + std::to_string(j), rerun::Scalars(data.TemperatureSensors.measurements[i].measurement[j]));
329 }
330
332 for (size_t i=0; i< sz; i++)
333 {
334 std::string name = "ThreeAxisGyroscopes_" + std::to_string(i);
335 m_rec->log(name + "_x", rerun::Scalars(data.ThreeAxisGyroscopes.measurements[i].measurement[0]));
336 m_rec->log(name + "_y", rerun::Scalars(data.ThreeAxisGyroscopes.measurements[i].measurement[1]));
337 m_rec->log(name + "_z", rerun::Scalars(data.ThreeAxisGyroscopes.measurements[i].measurement[2]));
338 }
339
341 for (size_t i=0; i< sz; i++)
342 {
343 std::string name = "ThreeAxisMagnetometers" + std::to_string(i);
344 m_rec->log(name + "_x", rerun::Scalars(data.ThreeAxisMagnetometers.measurements[i].measurement[0]));
345 m_rec->log(name + "_y", rerun::Scalars(data.ThreeAxisMagnetometers.measurements[i].measurement[1]));
346 m_rec->log(name + "_z", rerun::Scalars(data.ThreeAxisMagnetometers.measurements[i].measurement[2]));
347 }
348
349 return true;
350 }
351 return false;
352}
353
354void RerunLogger::process_Bottle_nested (const Bottle* data, std::vector<size_t> path)
355{
356 if (data==nullptr) return;
357 for (size_t i=0; i< data->size(); i++)
358 {
359 auto new_path = path;
360 new_path.push_back(i);
361 if (data->get(i).isList())
362 {
363 return process_Bottle_nested(data->get(i).asList(), new_path);
364 }
365 else if (data->get(i).isString())
366 {
367 }
368 else
369 {
370 std::string vsname = "value";
371 for (auto p : new_path) {vsname += "_" + std::to_string(p);}
372 m_rec->log(vsname, rerun::Scalars(data->get(i).asFloat32()));
373 }
374 }
375}
376
378{
379 yarp::os::Bottle data;
381 if (bcp)
382 {
383 process_Bottle_nested(&data, {});
384 return true;
385 }
386 return false;
387}
388
390{
393 if (bcp)
394 {
395 for (size_t i=0; i< data.size(); i++)
396 {
397 std::string vsname = "value_" + std::to_string(i);
398 m_rec->log(vsname, rerun::Scalars(data[i]));
399 }
400 return true;
401 }
402 return false;
403}
404
406{
409 if (bcp)
410 {
411 size_t n = data.controlMode.size();
412 for (size_t i=0; i< n; i++)
413 {
414 std::string name = "joint_" + std::to_string(i);
415 m_rec->log(name+"_Position", rerun::Scalars(data.jointPosition[i]));
416 m_rec->log(name+"_Velocity", rerun::Scalars(data.jointVelocity[i]));
417 m_rec->log(name+"_Acceleration", rerun::Scalars(data.jointAcceleration[i]));
418 m_rec->log(name+"_torque", rerun::Scalars(data.torque[i]));
419 m_rec->log(name+"_current", rerun::Scalars(data.current[i]));
420 m_rec->log(name+"_pwmDutycycle", rerun::Scalars(data.pwmDutycycle[i]));
421 }
422 return true;
423 }
424 return false;
425}
426
428{
431 if (b_cp)
432 {
433 m_rec->log("camera", rerun::DepthImage(
434 reinterpret_cast<const float*>(img.getRawImage()),
435 rerun::WidthHeight(img.width(), img.height())
436 ));
437 return true;
438 }
439 return false;
440}
441
442int main(int argc, char *argv[])
443{
445
446 // Read input parameters
448 rf.configure(argc,argv);
449
450 RerunLogger logger;
451 if (logger.configure(rf)) {
452 logger.runModule();
453 }
454
455 return 0;
456}
#define yInfo(...)
Definition Log.h:319
#define yError(...)
Definition Log.h:361
bool process_RGBImage(const Bottle *pbot)
yarp::os::BufferedPort< yarp::os::Bottle > m_port
Definition yarpRerun.cpp:33
bool process_RobotState(const Bottle *pbot)
bool process_Bottle(const Bottle *pbot)
bool process_Vector(const Bottle *pbot)
bool process_PointCloud(const Bottle *pbot)
void process_Bottle_nested(const Bottle *pbot, std::vector< size_t > path)
bool updateModule() override
Override this to do whatever your module needs to do.
bool process_DepthImage(const Bottle *pbot)
double getPeriod() override
You can override this to control the approximate periodicity at which updateModule() is called by run...
Definition yarpRerun.cpp:63
bool process_SensorStreamingData(const Bottle *pbot)
bool configure(yarp::os::ResourceFinder &rf) override
Configure the module, pass a ResourceFinder object to the module.
Definition yarpRerun.cpp:85
rerun::RecordingStream * m_rec
Definition yarpRerun.cpp:32
bool interruptModule() override
Try to halt any ongoing operations by threads managed by the module.
Definition yarpRerun.cpp:78
bool process_Lidar2D(const Bottle *pbot)
std::vector< SensorMeasurement > measurements
SensorMeasurements SixAxisForceTorqueSensors
SensorMeasurements ThreeAxisMagnetometers
yarp::sig::VectorOf< double > jointAcceleration
Definition jointData.h:31
yarp::sig::VectorOf< int > controlMode
Definition jointData.h:45
yarp::sig::VectorOf< double > current
Definition jointData.h:43
yarp::sig::VectorOf< double > pwmDutycycle
Definition jointData.h:41
yarp::sig::VectorOf< double > torque
Definition jointData.h:39
yarp::sig::VectorOf< double > jointPosition
Definition jointData.h:27
yarp::sig::VectorOf< double > jointVelocity
Definition jointData.h:29
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
size_type size() const
Gets the number of elements in the bottle.
Definition Bottle.cpp:251
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition Bottle.cpp:246
A mini-server for performing network communication in the background.
bool getEnvelope(PortReader &envelope) override
Get the envelope information (e.g., a timestamp) from the last message received on the port.
void close() override
Stop port activity.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
void interrupt() override
Interrupt any current reads or writes attached to the port.
T * read(bool shouldWait=true) override
Read an available object from the port.
static bool connect(const std::string &src, const std::string &dest, const std::string &carrier="", bool quiet=true)
Request that an output port connect to an input port.
Definition Network.cpp:682
Utilities for manipulating the YARP network, including initialization and shutdown.
Definition Network.h:706
static bool copyPortable(const PortWriter &writer, PortReader &reader)
Copy one portable to another, via writing and reading.
Definition Portable.cpp:16
A base-class for standard YARP modules that supports ResourceFinder.
Definition RFModule.h:20
virtual int runModule()
Calls updateModule() until that returns false.
Definition RFModule.cpp:323
Helper class for finding config files and other external resources.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
bool configure(int argc, char *argv[], bool skipFirstArgument=true)
Sets up the ResourceFinder.
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
An abstraction for a time stamp and/or sequence number.
Definition Stamp.h:21
double getTime() const
Get the time stamp.
Definition Stamp.cpp:34
virtual bool isString() const
Checks if value is a string.
Definition Value.cpp:156
virtual bool isList() const
Checks if value is a list.
Definition Value.cpp:162
virtual Bottle * asList() const
Get list value.
Definition Value.cpp:240
virtual yarp::conf::float32_t asFloat32() const
Get 32-bit floating point value.
Definition Value.cpp:216
virtual std::string asString() const
Get string value.
Definition Value.cpp:234
Typed image class.
Definition Image.h:605
size_t width() const
Gets width of image in pixels.
Definition Image.h:171
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition Image.cpp:479
size_t height() const
Gets height of image in pixels.
Definition Image.h:177
virtual size_t width() const
virtual size_t height() const
The PointCloud class.
Definition PointCloud.h:21
size_t size() const
Definition Vector.h:341
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121
An interface to the operating system, including Port based communication.
The main, catch-all namespace for YARP.
Definition dirs.h:16
int main(int argc, char *argv[])