spatialdds-ros 0.4.0__tar.gz → 0.4.1__tar.gz
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.
- {spatialdds_ros-0.4.0/spatialdds_ros.egg-info → spatialdds_ros-0.4.1}/PKG-INFO +1 -1
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/package.xml +1 -1
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/setup.py +1 -1
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/__init__.py +1 -1
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/robot_node.py +97 -2
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1/spatialdds_ros.egg-info}/PKG-INFO +1 -1
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros.egg-info/SOURCES.txt +1 -0
- spatialdds_ros-0.4.1/test/test_node_honesty.py +45 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/LICENSE +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/README.md +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/resource/spatialdds_ros +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/setup.cfg +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/PROVENANCE.md +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/_field_aliases.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/builtin/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/builtin/_types.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/anchors/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/anchors/_anchors.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/argeo/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/argeo/_argeo.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/common/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/common/_types.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/core/GnssService/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/core/GnssService/_core.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/core/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/core/_core.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/disco/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/disco/_discovery.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/_events.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/crossing_direction_enum/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/crossing_direction_enum/_events.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/event_state_enum/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/event_state_enum/_events.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/event_type_enum/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/event_type_enum/_events.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/severity_enum/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/severity_enum/_events.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/zone_kind_enum/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/zone_kind_enum/_events.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/_mapping.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/alignment_method/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/alignment_method/_mapping.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/edge_type/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/edge_type/_mapping.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/map_event_kind/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/map_event_kind/_mapping.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/map_kind/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/map_kind/_mapping.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/map_status/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/map_status/_mapping.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/owm/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/owm/_owm.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/semantics/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/semantics/_semantics.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/common/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/common/_common.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/lidar/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/lidar/_lidar.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/rad/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/rad/_rad.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/radio/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/radio/_radio.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/rf_beam/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/rf_beam/_rf_beam.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/vision/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/vision/_vision.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/slam_frontend/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/slam_frontend/_slam_frontend.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/vio/__init__.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/vio/_vio.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/adapter.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/announce.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/awareness.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/config.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/frames.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/kinematic.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/qos.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/recording.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/standalone.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/tempo.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/topics.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros/transport.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros.egg-info/dependency_links.txt +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros.egg-info/entry_points.txt +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros.egg-info/requires.txt +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros.egg-info/top_level.txt +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_ros.egg-info/zip-safe +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_acceptance_bare_scene.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_acceptance_mcap_gateway.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_acceptance_two_domains.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_acceptance_web_to_robot.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_adapter.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_awareness.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_config.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_frames.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_generated_types.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_kinematic.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_no_ros_needed.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_packaging.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_qos_and_tempo.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_readme.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_transport.py +0 -0
- {spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/test/test_types_resolve_at_definitions.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://relaxng.org/ns/structure/1.0"?>
|
|
3
3
|
<package format="3">
|
|
4
4
|
<name>spatialdds_ros</name>
|
|
5
|
-
<version>0.4.
|
|
5
|
+
<version>0.4.1</version>
|
|
6
6
|
<description>
|
|
7
7
|
Makes a ROS 2 robot a SpatialDDS participant: its pose published as a
|
|
8
8
|
spatial.owm entity on scene-scoped topics, goto commands consumed from
|
|
@@ -42,7 +42,7 @@ LONG_DESCRIPTION = (HERE / "README.md").read_text(encoding="utf-8")
|
|
|
42
42
|
|
|
43
43
|
setup(
|
|
44
44
|
name="spatialdds-ros",
|
|
45
|
-
version="0.4.
|
|
45
|
+
version="0.4.1",
|
|
46
46
|
# `spatialdds_idl18` ships alongside: the generated bindings annotate
|
|
47
47
|
# nested members with their own fully-qualified names, so the package has
|
|
48
48
|
# to be importable as `spatialdds_idl18` and cannot be nested inside this
|
|
@@ -198,6 +198,7 @@ def main(argv=None) -> int: # pragma: no cover
|
|
|
198
198
|
from tf2_ros import Buffer, TransformListener
|
|
199
199
|
self._tf_buffer = Buffer()
|
|
200
200
|
self._tf_listener = TransformListener(self._tf_buffer, self)
|
|
201
|
+
self._tf_freshness = TfFreshness()
|
|
201
202
|
self._read_pose = self._pose_from_tf
|
|
202
203
|
elif source == "amcl":
|
|
203
204
|
from geometry_msgs.msg import PoseWithCovarianceStamped
|
|
@@ -225,6 +226,14 @@ def main(argv=None) -> int: # pragma: no cover
|
|
|
225
226
|
# not converged yet simply has no transform, and the adapter's
|
|
226
227
|
# own silence handling already describes that state correctly.
|
|
227
228
|
return
|
|
229
|
+
# A transform the buffer has already answered with is not a new
|
|
230
|
+
# observation. Asked for "the latest", the buffer keeps returning
|
|
231
|
+
# the last transform it heard after its publisher has died, and
|
|
232
|
+
# calling that a sighting every tick kept a dead robot ACTIVE and
|
|
233
|
+
# freshly stamped forever -- the floor republishing a ghost the
|
|
234
|
+
# adapter's silence rule could never catch (finding 10).
|
|
235
|
+
if not self._tf_freshness.new(tf.header.stamp):
|
|
236
|
+
return
|
|
228
237
|
t = tf.transform.translation
|
|
229
238
|
self.adapter.observed(t.x, t.y, _yaw_of(tf.transform.rotation))
|
|
230
239
|
|
|
@@ -378,6 +387,9 @@ def main(argv=None) -> int: # pragma: no cover
|
|
|
378
387
|
self._goal_type = NavigateToPose
|
|
379
388
|
self._client = ActionClient(node, NavigateToPose, action_name)
|
|
380
389
|
self._action_name = action_name
|
|
390
|
+
# Only the latest goal may report. A goal superseded by a newer
|
|
391
|
+
# one ends too, and its ending is not news about the robot.
|
|
392
|
+
self._seq = 0
|
|
381
393
|
|
|
382
394
|
def available(self) -> Optional[str]:
|
|
383
395
|
if not self._client.server_is_ready():
|
|
@@ -397,8 +409,48 @@ def main(argv=None) -> int: # pragma: no cover
|
|
|
397
409
|
goal.pose.pose.position.y = y
|
|
398
410
|
goal.pose.pose.position.z = self._node.config.ground_z
|
|
399
411
|
goal.pose.pose.orientation.w = 1.0
|
|
400
|
-
self.
|
|
401
|
-
|
|
412
|
+
self._seq += 1
|
|
413
|
+
seq = self._seq
|
|
414
|
+
future = self._client.send_goal_async(goal)
|
|
415
|
+
future.add_done_callback(
|
|
416
|
+
lambda f: self._on_response(f, seq, x, y))
|
|
417
|
+
# Sent, not accepted: nav2 has not answered yet. Until 0.4.1 this
|
|
418
|
+
# said "accepted", and whatever nav2 then decided went nowhere: a
|
|
419
|
+
# rejected or aborted goal reached the robot's log and no client
|
|
420
|
+
# (finding 11).
|
|
421
|
+
return f"sent a goal at ({x:.2f}, {y:.2f}) to nav2"
|
|
422
|
+
|
|
423
|
+
def _on_response(self, future, seq: int, x: float, y: float) -> None:
|
|
424
|
+
if seq != self._seq:
|
|
425
|
+
return
|
|
426
|
+
try:
|
|
427
|
+
handle = future.result()
|
|
428
|
+
except Exception as error: # noqa: BLE001
|
|
429
|
+
self._refuse(f"goal ({x:.2f}, {y:.2f}) could not be sent to "
|
|
430
|
+
f"nav2: {error}")
|
|
431
|
+
return
|
|
432
|
+
if not handle.accepted:
|
|
433
|
+
self._refuse(goal_outcome(False, None, x, y))
|
|
434
|
+
return
|
|
435
|
+
handle.get_result_async().add_done_callback(
|
|
436
|
+
lambda f: self._on_result(f, seq, x, y))
|
|
437
|
+
|
|
438
|
+
def _on_result(self, future, seq: int, x: float, y: float) -> None:
|
|
439
|
+
if seq != self._seq:
|
|
440
|
+
return
|
|
441
|
+
try:
|
|
442
|
+
status = future.result().status
|
|
443
|
+
except Exception as error: # noqa: BLE001
|
|
444
|
+
self._refuse(f"goal ({x:.2f}, {y:.2f}): nav2 gave no result: "
|
|
445
|
+
f"{error}")
|
|
446
|
+
return
|
|
447
|
+
why = goal_outcome(True, status, x, y)
|
|
448
|
+
if why:
|
|
449
|
+
self._refuse(why)
|
|
450
|
+
|
|
451
|
+
def _refuse(self, why: str) -> None:
|
|
452
|
+
self._node.adapter.refused(why)
|
|
453
|
+
self._node.get_logger().info(why)
|
|
402
454
|
|
|
403
455
|
try:
|
|
404
456
|
node = SpatialDdsRobot()
|
|
@@ -416,6 +468,49 @@ def main(argv=None) -> int: # pragma: no cover
|
|
|
416
468
|
return 0
|
|
417
469
|
|
|
418
470
|
|
|
471
|
+
class TfFreshness:
|
|
472
|
+
"""Whether a looked-up transform is a new observation, by its stamp.
|
|
473
|
+
|
|
474
|
+
Compared stamp to stamp, never to a clock, so a sim on its own time and a
|
|
475
|
+
robot on wall time are treated alike: a transform is new if its stamp is
|
|
476
|
+
not the one the buffer answered with last time.
|
|
477
|
+
"""
|
|
478
|
+
|
|
479
|
+
def __init__(self) -> None:
|
|
480
|
+
self._last: Optional[tuple] = None
|
|
481
|
+
|
|
482
|
+
def new(self, stamp) -> bool:
|
|
483
|
+
key = (int(stamp.sec), int(stamp.nanosec))
|
|
484
|
+
if key == self._last:
|
|
485
|
+
return False
|
|
486
|
+
self._last = key
|
|
487
|
+
return True
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
#: action_msgs/GoalStatus, the three endings.
|
|
491
|
+
GOAL_SUCCEEDED, GOAL_CANCELED, GOAL_ABORTED = 4, 5, 6
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def goal_outcome(accepted: bool, status: Optional[int],
|
|
495
|
+
x: float, y: float) -> Optional[str]:
|
|
496
|
+
"""The refusal a goal's ending owes its requester, or None if it arrived.
|
|
497
|
+
|
|
498
|
+
A goal nav2 would not take, or gave up on, travels to whoever asked on the
|
|
499
|
+
robot's latched record (`RobotAdapter.refused`), as the kinematic fallback's
|
|
500
|
+
refusals always have.
|
|
501
|
+
"""
|
|
502
|
+
if not accepted:
|
|
503
|
+
return f"goal ({x:.2f}, {y:.2f}) rejected by nav2"
|
|
504
|
+
if status == GOAL_SUCCEEDED:
|
|
505
|
+
return None
|
|
506
|
+
if status == GOAL_ABORTED:
|
|
507
|
+
return (f"goal ({x:.2f}, {y:.2f}) abandoned: nav2 could not reach it "
|
|
508
|
+
f"(no plan, or the controller gave up)")
|
|
509
|
+
if status == GOAL_CANCELED:
|
|
510
|
+
return f"goal ({x:.2f}, {y:.2f}) cancelled before it was reached"
|
|
511
|
+
return f"goal ({x:.2f}, {y:.2f}) ended in nav2 status {status}"
|
|
512
|
+
|
|
513
|
+
|
|
419
514
|
def _yaw_of(q) -> float:
|
|
420
515
|
"""Yaw from a ROS quaternion message."""
|
|
421
516
|
return math.atan2(2.0 * (q.w * q.z + q.x * q.y),
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""The nav2 node says only what it saw: findings 10 and 11, without ROS.
|
|
2
|
+
|
|
3
|
+
The node itself needs rclpy, so its two decisions are module-level and are
|
|
4
|
+
checked here directly; the ROS run that shows them end to end is SpatialDDS-
|
|
5
|
+
demo's `robot-captures.spec.ts`, "the sim dies...", against the nav2 tier.
|
|
6
|
+
"""
|
|
7
|
+
from types import SimpleNamespace
|
|
8
|
+
|
|
9
|
+
from spatialdds_ros.robot_node import (
|
|
10
|
+
GOAL_ABORTED, GOAL_CANCELED, GOAL_SUCCEEDED, TfFreshness, goal_outcome)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def stamp(sec, nanosec=0):
|
|
14
|
+
return SimpleNamespace(sec=sec, nanosec=nanosec)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_a_transform_already_answered_is_not_a_new_observation():
|
|
18
|
+
"""Finding 10: the buffer's last transform, asked for again after its
|
|
19
|
+
publisher died, must not count as a sighting."""
|
|
20
|
+
fresh = TfFreshness()
|
|
21
|
+
assert fresh.new(stamp(100, 5)) is True
|
|
22
|
+
assert fresh.new(stamp(100, 5)) is False # the sim died here
|
|
23
|
+
assert fresh.new(stamp(100, 5)) is False
|
|
24
|
+
assert fresh.new(stamp(100, 6)) is True # and came back
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_freshness_is_stamp_to_stamp_not_against_a_clock():
|
|
28
|
+
"""A sim on its own time and a robot on wall time are treated alike."""
|
|
29
|
+
fresh = TfFreshness()
|
|
30
|
+
assert fresh.new(stamp(0, 1)) is True
|
|
31
|
+
assert fresh.new(stamp(1792950000, 0)) is True
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_a_goal_that_arrived_owes_no_refusal():
|
|
35
|
+
assert goal_outcome(True, GOAL_SUCCEEDED, 1, 2) is None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_every_other_ending_is_a_refusal_naming_the_goal():
|
|
39
|
+
"""Finding 11: rejected, aborted and cancelled goals reach the requester."""
|
|
40
|
+
for accepted, status, word in ((False, None, "rejected"),
|
|
41
|
+
(True, GOAL_ABORTED, "abandoned"),
|
|
42
|
+
(True, GOAL_CANCELED, "cancelled"),
|
|
43
|
+
(True, 2, "status 2")):
|
|
44
|
+
why = goal_outcome(accepted, status, 10.0, -12.0)
|
|
45
|
+
assert why and "(10.00, -12.00)" in why and word in why, why
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/core/GnssService/__init__.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/core/GnssService/_core.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/events/enums/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/mapping/enums/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/semantics/__init__.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/semantics/_semantics.py
RENAMED
|
File without changes
|
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/common/__init__.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/common/_common.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/lidar/__init__.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/lidar/_lidar.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/rad/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/radio/__init__.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/radio/_radio.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/rf_beam/__init__.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/rf_beam/_rf_beam.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/vision/__init__.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/sensing/vision/_vision.py
RENAMED
|
File without changes
|
{spatialdds_ros-0.4.0 → spatialdds_ros-0.4.1}/spatialdds_idl18/spatial/slam_frontend/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|