Skip to content

Commit 4164172

Browse files
authored
Merge pull request #13 from NVIDIA-ISAAC-ROS/release-dp-1.1
Isaac ROS 0.11.0 (DP1.1)
2 parents 9226576 + 9dddb27 commit 4164172

5 files changed

Lines changed: 164 additions & 111 deletions

File tree

README.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,17 @@ This package is powered by [NVIDIA Isaac Transport for ROS (NITROS)](https://dev
3838

3939

4040
## Latest Update
41-
Update 2022-06-30: Support NITROS acceleration
41+
Update 2022-08-31: Update to be compatible with JetPack 5.0.2
4242

4343
## Supported Platforms
4444
This package is designed and tested to be compatible with ROS2 Humble running on [Jetson](https://developer.nvidia.com/embedded-computing) with off-the-shelf cameras from NVIDIA partners (see the [Reference Cameras](#reference-cameras) section for more details).
4545
> **Note**: x86_64 system is not supported.
4646
47+
> **Note**: Versions of ROS2 earlier than Humble are **not** supported. This package depends on specific ROS2 implementation features that were only introduced beginning with the Humble release.
4748
48-
| Platform | Hardware | Software | Notes |
49-
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50-
| Jetson | [Jetson Orin](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-orin/)<br/>[Jetson Xavier](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-agx-xavier/) | [JetPack 5.0.1 DP](https://developer.nvidia.com/embedded/jetpack) | The [CSI](https://en.wikipedia.org/wiki/Camera_Serial_Interface) camera device needs to be connected and presented as a video device (e.g. `/dev/video0`).<br/><br/>For best performance, ensure that [power settings](https://docs.nvidia.com/jetson/archives/r34.1/DeveloperGuide/text/SD/PlatformPowerAndPerformance.html) are configured appropriately. |
49+
| Platform | Hardware | Software | Notes |
50+
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
51+
| Jetson | [Jetson Orin](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-orin/)<br/>[Jetson Xavier](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-agx-xavier/) | [JetPack 5.0.2](https://developer.nvidia.com/embedded/jetpack) | The [CSI](https://en.wikipedia.org/wiki/Camera_Serial_Interface) camera device needs to be connected and presented as a video device (e.g. `/dev/video0`).<br/><br/>For best performance, ensure that [power settings](https://docs.nvidia.com/jetson/archives/r34.1/DeveloperGuide/text/SD/PlatformPowerAndPerformance.html) are configured appropriately. |
5152

5253

5354
### Docker
@@ -183,8 +184,9 @@ Exit the Docker container and restart the `nvargus` daemon by running `sudo serv
183184

184185
## Updates
185186

186-
| Date | Changes |
187-
| ---------- | --------------------------- |
188-
| 2022-06-30 | Support NITROS acceleration |
189-
| 2022-03-18 | Support CameraInfo from URL |
190-
| 2021-10-20 | Initial release |
187+
| Date | Changes |
188+
| ---------- | ------------------------------------------ |
189+
| 2022-08-31 | Update to be compatible with JetPack 5.0.2 |
190+
| 2022-06-30 | Support NITROS acceleration |
191+
| 2022-03-18 | Support CameraInfo from URL |
192+
| 2021-10-20 | Initial release |

isaac_ros_argus_camera/package.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
1313
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
1414
<package format="3">
1515
<name>isaac_ros_argus_camera</name>
16-
<version>0.10.0</version>
16+
<version>0.11.0</version>
1717
<description>Support for Argus Stereo Camera</description>
1818

1919
<maintainer email="glo@nvidia.com">Greg Lo</maintainer>
@@ -27,6 +27,8 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
2727
<depend>camera_info_manager</depend>
2828
<depend>geometry_msgs</depend>
2929
<depend>isaac_ros_nitros</depend>
30+
<depend>isaac_ros_nitros_camera_info_type</depend>
31+
<depend>isaac_ros_nitros_image_type</depend>
3032
<depend>rclcpp</depend>
3133
<depend>rclcpp_components</depend>
3234
<depend>tf2_ros</depend>

isaac_ros_argus_camera/src/argus_camera_node.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "gxf/multimedia/camera.hpp"
2020
#include "gxf/std/timestamp.hpp"
2121
#include "isaac_ros_argus_camera/argus_camera_node.hpp"
22+
#include "isaac_ros_nitros_camera_info_type/nitros_camera_info.hpp"
23+
#include "isaac_ros_nitros_image_type/nitros_image.hpp"
2224

2325
namespace nvidia
2426
{
@@ -70,7 +72,11 @@ ArgusCameraNode::ArgusCameraNode(
7072
EXTENSIONS,
7173
PACKAGE_NAME),
7274
camera_link_frame_name_("camera"),
73-
tf_broadcaster_(std::make_unique<tf2_ros::TransformBroadcaster>(*this)) {}
75+
tf_broadcaster_(std::make_unique<tf2_ros::TransformBroadcaster>(*this))
76+
{
77+
registerSupportedType<nvidia::isaac_ros::nitros::NitrosCameraInfo>();
78+
registerSupportedType<nvidia::isaac_ros::nitros::NitrosImage>();
79+
}
7480

7581
void ArgusCameraNode::ArgusImageCallback(
7682
const gxf_context_t context, nitros::NitrosTypeBase & msg, const std::string frame_name)

isaac_ros_argus_camera/test/isaac_ros_argus_camera_mono_test.py

Lines changed: 68 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,46 +8,65 @@
88

99
import os
1010
import pathlib
11+
import shlex
12+
import subprocess
1113
import time
1214

1315
import cv2
1416
from cv_bridge import CvBridge
1517
from isaac_ros_test import IsaacROSBaseTest
1618
from launch_ros.actions import ComposableNodeContainer
1719
from launch_ros.descriptions import ComposableNode
20+
import launch_testing
1821
import pytest
1922
import rclpy
2023

2124
from sensor_msgs.msg import CameraInfo, Image
2225

26+
SKIP_TEST = True
27+
2328

2429
@pytest.mark.rostest
2530
def generate_test_description():
26-
argus_mono_node = ComposableNode(
27-
name='argus_mono',
28-
package='isaac_ros_argus_camera',
29-
plugin='nvidia::isaac_ros::argus::ArgusMonoNode',
30-
namespace=IsaacArgusMonoNodeTest.generate_namespace(),
31-
)
32-
33-
return IsaacArgusMonoNodeTest.generate_test_description([
34-
ComposableNodeContainer(
35-
name='argus_mono_container',
36-
package='rclcpp_components',
37-
executable='component_container_mt',
38-
composable_node_descriptions=[argus_mono_node],
31+
device_id = 0
32+
command = f'"if [ -c /dev/video{device_id} ]; then echo Device Found; \
33+
else echo Device Not Found; fi"'
34+
result = subprocess.run(shlex.split(command), shell=True, capture_output=True, text=True)
35+
36+
if(result.stdout.strip() == 'Device Found'):
37+
IsaacArgusMonoNodeTest.skip_test = False
38+
39+
argus_mono_node = ComposableNode(
40+
name='argus_mono',
41+
package='isaac_ros_argus_camera',
42+
plugin='nvidia::isaac_ros::argus::ArgusMonoNode',
3943
namespace=IsaacArgusMonoNodeTest.generate_namespace(),
40-
output='screen',
41-
arguments=['--ros-args', '--log-level', 'info',
42-
'--log-level', 'isaac_ros_test.argus_mono:=debug',
43-
'--log-level', 'NitrosImage:=debug',
44-
'--log-level', 'NitrosCameraInfo:=debug'],
44+
parameters=[{'camera_id': device_id}]
4545
)
46-
])
46+
47+
return IsaacArgusMonoNodeTest.generate_test_description([
48+
ComposableNodeContainer(
49+
name='argus_mono_container',
50+
package='rclcpp_components',
51+
executable='component_container_mt',
52+
composable_node_descriptions=[argus_mono_node],
53+
namespace=IsaacArgusMonoNodeTest.generate_namespace(),
54+
output='screen',
55+
arguments=['--ros-args', '--log-level', 'info',
56+
'--log-level', 'isaac_ros_test.argus_mono:=debug',
57+
'--log-level', 'NitrosImage:=debug',
58+
'--log-level', 'NitrosCameraInfo:=debug'],
59+
)
60+
])
61+
else:
62+
IsaacArgusMonoNodeTest.skip_test = True
63+
return IsaacArgusMonoNodeTest.generate_test_description(
64+
[launch_testing.actions.ReadyToTest()])
4765

4866

4967
class IsaacArgusMonoNodeTest(IsaacROSBaseTest):
5068
filepath = pathlib.Path(os.path.dirname(__file__))
69+
skip_test = False
5170

5271
def test_image_capture(self):
5372
"""
@@ -56,30 +75,33 @@ def test_image_capture(self):
5675
Test that the functionality to read the image message from argus mono camera and save
5776
it to the disk.
5877
"""
59-
TIMEOUT = 10
60-
received_messages = {}
61-
62-
self.generate_namespace_lookup(['left/image_raw', 'left/camerainfo'])
63-
64-
subs = self.create_logging_subscribers(
65-
[('left/image_raw', Image), ('left/camerainfo', CameraInfo)], received_messages,
66-
accept_multiple_messages=True)
67-
try:
68-
end_time = time.time() + TIMEOUT
69-
done = False
70-
71-
while time.time() < end_time:
72-
73-
rclpy.spin_once(self.node, timeout_sec=(0.1))
74-
if len(received_messages['left/image_raw']) > 0 and \
75-
len(received_messages['left/camerainfo']) > 0:
76-
done = True
77-
break
78-
self.assertTrue(done, 'Appropriate output not received')
79-
left_image = received_messages['left/image_raw']
80-
81-
left_cv_image = CvBridge().imgmsg_to_cv2(left_image[0], desired_encoding='bgr8')
82-
cv2.imwrite('left_image.png', left_cv_image)
83-
84-
finally:
85-
self.node.destroy_subscription(subs)
78+
if self.skip_test:
79+
self.skipTest('No camera detected! Skipping test.')
80+
else:
81+
TIMEOUT = 10
82+
received_messages = {}
83+
84+
self.generate_namespace_lookup(['left/image_raw', 'left/camerainfo'])
85+
86+
subs = self.create_logging_subscribers(
87+
[('left/image_raw', Image), ('left/camerainfo', CameraInfo)], received_messages,
88+
accept_multiple_messages=True)
89+
try:
90+
end_time = time.time() + TIMEOUT
91+
done = False
92+
93+
while time.time() < end_time:
94+
95+
rclpy.spin_once(self.node, timeout_sec=(0.1))
96+
if len(received_messages['left/image_raw']) > 0 and \
97+
len(received_messages['left/camerainfo']) > 0:
98+
done = True
99+
break
100+
self.assertTrue(done, 'Appropriate output not received')
101+
left_image = received_messages['left/image_raw']
102+
103+
left_cv_image = CvBridge().imgmsg_to_cv2(left_image[0], desired_encoding='bgr8')
104+
cv2.imwrite('left_image.png', left_cv_image)
105+
106+
finally:
107+
self.node.destroy_subscription(subs)

isaac_ros_argus_camera/test/isaac_ros_argus_camera_stereo_test.py

Lines changed: 75 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88

99
import os
1010
import pathlib
11+
import shlex
12+
import subprocess
1113
import time
1214

1315
import cv2
1416
from cv_bridge import CvBridge
1517
from isaac_ros_test import IsaacROSBaseTest
1618
from launch_ros.actions import ComposableNodeContainer
1719
from launch_ros.descriptions import ComposableNode
20+
import launch_testing
1821
import pytest
1922
import rclpy
2023

@@ -23,32 +26,46 @@
2326

2427
@pytest.mark.rostest
2528
def generate_test_description():
26-
argus_stereo_node = ComposableNode(
27-
name='argus_stereo',
28-
package='isaac_ros_argus_camera',
29-
plugin='nvidia::isaac_ros::argus::ArgusStereoNode',
30-
namespace=IsaacArgusStereoNodeTest.generate_namespace(),
31-
)
32-
33-
return IsaacArgusStereoNodeTest.generate_test_description([
34-
ComposableNodeContainer(
35-
name='argus_stereo_container',
36-
package='rclcpp_components',
37-
executable='component_container_mt',
38-
composable_node_descriptions=[argus_stereo_node],
29+
device_id = 0
30+
command = f'"if [ -c /dev/video{device_id} ]; then echo Device Found; \
31+
else echo Device Not Found; fi"'
32+
result = subprocess.run(shlex.split(command), shell=True, capture_output=True, text=True)
33+
34+
if(result.stdout.strip() == 'Device Found'):
35+
IsaacArgusStereoNodeTest.skip_test = False
36+
37+
argus_stereo_node = ComposableNode(
38+
name='argus_stereo',
39+
package='isaac_ros_argus_camera',
40+
plugin='nvidia::isaac_ros::argus::ArgusStereoNode',
3941
namespace=IsaacArgusStereoNodeTest.generate_namespace(),
40-
output='screen',
41-
arguments=['--ros-args', '--log-level', 'info',
42-
'--log-level', 'isaac_ros_test.argus_stereo:=debug',
43-
'--log-level', 'NitrosImage:=debug',
44-
'--log-level', 'NitrosCameraInfo:=debug'
45-
],
42+
parameters=[{'camera_id': device_id}]
4643
)
47-
])
44+
45+
return IsaacArgusStereoNodeTest.generate_test_description([
46+
ComposableNodeContainer(
47+
name='argus_stereo_container',
48+
package='rclcpp_components',
49+
executable='component_container_mt',
50+
composable_node_descriptions=[argus_stereo_node],
51+
namespace=IsaacArgusStereoNodeTest.generate_namespace(),
52+
output='screen',
53+
arguments=['--ros-args', '--log-level', 'info',
54+
'--log-level', 'isaac_ros_test.argus_stereo:=debug',
55+
'--log-level', 'NitrosImage:=debug',
56+
'--log-level', 'NitrosCameraInfo:=debug'
57+
],
58+
)
59+
])
60+
else:
61+
IsaacArgusStereoNodeTest.skip_test = True
62+
return IsaacArgusStereoNodeTest.generate_test_description(
63+
[launch_testing.actions.ReadyToTest()])
4864

4965

5066
class IsaacArgusStereoNodeTest(IsaacROSBaseTest):
5167
filepath = pathlib.Path(os.path.dirname(__file__))
68+
skip_test = False
5269

5370
def test_image_capture(self):
5471
"""
@@ -57,37 +74,41 @@ def test_image_capture(self):
5774
Test that the functionality to read the image message from argus stereo camera and save
5875
it to the disk.
5976
"""
60-
TIMEOUT = 10
61-
received_messages = {}
62-
63-
self.generate_namespace_lookup(
64-
['left/image_raw', 'right/image_raw', 'left/camerainfo', 'right/camerainfo'])
65-
66-
subs = self.create_logging_subscribers(
67-
[('left/image_raw', Image), ('right/image_raw', Image),
68-
('left/camerainfo', CameraInfo), ('right/camerainfo', CameraInfo)], received_messages,
69-
accept_multiple_messages=True)
70-
try:
71-
end_time = time.time() + TIMEOUT
72-
done = False
73-
74-
while time.time() < end_time:
75-
76-
rclpy.spin_once(self.node, timeout_sec=(0.1))
77-
if len(received_messages['left/image_raw']) > 0 and \
78-
len(received_messages['right/image_raw']) > 0 and \
79-
len(received_messages['left/camerainfo']) > 0 and \
80-
len(received_messages['right/camerainfo']) > 0:
81-
done = True
82-
break
83-
self.assertTrue(done, 'Appropriate output not received')
84-
left_image = received_messages['left/image_raw']
85-
right_image = received_messages['right/image_raw']
86-
87-
left_cv_image = CvBridge().imgmsg_to_cv2(left_image[0], desired_encoding='bgr8')
88-
right_cv_image = CvBridge().imgmsg_to_cv2(right_image[0], desired_encoding='bgr8')
89-
cv2.imwrite('left_image.png', left_cv_image)
90-
cv2.imwrite('right_image.png', right_cv_image)
91-
92-
finally:
93-
self.node.destroy_subscription(subs)
77+
if self.skip_test:
78+
self.skipTest('No camera detected! Skipping test.')
79+
else:
80+
TIMEOUT = 10
81+
received_messages = {}
82+
83+
self.generate_namespace_lookup(
84+
['left/image_raw', 'right/image_raw', 'left/camerainfo', 'right/camerainfo'])
85+
86+
subs = self.create_logging_subscribers(
87+
[('left/image_raw', Image), ('right/image_raw', Image),
88+
('left/camerainfo', CameraInfo), ('right/camerainfo', CameraInfo)],
89+
received_messages,
90+
accept_multiple_messages=True)
91+
try:
92+
end_time = time.time() + TIMEOUT
93+
done = False
94+
95+
while time.time() < end_time:
96+
97+
rclpy.spin_once(self.node, timeout_sec=(0.1))
98+
if len(received_messages['left/image_raw']) > 0 and \
99+
len(received_messages['right/image_raw']) > 0 and \
100+
len(received_messages['left/camerainfo']) > 0 and \
101+
len(received_messages['right/camerainfo']) > 0:
102+
done = True
103+
break
104+
self.assertTrue(done, 'Appropriate output not received')
105+
left_image = received_messages['left/image_raw']
106+
right_image = received_messages['right/image_raw']
107+
108+
left_cv_image = CvBridge().imgmsg_to_cv2(left_image[0], desired_encoding='bgr8')
109+
right_cv_image = CvBridge().imgmsg_to_cv2(right_image[0], desired_encoding='bgr8')
110+
cv2.imwrite('left_image.png', left_cv_image)
111+
cv2.imwrite('right_image.png', right_cv_image)
112+
113+
finally:
114+
self.node.destroy_subscription(subs)

0 commit comments

Comments
 (0)