diff --git a/src/surface/ps5_controller/README.md b/src/surface/ps5_controller/README.md index 6ad63bc1..689d96bd 100644 --- a/src/surface/ps5_controller/README.md +++ b/src/surface/ps5_controller/README.md @@ -20,7 +20,7 @@ ros2 launch ps5-controller controller_launch.py * **`/joy`** ([sensor_msgs/Joy]) - Outdated ROV movement instructions + Information about the controller input. ## Subscribed Topics diff --git a/src/surface/ps5_controller/package.xml b/src/surface/ps5_controller/package.xml index a638b592..838d8120 100644 --- a/src/surface/ps5_controller/package.xml +++ b/src/surface/ps5_controller/package.xml @@ -3,7 +3,7 @@ ps5_controller 1.0.0 - Biolerplate for calling standard joystick launch file. + Boilerplate for calling standard joystick launch file. Michael Carlstrom Apache License 2.0 diff --git a/src/surface/ps5_controller/setup.py b/src/surface/ps5_controller/setup.py index d844a8c7..3bdaccce 100644 --- a/src/surface/ps5_controller/setup.py +++ b/src/surface/ps5_controller/setup.py @@ -22,7 +22,7 @@ zip_safe=True, maintainer='Michael Carlstrom', maintainer_email='rmc170@case.edu', - description='Biolerplate for calling standard joystick launch file.', + description='Boilerplate for calling standard joystick launch file.', license='Apache License 2.0', tests_require=['pytest'], entry_points={}, diff --git a/src/surface/ros2_video_streamer b/src/surface/ros2_video_streamer index aed5f989..e1a8d332 160000 --- a/src/surface/ros2_video_streamer +++ b/src/surface/ros2_video_streamer @@ -1 +1 @@ -Subproject commit aed5f98999c1b73894d8f8ec21976f2c8077e1b0 +Subproject commit e1a8d332467ed3109117a19db74c2385b59f116a diff --git a/src/surface/rov_flir/README.md b/src/surface/rov_flir/README.md new file mode 100644 index 00000000..6a9bba29 --- /dev/null +++ b/src/surface/rov_flir/README.md @@ -0,0 +1,74 @@ +# rov_flir + +## Overview + +This is a boilerplate package which launches the camera_driver_node from the flir_launch package. + +## Setup + +Run the setup file from spinnaker_camera_driver + +```bash +ros2 run spinnaker_camera_driver linux_setup_flir +``` + +## Debugging + +You can install the Spinnaker SDK & Spinview GUI for debugging [here](https://www.flir.com/products/spinnaker-sdk/). + +If you get errors about cameras on the wrong subnet, install this and open Spinview. Write click the entries for each camera and select "Auto Force IPs". + +## Usage + +Run the main node with + +```bash +ros2 launch rov_flir flir_launch.py +``` + +## Settings + +In the config folder are the nodes from the spinnaker api, these are different from ROS nodes. They are basically settings of the cameras. Each setting in the config file has a `name` which is the name of the ROS parameter, a `type` which is the data type of the field, and finally each setting has a `node` which is the name of the setting in spinnaker. + +## Launch files + +* **flir_launch.py:** Launches the camera_driver_node for the two flir cameras. + +## Published Topics + +* **`/front_camera/image_raw`** ([sensor_msgs/msg/Image]) + + Image feed for front camera. + +* **`/front_camera/meta`** ([flir_camera_msgs/msg/ImageMetaData]) + + Front camera image meta data. + +* **`/front_camera/camera_info`** ([sensor_msgs/msg/CameraInfo]) + + Front camera info. + +* **`/bottom_camera/image_raw`** ([sensor_msgs/msg/Image]) + + Image feed for bottom camera. + +* **`/bottom_camera/meta`** ([flir_camera_msgs/msg/ImageMetaData]) + + Bottom camera image meta data. + +* **`/bottom_camera/camera_info`** ([sensor_msgs/msg/CameraInfo]) + + Bottom camera info. + +## Subscribed Topics + +* **`/front_camera/control`** ([flir_camera_msgs/msg/CameraControl]) + Controls exposure and gain. + +* **`/bottom_camera/control`** ([flir_camera_msgs/msg/CameraControl]) + Controls exposure and gain. + +[sensor_msgs/msg/Image]: https://docs.ros2.org/latest/api/sensor_msgs/msg/Image.html +[flir_camera_msgs/msg/ImageMetaData]: https://github.com/ros-drivers/flir_camera_driver/blob/humble-devel/flir_camera_msgs/msg/ImageMetaData.msg +[sensor_msgs/msg/CameraInfo]: https://docs.ros2.org/latest/api/sensor_msgs/msg/CameraInfo.html +[flir_camera_msgs/msg/CameraControl]: https://github.com/ros-drivers/flir_camera_driver/blob/humble-devel/flir_camera_msgs/msg/CameraControl.msg \ No newline at end of file diff --git a/src/surface/rov_flir/config/blackfly_s.yaml b/src/surface/rov_flir/config/blackfly_s.yaml new file mode 100644 index 00000000..608bc806 --- /dev/null +++ b/src/surface/rov_flir/config/blackfly_s.yaml @@ -0,0 +1,154 @@ +# +# config file for blackfly S cameras (USB3 and GigE) +# +# This file maps the ros parameters to the corresponding Spinnaker "nodes" in the camera. +# For more details on how to modify this file, see the README on camera configuration files. + + +parameters: + # + # -------- image format control + # + - name: pixel_format + type: enum + # Check available values with SpinView. Not all are supported by ROS! + # Some formats are e.g. "Mono8", "BayerRG8", "BGR8", "BayerRG16" + # default is "BayerRG8" + node: ImageFormatControl/PixelFormat + - name: image_width + type: int + node: ImageFormatControl/Width + - name: image_height + type: int + node: ImageFormatControl/Height + - name: offset_x # offset must come after image width reduction! + type: int + node: ImageFormatControl/OffsetX + - name: offset_y + type: int + node: ImageFormatControl/OffsetY + # Added by ROV + - name: binning_x + type: int + node: ImageFormatControl/BinningHorizontal + - name: binning_y + type: int + node: ImageFormatControl/BinningVertical + # + # -------- analog control + # + - name: gain_auto + type: enum + # valid values are "Continuous", "Off" + node: AnalogControl/GainAuto + - name: gain + type: float + node: AnalogControl/Gain + # + # -------- device link throughput limiting + # + - name: device_link_throughput_limit + type: int + node: DeviceControl/DeviceLinkThroughputLimit + # + # -------- transport layer control (GigE) + # + - name: gev_scps_packet_size + type: int + # default is 1400. Set to 9000 to enable jumbo frames, ensure NIC MTU set >= 9000 + node: TransportLayerControl/GigEVision/GevSCPSPacketSize + # + # -------- digital IO control + # + - name: line0_selector # black wire: opto-isolated input + type: enum + node: DigitalIOControl/LineSelector + - name: line1_selector # white wire: opto-isolated output + type: enum + node: DigitalIOControl/LineSelector + - name: line1_linemode # valid values: "Input", "Output" + type: enum + node: DigitalIOControl/LineMode + - name: line2_selector # red wire: non-isolated input/output + type: enum + node: DigitalIOControl/LineSelector + - name: line2_v33enable # red wire: 3.3V power + type: bool + node: DigitalIOControl/V3_3Enable + - name: line3_selector # green wire: aux voltage input and non-isolated input + type: enum + node: DigitalIOControl/LineSelector + - name: line3_linemode # valid values: "Input", "Output" + type: enum + node: DigitalIOControl/LineMode + # + # -------- acquisition control + # + - name: exposure_auto + type: enum + # valid values are "Off", "Continuous" + node: AcquisitionControl/ExposureAuto + - name: exposure_time + type: float + node: AcquisitionControl/ExposureTime + - name: frame_rate_enable + type: bool + node: AcquisitionControl/AcquisitionFrameRateEnable + - name: frame_rate + type: float + node: AcquisitionControl/AcquisitionFrameRate + - name: trigger_selector + type: enum + # valid values are e.g. "FrameStart", "AcquisitionStart", "FrameBurstStart" + node: AcquisitionControl/TriggerSelector + - name: trigger_mode + type: enum + # valid values are "On" and "Off" + node: AcquisitionControl/TriggerMode + - name: trigger_source + type: enum + # valid values are "Line<0,1,2>", "UserOutput<0,1,2>", "Counter<0,1>", + # "LogicBlock<0,1> + node: AcquisitionControl/TriggerSource + - name: trigger_delay + # value >= 9 + type: float + node: AcquisitionControl/TriggerDelay + - name: trigger_overlap + type: enum + # valid values: "Off" and "ReadOut" + node: AcquisitionControl/TriggerOverlap + # + # --------- chunk control + # + - name: chunk_mode_active + type: bool + node: ChunkDataControl/ChunkModeActive + - name: chunk_selector_frame_id + type: enum + # valid values: "FrameID" + node: ChunkDataControl/ChunkSelector + - name: chunk_enable_frame_id + type: bool + node: ChunkDataControl/ChunkEnable + - name: chunk_selector_exposure_time + type: enum + # valid values: "ExposureTime" + node: ChunkDataControl/ChunkSelector + - name: chunk_enable_exposure_time + type: bool + node: ChunkDataControl/ChunkEnable + - name: chunk_selector_gain + type: enum + # valid values: "Gain" + node: ChunkDataControl/ChunkSelector + - name: chunk_enable_gain + type: bool + node: ChunkDataControl/ChunkEnable + - name: chunk_selector_timestamp + type: enum + # valid values: "Timestamp" + node: ChunkDataControl/ChunkSelector + - name: chunk_enable_timestamp + type: bool + node: ChunkDataControl/ChunkEnable diff --git a/src/surface/rov_flir/launch/flir_launch.py b/src/surface/rov_flir/launch/flir_launch.py new file mode 100644 index 00000000..a77a9ce1 --- /dev/null +++ b/src/surface/rov_flir/launch/flir_launch.py @@ -0,0 +1,76 @@ +import os + +from ament_index_python.packages import get_package_share_directory +from launch.launch_description import LaunchDescription +from launch_ros.actions import Node +from launch_ros.parameter_descriptions import Parameter + + +def generate_launch_description() -> LaunchDescription: + + parameter_file = os.path.join(get_package_share_directory('rov_flir'), 'config', + 'blackfly_s.yaml') + + parameters = { + 'debug': False, + 'compute_brightness': False, + 'adjust_timestamp': True, + 'dump_node_map': False, + # set parameters defined in blackfly_s.yaml + 'gain_auto': 'Continuous', + # 'pixel_format': 'BayerRG8', + 'exposure_auto': 'Continuous', + # These are useful for GigE cameras + 'device_link_throughput_limit': 125000000, + 'gev_scps_packet_size': 9000, + # ---- to reduce the sensor width and shift the crop + # 'image_width': 1280, + # 'image_height': 720, + # 'offset_x': 16, + # 'offset_y': 0, + 'binning_x': 2, + 'binning_y': 2, + 'frame_rate_auto': 'Off', + 'frame_rate': 60.0, + 'frame_rate_enable': True, + 'buffer_queue_size': 1, + 'trigger_mode': 'Off', + 'chunk_mode_active': True, + 'chunk_selector_frame_id': 'FrameID', + 'chunk_enable_frame_id': True, + 'chunk_selector_exposure_time': 'ExposureTime', + 'chunk_enable_exposure_time': True, + 'chunk_selector_gain': 'Gain', + 'chunk_enable_gain': True, + 'chunk_selector_timestamp': 'Timestamp', + 'chunk_enable_timestamp': True + } + + # launches node to run front flir camera + front_cam: Node = Node( + package='spinnaker_camera_driver', + executable='camera_driver_node', + name='front_camera', + emulate_tty=True, + output='screen', + parameters=[Parameter('serial_number', '23473577'), + Parameter('parameter_file', parameter_file), + parameters] + ) + + # launches node to run bottom flir camera + bottom_cam: Node = Node( + package='spinnaker_camera_driver', + executable='camera_driver_node', + name='bottom_camera', + emulate_tty=True, + output='screen', + parameters=[Parameter('serial_number', '23473566'), + Parameter('parameter_file', parameter_file), + parameters] + ) + + return LaunchDescription([ + front_cam, + bottom_cam + ]) diff --git a/src/surface/rov_flir/package.xml b/src/surface/rov_flir/package.xml new file mode 100644 index 00000000..be941b00 --- /dev/null +++ b/src/surface/rov_flir/package.xml @@ -0,0 +1,20 @@ + + + + rov_flir + 1.0.0 + Boilerplate for calling flir launch file. + Michael Carlstrom + Apache License 2.0 + + ament_flake8 + ament_pep257 + python3-pytest + + ros2launch + spinnaker_camera_driver + + + ament_python + + diff --git a/src/surface/rov_flir/resource/rov_flir b/src/surface/rov_flir/resource/rov_flir new file mode 100644 index 00000000..e69de29b diff --git a/src/surface/rov_flir/rov_flir/__init__.py b/src/surface/rov_flir/rov_flir/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/surface/rov_flir/setup.cfg b/src/surface/rov_flir/setup.cfg new file mode 100644 index 00000000..812ad80b --- /dev/null +++ b/src/surface/rov_flir/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/rov_flir +[install] +install_scripts=$base/lib/rov_flir diff --git a/src/surface/rov_flir/setup.py b/src/surface/rov_flir/setup.py new file mode 100644 index 00000000..6717701e --- /dev/null +++ b/src/surface/rov_flir/setup.py @@ -0,0 +1,30 @@ +import os +from glob import glob + +from setuptools import setup + +package_name = 'rov_flir' + +setup( + name=package_name, + version='1.0.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', + ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + # Include all launch files. + (os.path.join('share', package_name, 'launch'), + glob('launch/*launch.[pxy][yma]*')), + (os.path.join('share', package_name, 'config'), + glob('config/*')) + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='Michael Carlstrom', + maintainer_email='rmc170@case.edu', + description='Boilerplate for calling standard flir launch file.', + license='Apache License 2.0', + tests_require=['pytest'], + entry_points={}, +) diff --git a/src/surface/rov_flir/test/test_flake8.py b/src/surface/rov_flir/test/test_flake8.py new file mode 100644 index 00000000..eac16eef --- /dev/null +++ b/src/surface/rov_flir/test/test_flake8.py @@ -0,0 +1,25 @@ +# Copyright 2017 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_flake8.main import main_with_errors +import pytest + + +@pytest.mark.flake8 +@pytest.mark.linter +def test_flake8() -> None: + rc, errors = main_with_errors(argv=[]) + assert rc == 0, \ + 'Found %d code style errors / warnings:\n' % len(errors) + \ + '\n'.join(errors) diff --git a/src/surface/rov_flir/test/test_mypy.py b/src/surface/rov_flir/test/test_mypy.py new file mode 100644 index 00000000..79fc51ad --- /dev/null +++ b/src/surface/rov_flir/test/test_mypy.py @@ -0,0 +1,15 @@ +"""Test mypy on this module.""" +import os + +import pytest +from ament_mypy.main import main + + +@pytest.mark.mypy +@pytest.mark.linter +def test_mypy() -> None: + """Tests mypy on this module.""" + file_path = __file__.replace(f'{__name__}.py', '') + config_file = os.path.join(file_path, '..', '..', '..', '..', 'mypy.ini') + error_code = main(argv=['--config', config_file]) + assert error_code == 0, 'Found code style errors / warnings' diff --git a/src/surface/rov_flir/test/test_pep257.py b/src/surface/rov_flir/test/test_pep257.py new file mode 100644 index 00000000..b6808e1d --- /dev/null +++ b/src/surface/rov_flir/test/test_pep257.py @@ -0,0 +1,23 @@ +# Copyright 2015 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_pep257.main import main +import pytest + + +@pytest.mark.linter +@pytest.mark.pep257 +def test_pep257() -> None: + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found code style errors / warnings'