Skip to content

Commit d7d3aae

Browse files
authored
Merge pull request #21 from hmakelin/hmakelin-autopilot-refactor
Use ROS remapping for camera info and image topics
2 parents 3583216 + b89c456 commit d7d3aae

11 files changed

+51
-64
lines changed

config/test_typhoon_h480__ksql_airport.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ mock_gps_node:
1212
request_timeout: 10
1313
misc:
1414
autopilot: 'gisnav.autopilots.px4_micrortps.PX4microRTPS'
15-
image_topic: '/camera/image_raw'
16-
camera_info_topic: '/camera/camera_info'
1715
mock_gps_selection: 1
1816
attitude_deviation_threshold: 10
1917
#max_pitch: 30

config/typhoon_h480__ksql_airport.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ mock_gps_node:
1111
request_timeout: 10
1212
misc:
1313
autopilot: 'gisnav.autopilots.px4_micrortps.PX4microRTPS'
14-
image_topic: '/camera/image_raw'
15-
camera_info_topic: '/camera/camera_info'
1614
attitude_deviation_threshold: 10 # degrees
1715
max_pitch: 30 # 30 # Used by _should_match
1816
min_match_altitude: 50

config/typhoon_h480__ksql_airport_ardupilot.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ mock_gps_node:
1111
request_timeout: 10
1212
misc:
1313
autopilot: 'gisnav.autopilots.ardupilot_mavros.ArduPilotMAVROS'
14-
image_topic: '/camera/image_raw'
15-
camera_info_topic: '/camera/camera_info'
1614
attitude_deviation_threshold: 10 # degrees
1715
max_pitch: 50 # 30 # Make bigger with static_camera: True # Used by _should_match
1816
min_match_altitude: 50

docs/conf.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
# -- Project information -----------------------------------------------------
3030

3131
project = package_data.package_name
32-
copyright = f'2021, {package_data.author}'
32+
copyright = f'2022, {package_data.author}'
3333
author = package_data.author
3434

3535
# -- General configuration ---------------------------------------------------
@@ -69,7 +69,16 @@
6969
"image_light": "img/logo.png",
7070
"image_dark": "img/logo_inverted.png",
7171
},
72-
"collapse_navigation": True
72+
"collapse_navigation": True,
73+
"icon_links": [
74+
{
75+
"name": "GitHub",
76+
"url": "https://github.com/hmakelin/gisnav",
77+
"icon": "fab fa-github",
78+
"type": "fontawesome",
79+
}
80+
],
81+
"icon_links_label": "Quick Links",
7382
}
7483

7584
# Make version number accessible in .rst files

docs/pages/api_documentation.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ will only be interested in the :class:`.BaseNode` and :class:`.PoseEstimator` cl
88

99
.. _GISNav ROS 2 package: https://gitlab.com/px4-ros2-map-nav/python_px4_ros2_map_nav
1010

11+
.. note::
12+
GISNav is under active development and stability of the API is not guaranteed. Use a specific commit or version tag
13+
to mitigate the impact of breaking changes.
14+
1115
Indices and Tables
1216
=================================================
1317
Use the search in the sidebar or these indices to find what you are looking for.

docs/pages/developer_guide.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Developer Guide
66
GISNav is untested and has only been demonstrated in a software-in-the-loop (SITL) simulation environment.
77
Do not use this software for real drone flights.
88

9+
.. note::
10+
GISNav is under active development and stability of the API is not guaranteed. Use a specific commit or version tag
11+
to mitigate the impact of breaking changes.
12+
913
This section provides instruction on how you can integrate GISNav with your project as well as configure and extend
1014
it to match your use case.
1115

@@ -314,6 +318,17 @@ the PX4 User Guide.
314318
.. seealso::
315319
`PX4-ROS 2 bridge <https://docs.px4.io/master/en/ros/ros2_comm.html>`_ for more information on the PX4-ROS 2 bridge
316320

321+
Remap ROS 2 Topics
322+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
323+
By default, the :class:`.CameraInfo` and :class:`px4_msgs.Image` messages are expected at ``camera/camera_info`` and
324+
``camera/image_raw`` topics, respectively. The topics can be remapped:
325+
326+
.. code-block:: bash
327+
328+
ros2 run gisnav mock_gps_node --mavros --ros-args --log-level info \
329+
--params-file src/gisnav/config/typhoon_h480__ksql_airport_ardupilot.yaml \
330+
-r camera/camera_info:=camera_info -r camera/image_raw:=image_raw
331+
317332
Testing
318333
====================================================
319334
Unit & ROS 2 integration tests

docs/pages/get_started.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
**************************************************
22
Get Started
33
**************************************************
4+
..
5+
Skip GitHub video link (:start-after: .mp4)
6+
47
.. include:: ../../README.md
58
:parser: myst_parser.sphinx_
6-
7-
9+
:start-after: .mp4

gisnav/autopilots/ardupilot_mavros.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,13 @@ class ArduPilotMAVROS(Autopilot):
4141
}
4242
"""ROS topics to subscribe"""
4343

44-
def __init__(self, node: rclpy.node.Node, camera_info_topic: str, image_topic: str,
45-
image_callback: Callable[[Image], None]) -> None:
44+
def __init__(self, node: rclpy.node.Node, image_callback: Callable[[Image], None]) -> None:
4645
"""Initialize class
4746
4847
:param node: Parent node that handles the ROS subscriptions
49-
:param camera_info_topic: ROS camera info topic to subscribe to
50-
:param image_topic: ROS camera image (raw) topic to subscribe to
5148
:param image_callback: Callback function for camera image
5249
"""
53-
super().__init__(node, camera_info_topic, image_topic, image_callback)
50+
super().__init__(node, image_callback)
5451

5552
# TODO: copy to shared folder and use relative path
5653
self._egm96 = GeoidPGM('/usr/share/GeographicLib/geoids/egm96-5.pgm', kind=-3)

gisnav/autopilots/autopilot.py

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,28 @@ class Autopilot(ABC):
2424
TELEMETRY_EXPIRATION_LIMIT = 1e6
2525
"""Expiration period in usec for vehicle state (if telemetry data is older than this it should not be used)"""
2626

27-
def __init__(self, node: rclpy.node.Node, camera_info_topic: str, image_topic: str,
28-
on_image_callback: Callable[[ImageData], None]) -> None:
27+
CAMERA_INFO_TOPIC = 'camera/camera_info'
28+
"""ROS camera info (:class:`.sensor_msgs.msg.CameraInfo`) topic to subscribe to"""
29+
30+
IMAGE_RAW_TOPIC = 'camera/image_raw'
31+
"""ROS image raw (:class:`.sensor_msgs.msg.Image`) topic to subscribe to"""
32+
33+
def __init__(self, node: rclpy.node.Node, on_image_callback: Callable[[ImageData], None]) -> None:
2934
"""Initializes autopilot adapter
3035
3136
:param node: Parent node that handles the ROS subscriptions
32-
:param camera_info_topic: ROS camera info topic to subscribe to
33-
:param image_topic: ROS topic for :class:`.sensor_msgs.msg.Image`
3437
:param on_image_callback: Callback function for camera image
3538
"""
3639
self._node = node
3740
self._topics = {}
3841

3942
# Subscribe to camera data topic
4043
self.camera_data = None
41-
self._camera_info_topic = camera_info_topic
42-
self._subscribe(self._camera_info_topic, CameraInfo, self._camera_info_callback,
44+
self._subscribe(self.CAMERA_INFO_TOPIC, CameraInfo, self._camera_info_callback,
4345
rclpy.qos.QoSPresetProfiles.SENSOR_DATA.value)
4446

4547
# Image topic callback gets access to base node through provided on_image_callback
46-
self._image_topic = image_topic
47-
self._subscribe(self._image_topic, Image, on_image_callback, rclpy.qos.QoSPresetProfiles.SENSOR_DATA.value)
48+
self._subscribe(self.IMAGE_RAW_TOPIC, Image, on_image_callback, rclpy.qos.QoSPresetProfiles.SENSOR_DATA.value)
4849

4950
@property
5051
def _node(self) -> rclpy.node.Node:
@@ -76,26 +77,6 @@ def camera_data(self, value: Optional[CameraData]) -> None:
7677
assert_type(value, get_args(Optional[CameraData]))
7778
self.__camera_data = value
7879

79-
@property
80-
def _camera_info_topic(self) -> str:
81-
"""CameraInfo ROS topic name."""
82-
return self.__camera_info_topic
83-
84-
@_camera_info_topic.setter
85-
def _camera_info_topic(self, value: str) -> None:
86-
assert_type(value, str)
87-
self.__camera_info_topic = value
88-
89-
@property
90-
def _image_topic(self) -> str:
91-
"""Image ROS topic name."""
92-
return self.__image_topic
93-
94-
@_image_topic.setter
95-
def _image_topic(self, value: str) -> None:
96-
assert_type(value, str)
97-
self.__image_topic = value
98-
9980
def _subscribe(self, topic_name: str, class_: type, callback: Callable, qos: rclpy.qos.QoSProfile) -> None:
10081
"""Subscribes to ROS topic
10182
@@ -137,10 +118,10 @@ def _camera_info_callback(self, msg: CameraInfo) -> None:
137118
return None
138119
else:
139120
self.camera_data = CameraData(k=msg.k.reshape((3, 3)), dim=Dim(msg.height, msg.width))
140-
camera_info_topic = self._topics.get(self._camera_info_topic, {}).get(self._TOPICS_SUBSCRIBER_KEY, None)
141-
if camera_info_topic is not None:
121+
camera_info_sub = self._topics.get(self.CAMERA_INFO_TOPIC, {}).get(self._TOPICS_SUBSCRIBER_KEY, None)
122+
if camera_info_sub is not None:
142123
# Assume camera info is static, destroy subscription
143-
camera_info_topic.destroy()
124+
camera_info_sub.destroy()
144125

145126
@property
146127
@abstractmethod

gisnav/autopilots/px4_micrortps.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,13 @@ class PX4microRTPS(Autopilot):
4040
}
4141
"""ROS topics to subscribe"""
4242

43-
def __init__(self, node: rclpy.node.Node, camera_info_topic: str, image_topic: str,
44-
image_callback: Callable[[Image], None]) -> None:
43+
def __init__(self, node: rclpy.node.Node, image_callback: Callable[[Image], None]) -> None:
4544
"""Initialize class
4645
4746
:param node: Parent node that handles the ROS subscriptions
48-
:param camera_info_topic: ROS camera info topic to subscribe to
49-
:param image_topic: ROS camera image (raw) topic to subscribe to
5047
:param image_callback: Callback function for camera image
5148
"""
52-
super().__init__(node, camera_info_topic, image_topic, image_callback)
49+
super().__init__(node, image_callback)
5350

5451
self._setup_subscribers()
5552

0 commit comments

Comments
 (0)