rosotacom-dev 2.5.dev29__py3-none-any.whl → 2.5.dev33__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,15 +27,23 @@
27
27
  // The base is ros-base, not desktop-full: 299 MB compressed against 1422 MB,
28
28
  // and nothing here runs a GUI (enable_gui_forwarding is false above). The
29
29
  // e2e suite was run against both to find out what desktop-full had been
30
- // providing without anyone declaring it — one package, ros-kilted-gps-msgs,
31
- // which the anonymized remote-assist session needs for gps_msgs/msg/GPSFix.
32
- // It is declared below. Add rviz2 or a simulator here if you want them; that
33
- // is a project's decision, not a default.
30
+ // providing without anyone declaring it. It named ros-kilted-gps-msgs, for
31
+ // the gps_msgs/msg/GPSFix the anonymized remote-assist session publishes.
32
+ //
33
+ // It could not name ros-kilted-compressed-image-transport, and that one is
34
+ // why this list is not just an inventory: no e2e session has a /compressed
35
+ // input topic, so the suite never loaded compressed_sub. A vehicle camera
36
+ // does, on both ends of the link — the sender republishes compressed to
37
+ // ffmpeg, the receiver decodes back to the CompressedImage twin. Declaring
38
+ // ros-kilted-image-transport alone gets you raw and nothing else.
39
+ //
40
+ // Add rviz2 or a simulator here if you want them; that is a project's
41
+ // decision, not a default.
34
42
  "build_args": {
35
43
  "BASE_IMAGE": "ros:kilted-ros-base-noble",
36
44
  "DIGEST": "@sha256:4ca53d5b084bdbe92a7a7d7186f56db6a716a6c7c33ad401ddb0ec82d6e9e479",
37
45
  "INSTALL_ZENOH": "1",
38
- "APT_PACKAGES": "iputils-ping psmisc net-tools snmp iw nload iftop iproute2 tshark ros-kilted-domain-bridge ros-kilted-rmw-cyclonedds-cpp ros-kilted-rmw-zenoh-cpp ros-kilted-topic-tools ros-kilted-image-transport ros-kilted-ffmpeg-image-transport ros-kilted-ffmpeg-image-transport-msgs ros-kilted-gps-msgs",
46
+ "APT_PACKAGES": "iputils-ping psmisc net-tools snmp iw nload iftop iproute2 tshark ros-kilted-domain-bridge ros-kilted-rmw-cyclonedds-cpp ros-kilted-rmw-zenoh-cpp ros-kilted-topic-tools ros-kilted-image-transport ros-kilted-compressed-image-transport ros-kilted-ffmpeg-image-transport ros-kilted-ffmpeg-image-transport-msgs ros-kilted-gps-msgs",
39
47
  "PIP_PACKAGES": "numpy>=1.26,<2 lz4 pysnmp speedtest-cli psutil zstandard opencv-python"
40
48
  }
41
49
  }
@@ -52,6 +52,17 @@ topics:
52
52
  local_republish: true
53
53
  gop_size: 4
54
54
  bit_rate: 2000000
55
+ # Wrapping an encoded stream: the wrapper runs after the encoder, so the
56
+ # envelope carries the FFMPEGPacket that actually crosses the link, and
57
+ # the unwrapper republishes onto `/camera/image/ffmpeg` -- the name the
58
+ # reverse republish already decodes from. Nothing downstream is renamed,
59
+ # which is what this example proves end to end.
60
+ use_ota_wrapper: true
55
61
  expect:
56
62
  hz: { min: 3, max: 8 }
57
63
  latency_ms: { max: 1000 }
64
+ # The bound is the same 30% the video-quality check tolerates on this
65
+ # synthetic link; the assertion's purpose is that the number exists at
66
+ # all. Without the wrapper an encoded stream has no per-message
67
+ # accounting, and `loss_pct` on a topic that cannot report it fails.
68
+ loss_pct: { max: 30 }
@@ -27,15 +27,23 @@
27
27
  // The base is ros-base, not desktop-full: 299 MB compressed against 1422 MB,
28
28
  // and nothing here runs a GUI (enable_gui_forwarding is false above). The
29
29
  // e2e suite was run against both to find out what desktop-full had been
30
- // providing without anyone declaring it — one package, ros-kilted-gps-msgs,
31
- // which the anonymized remote-assist session needs for gps_msgs/msg/GPSFix.
32
- // It is declared below. Add rviz2 or a simulator here if you want them; that
33
- // is a project's decision, not a default.
30
+ // providing without anyone declaring it. It named ros-kilted-gps-msgs, for
31
+ // the gps_msgs/msg/GPSFix the anonymized remote-assist session publishes.
32
+ //
33
+ // It could not name ros-kilted-compressed-image-transport, and that one is
34
+ // why this list is not just an inventory: no e2e session has a /compressed
35
+ // input topic, so the suite never loaded compressed_sub. A vehicle camera
36
+ // does, on both ends of the link — the sender republishes compressed to
37
+ // ffmpeg, the receiver decodes back to the CompressedImage twin. Declaring
38
+ // ros-kilted-image-transport alone gets you raw and nothing else.
39
+ //
40
+ // Add rviz2 or a simulator here if you want them; that is a project's
41
+ // decision, not a default.
34
42
  "build_args": {
35
43
  "BASE_IMAGE": "ros:kilted-ros-base-noble",
36
44
  "DIGEST": "@sha256:4ca53d5b084bdbe92a7a7d7186f56db6a716a6c7c33ad401ddb0ec82d6e9e479",
37
45
  "INSTALL_ZENOH": "1",
38
- "APT_PACKAGES": "iputils-ping psmisc net-tools snmp iw nload iftop iproute2 tshark ros-kilted-domain-bridge ros-kilted-rmw-cyclonedds-cpp ros-kilted-rmw-zenoh-cpp ros-kilted-topic-tools ros-kilted-image-transport ros-kilted-ffmpeg-image-transport ros-kilted-ffmpeg-image-transport-msgs ros-kilted-gps-msgs",
46
+ "APT_PACKAGES": "iputils-ping psmisc net-tools snmp iw nload iftop iproute2 tshark ros-kilted-domain-bridge ros-kilted-rmw-cyclonedds-cpp ros-kilted-rmw-zenoh-cpp ros-kilted-topic-tools ros-kilted-image-transport ros-kilted-compressed-image-transport ros-kilted-ffmpeg-image-transport ros-kilted-ffmpeg-image-transport-msgs ros-kilted-gps-msgs",
39
47
  "PIP_PACKAGES": "numpy>=1.26,<2 lz4 pysnmp speedtest-cli psutil zstandard opencv-python"
40
48
  }
41
49
  }
@@ -75,6 +75,7 @@ from com_py.status_overview_core import (
75
75
  StatusAggregator,
76
76
  collect_stage_metadata,
77
77
  collect_stage_topics,
78
+ stamp_delay,
78
79
  )
79
80
 
80
81
  ECHO_HEARTBEAT_TYPE = "com_msgs/msg/EchoHeartbeat"
@@ -274,12 +275,26 @@ class StageObserver(Node):
274
275
  stamp = getattr(header, "stamp", None) if header is not None else None
275
276
  if stamp is not None:
276
277
  try:
277
- msg_time = rclpy.time.Time.from_msg(stamp)
278
- d = (now_ros - msg_time).nanoseconds / 1e9
279
- if -1.0 < d < 1000.0: # guard unsynced clocks / zero stamps
280
- delay_s = d
278
+ stamp_s = _stamp_seconds(stamp)
281
279
  except Exception:
282
- delay_s = None
280
+ stamp_s = None
281
+ if stamp_s is not None:
282
+ d = now_ros_s - stamp_s
283
+ # An inbound stage carries a stamp written by the peer's
284
+ # clock, so it is comparable to ours only once the offset
285
+ # the heartbeat measures is applied -- exactly what the
286
+ # OtaStamped branch above does with `t_wrap`. A local
287
+ # stage was stamped by this machine and must stay raw.
288
+ contexts = self._stage_metadata.get(topic, [])
289
+ peer_stamped = any(
290
+ context.get("direction") == "inbound" for context in contexts
291
+ )
292
+ estimate = self.clock_estimator.estimate() if peer_stamped else None
293
+ if estimate is not None:
294
+ clock_offset_s = estimate["offset_s"]
295
+ rtt_s = estimate["rtt_s"]
296
+ raw_delay_s = d
297
+ delay_s = stamp_delay(d, clock_offset_s)
283
298
 
284
299
  obs.record(
285
300
  size,
@@ -148,6 +148,33 @@ class ClockOffsetEstimator:
148
148
  }
149
149
 
150
150
 
151
+ #: Plausibility window (seconds) for a latency derived from a message header
152
+ #: stamp. Outside it the number is not a latency but an unset stamp (epoch 0) or
153
+ #: a clock difference no offset estimate explains.
154
+ STAMP_DELAY_MIN_S = -1.0
155
+ STAMP_DELAY_MAX_S = 1000.0
156
+
157
+
158
+ def stamp_delay(raw_delay_s: float, clock_offset_s: Optional[float] = None) -> Optional[float]:
159
+ """Latency from a header stamp, corrected by the estimated peer clock offset.
160
+
161
+ ``raw_delay_s`` is ``local_now - stamp``. ``clock_offset_s`` is peer clock
162
+ minus local clock (as ``ClockOffsetEstimator`` reports it), so the corrected
163
+ delay is their sum -- the same arithmetic the OtaStamped path uses on its
164
+ ``t_wrap``.
165
+
166
+ Returns ``None`` when the result falls outside the plausibility window. The
167
+ guard is applied to the corrected value on purpose: a topic whose stamp is
168
+ written by the peer used to be dropped for an offset this node has already
169
+ measured, which reads as "no latency available" instead of "latency, once
170
+ the clocks are reconciled".
171
+ """
172
+ corrected = raw_delay_s if clock_offset_s is None else raw_delay_s + clock_offset_s
173
+ if STAMP_DELAY_MIN_S < corrected < STAMP_DELAY_MAX_S:
174
+ return corrected
175
+ return None
176
+
177
+
151
178
  # --- Link overhead (session-level) -----------------------------------------
152
179
 
153
180
  def _payload_kbps(stage: Optional[Dict[str, Any]]) -> float:
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
+ import array
3
4
  import re
4
5
  from threading import Lock
5
6
 
@@ -139,7 +140,12 @@ class UniversalOtaWrapperNode(Node):
139
140
  out_msg.header.frame_id = header.frame_id
140
141
  out_msg.seq = self._next_sequence(source_topic)
141
142
  out_msg.msg_type = msg_type_str
142
- out_msg.serialized_msg = list(serialized)
143
+ # array('B', ...) hits the generated setter's fast path and stores the
144
+ # buffer as-is. A list would allocate one Python int per payload byte,
145
+ # inside the interval that `header.stamp` above is meant to measure --
146
+ # and rule out wrapping anything large (a ~100 kB encoded video packet
147
+ # at 10 Hz is 1M allocations per second).
148
+ out_msg.serialized_msg = array.array('B', serialized)
143
149
 
144
150
  publisher.publish(out_msg)
145
151
  except Exception as exc:
@@ -1255,11 +1255,15 @@ def _final_topic_type(entry: TopicEntry, pipe: Dict[str, Any]) -> str:
1255
1255
  f"Unsupported transport type '{transport.type}' for topic '{entry.base}'. "
1256
1256
  f"Known output type mappings: {sorted(TRANSPORT_OUTPUT_TYPES)}"
1257
1257
  )
1258
- return TRANSPORT_OUTPUT_TYPES[transport.type]
1259
1258
 
1259
+ # Same order as the pipeline stages themselves: whatever is applied last
1260
+ # decides the type of what crosses the link, and the wrapper is always last.
1260
1261
  if pipe.get("ota_wrap"):
1261
1262
  return OTA_STAMPED_MSG_TYPE
1262
1263
 
1264
+ if transport is not None:
1265
+ return TRANSPORT_OUTPUT_TYPES[transport.type]
1266
+
1263
1267
  if pipe.get("compress"):
1264
1268
  return COMPRESSED_MSG_TYPE
1265
1269
 
@@ -1271,6 +1275,49 @@ def _final_topic_type(entry: TopicEntry, pipe: Dict[str, Any]) -> str:
1271
1275
  return msg_type
1272
1276
 
1273
1277
 
1278
+ def _delivered_topic(pipe: Dict[str, Any], final: str) -> str:
1279
+ """The topic the receiver's post-processing chain ends on, before trickle.
1280
+
1281
+ The receiver undoes the sender's stages in reverse order, so this walks the
1282
+ same chain backwards rather than picking one branch: unwrap, decode a
1283
+ transport, decompress, framebridge down.
1284
+ """
1285
+ topic = final
1286
+ if pipe.get("ota_wrap"):
1287
+ # The unwrapper republishes on the pre-wrap name, which is why wrapping
1288
+ # renames nothing downstream of it.
1289
+ topic = str(pipe["ota_in"])
1290
+ transport = pipe.get("transport")
1291
+ if isinstance(transport, TransportSpec) and transport.local_republish:
1292
+ # image_transport reverse republish decodes the encoded topic into
1293
+ # `<encoded>/raw`; PSNR/SSIM and application-level checks need that
1294
+ # decoded sensor_msgs/Image stage, not the encoded packet.
1295
+ topic = str(pipe["irt_in"]) + "/raw"
1296
+ elif pipe.get("compress"):
1297
+ topic = str(pipe["comp_in"])
1298
+ if pipe.get("framebridge") == "global_to_local":
1299
+ # global_to_local runs on the receiver: the OTA `final` is the global
1300
+ # (globalframe) topic, and the framebridge transforms it down to the
1301
+ # local base topic -- that base is the post-framebridge native_in.
1302
+ topic = str(pipe["fb_g2l_base"])
1303
+ return topic
1304
+
1305
+
1306
+ def _postprocessed_topic(pipe: Dict[str, Any], final: str) -> str:
1307
+ """The topic the receiving application actually reads."""
1308
+ topic = _delivered_topic(pipe, final)
1309
+ if pipe.get("trickle_hz") is not None:
1310
+ # Receiver-side trickle re-publishes the delivered topic at a fixed rate
1311
+ # to `<delivered>/trickle` (the trickle node's trickle_topic_suffix).
1312
+ # That republished topic is the real delivered output, so it is the
1313
+ # monitored native_in stage -- otherwise the trickle re-publish is an
1314
+ # observability blind spot (its rate cannot be asserted). It republishes
1315
+ # what the application would read, not the envelope: on a wrapped topic
1316
+ # that is the unwrapped one.
1317
+ topic = topic + "/trickle"
1318
+ return topic
1319
+
1320
+
1274
1321
  def _heartbeat_monitor_overrides(heartbeat_expect: Optional[Dict[str, Any]]) -> List[Tuple[str, Any]]:
1275
1322
  """Override the heartbeat_echo status thresholds from a declared
1276
1323
  `shared.heartbeat.expect`. Only latency and loss map cleanly to the monitor's
@@ -1342,31 +1389,6 @@ def _build_status_pipeline_spec(
1342
1389
  return float(pipe["trickle_hz"])
1343
1390
  return None
1344
1391
 
1345
- def _postprocessed_topic(pipe: Dict[str, Any], final: str) -> str:
1346
- if pipe.get("trickle_hz") is not None:
1347
- # Receiver-side trickle re-publishes the delivered OTA `final` at a fixed
1348
- # rate to `<final>/trickle` (the trickle node's trickle_topic_suffix). That
1349
- # republished topic is the real delivered output, so it is the monitored
1350
- # native_in stage -- otherwise the trickle re-publish is an observability
1351
- # blind spot (its rate cannot be asserted).
1352
- return final + "/trickle"
1353
- if pipe.get("compress"):
1354
- return str(pipe["comp_in"])
1355
- if pipe.get("ota_wrap"):
1356
- return str(pipe["ota_in"])
1357
- if pipe.get("framebridge") == "global_to_local":
1358
- # global_to_local runs on the receiver: the OTA `final` is the global
1359
- # (globalframe) topic, and the framebridge transforms it down to the
1360
- # local base topic -- that base is the post-framebridge native_in.
1361
- return str(pipe["fb_g2l_base"])
1362
- transport = pipe.get("transport")
1363
- if isinstance(transport, TransportSpec) and transport.local_republish:
1364
- # image_transport reverse republish decodes `<final>` into
1365
- # `<final>/raw`; PSNR/SSIM and application-level checks need that
1366
- # decoded sensor_msgs/Image stage, not the encoded packet.
1367
- return final + "/raw"
1368
- return final
1369
-
1370
1392
  def _relay_in_local_topic(topic: str) -> str:
1371
1393
  if inbound_keep_source_prefix:
1372
1394
  return f"/{remote_name}{topic}"
@@ -1714,11 +1736,6 @@ def _compute_pipeline(
1714
1736
  comp_in = topic
1715
1737
  topic = topic + comp_alg_suffix
1716
1738
 
1717
- ota_in = None
1718
- if ota_wrap:
1719
- ota_in = topic
1720
- topic = topic + ota_suffix
1721
-
1722
1739
  it_in = None
1723
1740
  irt_in = None
1724
1741
  if transport:
@@ -1727,6 +1744,15 @@ def _compute_pipeline(
1727
1744
  if transport.local_republish:
1728
1745
  irt_in = topic
1729
1746
 
1747
+ # The wrapper is last, always. Its `seq` and send stamp describe whatever it
1748
+ # wraps, so anything applied after it would be measured by an envelope that
1749
+ # never carried it -- and would append its own suffix to the wrapped name,
1750
+ # renaming the delivered topic under a receiver that subscribes by name.
1751
+ ota_in = None
1752
+ if ota_wrap:
1753
+ ota_in = topic
1754
+ topic = topic + ota_suffix
1755
+
1730
1756
  return {
1731
1757
  "final": topic,
1732
1758
  "restamp": restamp,
@@ -2546,8 +2572,16 @@ def func(
2546
2572
  # Trickle: local-only periodic republisher (receiver side only).
2547
2573
  # Subscribes to inbound final topics (with source-name prefix when applicable)
2548
2574
  # and republishes at a fixed rate for visualization software.
2575
+ # Trickle runs at the very end of the receiver chain, so it republishes
2576
+ # what the local post-processing produced -- not the OTA `final`, which
2577
+ # on a wrapped topic is still the envelope. `_delivered_topic` is the
2578
+ # same computation the status pipeline spec uses for `native_in`, so the
2579
+ # two cannot drift apart.
2549
2580
  trickle_in_items = [
2550
- (_prefix_with_source_name_if_needed(local, remote, p["final"]), p["trickle_hz"])
2581
+ (
2582
+ _prefix_with_source_name_if_needed(local, remote, _delivered_topic(p, p["final"])),
2583
+ p["trickle_hz"],
2584
+ )
2551
2585
  for p in in_pipes
2552
2586
  if p["trickle_hz"] is not None
2553
2587
  ]
@@ -2599,7 +2633,10 @@ def func(
2599
2633
  if not p["normalize"]:
2600
2634
  continue
2601
2635
  base = e.base.lstrip("/")
2602
- suffix_source = p["comp_in"] if p["comp_in"] else p["final"]
2636
+ # Normalization is receiver-side too, so it works on the delivered
2637
+ # topic rather than the OTA `final` (identical unless something is
2638
+ # wrapped, where `final` is still the envelope).
2639
+ suffix_source = _delivered_topic(p, p["final"])
2603
2640
  suffix = suffix_source[len(e.base) :]
2604
2641
  nor_items.append((base, suffix))
2605
2642
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rosotacom-dev
3
- Version: 2.5.dev29
3
+ Version: 2.5.dev33
4
4
  Summary: Host CLI for ROS OTA communication sessions.
5
5
  Author: develNor
6
6
  License-Expression: BSD-3-Clause
@@ -23,13 +23,13 @@ rosotacom/trace_profiles.py,sha256=KNM1RExHDXkppWZdqbSPXTjwJ8f7io8IU48HnKzmHKY,2
23
23
  rosotacom/transit.py,sha256=0BqDO3nfYJ1PMXRz8b3084sDOrCjhO5zwdqC_-qU6bo,10531
24
24
  rosotacom/video_quality.py,sha256=9NqWA3MgHDvjGmJoHHXQCqb17cyIkHYTrkwNxBoVqMA,33845
25
25
  rosotacom/resources/benched-set.yaml,sha256=wbWsoPHRQ5ji_pjM-rPe0dOSXv5kfD31FJoTn9YGsO0,14978
26
- rosotacom/resources/ros2docker.json.example,sha256=57d-jx4zFo0_2Wg6zQ_aCLHGU-f4I7rn0mP5JUs84zk,2104
26
+ rosotacom/resources/ros2docker.json.example,sha256=ARbtWmVNWCcAMcFhaHIPBocefDlc9Zx8gHS47uD5D_Q,2582
27
27
  rosotacom/resources/examples/.gitignore,sha256=9FFIV42CR379XRSDOC9UdXsfJP8cGACLjHxiU9TJG6E,19
28
28
  rosotacom/resources/examples/README.md,sha256=RclnxBhlKcl9nRp2PvllVy6akKMZ82cOLv29et-SPyQ,5889
29
29
  rosotacom/resources/examples/__init__.py,sha256=IKLiqdO5jeBX3rMkWyb_Uc3SrQZp5vkJtqoTD_NZ90E,52
30
30
  rosotacom/resources/examples/deployment.example.yaml,sha256=E3HMJhv-Ft5mA6PC8d7yVZz1uwG3OQhCD_MBnhxtvAg,450
31
31
  rosotacom/resources/examples/profiles.yaml,sha256=KhmbIvO7GAWEQEm8QmIr_VCP14eioh_nSohxFf9gouw,3375
32
- rosotacom/resources/examples/ros2docker.json,sha256=Icpu5RIccdcHNL1rq6eqQJI7gdGe6Q6o9L4dGuJOETY,2062
32
+ rosotacom/resources/examples/ros2docker.json,sha256=jX9YYAD1plb9oJsjtRcJuPA5t542x6iRZ6eInUG5IQE,2540
33
33
  rosotacom/resources/examples/rosotacom.yaml,sha256=lpFnRNJv9kjS3Pd6dJAG1PXF-UP-YbSOK8dNcUe68hY,351
34
34
  rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml,sha256=esIzUWq2anN89egMyZcHDCs5eIuVyruSU0eZPtfo2-c,445
35
35
  rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml,sha256=rxDLMqCyX-WR0Q4moGgmDhxpO4ffvf9pSSihJhXAsNQ,313
@@ -85,7 +85,7 @@ rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml,sh
85
85
  rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml,sha256=tWT5ixqp5Vd_34TIiWMJ35nsYnQGKXOMSHPamIl-ebs,5176
86
86
  rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml,sha256=rCRHhkz5acsvlB1Y6hdvF8L_1Y1EnX6mGNDNu2VV4Zc,1766
87
87
  rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml,sha256=xoYZkieGMzQnKg2V0PEeDStNPcyC6j8WSahexPOtFZw,1949
88
- rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml,sha256=gDrOODjU36qHOQL0g4yozSi27Ix28l2z7oF_VL2ZkQs,1239
88
+ rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml,sha256=5wxiQ28Rg1Za48XhywHg5I1_Oc86PRGvOsQyNBy0zaI,1983
89
89
  rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml,sha256=026HR2Q8bvqbZpoeMw7qXPU2aGzD3HcqlZFckum3FDQ,407
90
90
  rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml,sha256=p2iEIOCFbW5ojaNqucSM7ZGPu-dbPl7gXAVhRRB7ojI,1033
91
91
  rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml,sha256=Zjdbj0U8eAaQXW5aLaKtRldlh7YKhDs1vczZD9AuE6Y,670
@@ -159,8 +159,8 @@ rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py,sha256=S8LjtZs_WBdnvL5oN
159
159
  rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py,sha256=prpmQf_cXp3KMYw3FlBZfNhq0Rrz56YUjWOunVF6xL8,9259
160
160
  rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py,sha256=su_oWQBeDeLHdCy08YzzsASPgYoWID-syqqVkrjSg4g,2768
161
161
  rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py,sha256=VXR0EN8EdExxLSb8UbY4mTv94khLZi6weqJpQtRMbd8,2600
162
- rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py,sha256=l9blUDfBePFKGxAvEoFPg3buAUU6Z12l3jZdoXVwISw,21337
163
- rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py,sha256=q0eGd20F39CI5qx7aFxB2cA4uQ_TFn2o_H9G2VTW6H8,44165
162
+ rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py,sha256=C9WK6bhW-8rKPmqcmtC3Wl8kTluEiS4lR-sGwg9Dh-k,22245
163
+ rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py,sha256=evMMHhuOggQ_W28z12aJLH0KAayxfQJJmeYC13bUthU,45407
164
164
  rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py,sha256=eWq0D-pVDadj186e2ZC4kZpxTBkXMzi24BfBj3NjGXc,3777
165
165
  rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py,sha256=tS_7gLtEVwyPBE2kk_khFBvJSiHaUPSK8w2OtJRSJRc,15019
166
166
  rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py,sha256=WA34WSuY4jpzqsJ9S3HgETTWP5tZHGsslF7FAqE8oik,7092
@@ -168,7 +168,7 @@ rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py,sha256=gp2qb55dEuF_7LsqD
168
168
  rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py,sha256=b_teazIo8ymguKq-f9Xpwe3Q4uRFBhCqb1qB5EC0NP0,25730
169
169
  rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py,sha256=h-S0hegzxrI4I5hemPj0M3aCys1zJd7sAgtvjJesCsg,16041
170
170
  rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py,sha256=AOj8IUxBlqn3IfUUEcEIz6lyB0Ni4Lq5O8Ep8a3Cagw,7587
171
- rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py,sha256=wvEWgY79DK-vLtGlwX5k_fAHC8TgpcZsA3TM_Y7NyRo,5750
171
+ rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py,sha256=Y3MjXWpYLNV3MzjHPgqDehsIwlEe-mqgxVCegNe5y1w,6161
172
172
  rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py,sha256=lcS4mdKTyhfjpuOZ5jqwuThRGipt4lYBCX7C2OGUVg8,2938
173
173
  rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py,sha256=dyhpCEXkqbpMQCrSx9-qYL47k7dVszmT2hyDazMi8vE,3559
174
174
  rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py,sha256=bR7ag8q7x33qG_2qF-sRIYAIUaAvzEoZ45p4XqiXJWo,4589
@@ -185,13 +185,13 @@ rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py,sha256
185
185
  rosotacom/resources/ws/session/creation/anonymize_bag.py,sha256=jxOTKFjmde-pyoVWE9-9icpSjf4nh97-q2Eqx-BDUl8,6154
186
186
  rosotacom/resources/ws/session/creation/catmux_log_setup.sh,sha256=d6slqefxfCUhBlGWw3fkC50RbntuQR93e8h54hTww7c,3135
187
187
  rosotacom/resources/ws/session/creation/create_session_yaml.py,sha256=8cfzkUxK7IebIBC36Vu7lcWtogM8fG0zveBCUGeiVdU,5727
188
- rosotacom/resources/ws/session/creation/generate_session_files.py,sha256=AlkxApxsFJWCAPjCdnLcUYVwjXzlCuJjedAwP5yTQ8E,139984
188
+ rosotacom/resources/ws/session/creation/generate_session_files.py,sha256=Iw5spNwJrO7FLRGMk2pxnj5CBVkmkuQKLOulF-jUzQs,141798
189
189
  rosotacom/resources/ws/session/creation/run_session.py,sha256=G2hJhrmLp11gm3JZ6_C-zZcqu_reXlE_wmobB7BiCfU,16849
190
190
  rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py,sha256=Ub_5f-ttUUc-rAPrZmg_Op34s8Z4C91hTyEn8fgyt-E,2633
191
191
  rosotacom/resources/ws/session/creation/strip_ansi.py,sha256=vNjpemcq4xHr0VG4x0bZqvgwEBEfOgN-b4PzbrM5nfM,851
192
- rosotacom_dev-2.5.dev29.dist-info/licenses/LICENSE.txt,sha256=FDB3-fao3lqZ94wsJHKAH7U88kAnfvZhZC8Hm5rN__g,1459
193
- rosotacom_dev-2.5.dev29.dist-info/METADATA,sha256=ZYzA1qHTeKXTfQtwdk6xo2ttgwlQ8mspDgirHirCep0,52217
194
- rosotacom_dev-2.5.dev29.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
195
- rosotacom_dev-2.5.dev29.dist-info/entry_points.txt,sha256=-Hl9WKAfkLjMHUonDTxvz86EgSfZf6oyatRMxypS5iA,147
196
- rosotacom_dev-2.5.dev29.dist-info/top_level.txt,sha256=BZrtQcIVDWn_pQZR3Mlssqy5SaRXHjOa6B-1D9Fy4Ao,10
197
- rosotacom_dev-2.5.dev29.dist-info/RECORD,,
192
+ rosotacom_dev-2.5.dev33.dist-info/licenses/LICENSE.txt,sha256=FDB3-fao3lqZ94wsJHKAH7U88kAnfvZhZC8Hm5rN__g,1459
193
+ rosotacom_dev-2.5.dev33.dist-info/METADATA,sha256=aNZPP_sF9HgAcaTI9RFmiBnUfN9k5NiI2vd8ERmvimI,52217
194
+ rosotacom_dev-2.5.dev33.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
195
+ rosotacom_dev-2.5.dev33.dist-info/entry_points.txt,sha256=-Hl9WKAfkLjMHUonDTxvz86EgSfZf6oyatRMxypS5iA,147
196
+ rosotacom_dev-2.5.dev33.dist-info/top_level.txt,sha256=BZrtQcIVDWn_pQZR3Mlssqy5SaRXHjOa6B-1D9Fy4Ao,10
197
+ rosotacom_dev-2.5.dev33.dist-info/RECORD,,