Skip to content

Commit 6159ed6

Browse files
authored
Push 4.58.3 release into ros2-master (#3540)
2 parents 775b167 + d84d094 commit 6159ed6

15 files changed

Lines changed: 98 additions & 94 deletions

File tree

.github/workflows/main.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,14 @@ jobs:
3131
strategy:
3232
fail-fast: false
3333
matrix:
34-
ros_distro: [rolling, iron, humble, jazzy, kilted]
34+
ros_distro: [rolling, humble, jazzy, kilted]
3535
include:
3636
- ros_distro: 'rolling'
3737
os: ubuntu-24.04
3838
- ros_distro: 'kilted'
3939
os: ubuntu-24.04
4040
- ros_distro: 'jazzy'
4141
os: ubuntu-24.04
42-
- ros_distro: 'iron'
43-
os: ubuntu-22.04
4442
- ros_distro: 'humble'
4543
os: ubuntu-22.04
4644

@@ -122,7 +120,7 @@ jobs:
122120
# wget $bag_filename -P "records/"
123121
# sudo apt install ros-${{ matrix.ros_distro}}-launch-pytest
124122

125-
- name: Install Packages For Humble/Iron/Rolling/Jazzy/Kilted Tests
123+
- name: Install Packages For Humble/Rolling/Jazzy/Kilted Tests
126124
shell: bash
127125
run: |
128126
apt-get install -y python3-pip python3-venv

realsense2_camera/include/constants.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#define REALSENSE_ROS_MAJOR_VERSION 4
2121
#define REALSENSE_ROS_MINOR_VERSION 58
22-
#define REALSENSE_ROS_PATCH_VERSION 2
22+
#define REALSENSE_ROS_PATCH_VERSION 3
2323

2424
#define STRINGIFY(arg) #arg
2525
#define VAR_ARG_STRING(arg) STRINGIFY(arg)

realsense2_camera/package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
33
<package format="3">
44
<name>realsense2_camera</name>
5-
<version>4.58.2</version>
5+
<version>4.58.3</version>
66
<description>RealSense camera package allowing access to RealSense D400 3D cameras</description>
77
<maintainer email="rsswsdk@realsensecloud.onmicrosoft.com">LibRealSense ROS Team</maintainer>
88
<maintainer email="nir.azkiel@realsenseai.com">Nir Azkiel</maintainer>

realsense2_camera/src/image_publisher.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,17 @@ image_transport_publisher::image_transport_publisher( rclcpp::Node & node,
4141
const std::string & topic_name,
4242
const rmw_qos_profile_t & qos )
4343
{
44+
#if defined( LYRICAL ) || defined( ROLLING )
45+
// On Rolling/Lyrical, image_transport::create_publisher deduces NodeT
46+
// from a Node reference (it then calls node.get_node_base_interface()),
47+
// and the QoS argument is rclcpp::QoS rather than rmw_qos_profile_t.
48+
rclcpp::QoS rclcpp_qos( rclcpp::QoSInitialization::from_rmw( qos ), qos );
49+
image_publisher_impl = std::make_shared< image_transport::Publisher >(
50+
image_transport::create_publisher( node, topic_name, rclcpp_qos ) );
51+
#else
4452
image_publisher_impl = std::make_shared< image_transport::Publisher >(
4553
image_transport::create_publisher( &node, topic_name, qos ) );
54+
#endif
4655
}
4756
void image_transport_publisher::publish( sensor_msgs::msg::Image::UniquePtr image_ptr )
4857
{

realsense2_camera/src/realsense_node_factory.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,12 +448,14 @@ void RealSenseNodeFactory::startDevice()
448448
if (_realSenseNode) _realSenseNode.reset();
449449
std::string device_name(_device.get_info(RS2_CAMERA_INFO_NAME));
450450
std::string pid_str(_device.get_info(RS2_CAMERA_INFO_PRODUCT_ID));
451+
std::string connection_type(_device.supports(RS2_CAMERA_INFO_CONNECTION_TYPE) ?
452+
_device.get_info(RS2_CAMERA_INFO_CONNECTION_TYPE) : "");
451453
uint16_t pid;
452454

453-
if (device_name == "Intel RealSense D555")
455+
if (connection_type == "DDS" && device_name.find("D555") != std::string::npos)
454456
{
455-
// currently the PID of DDS devices is hardcoded as "DDS"
456-
// need to be fixed in librealsense
457+
// DDS devices don't expose a real USB PID (PRODUCT_ID is hardcoded as "DDS"
458+
// in librealsense), so resolve the model by name instead.
457459
pid = RS555_PID;
458460
}
459461
else

realsense2_camera/test/live_camera/rosci.py

Lines changed: 40 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535

3636
from rspy import log, file
3737
regex = None
38-
hub_reset = False
3938
handle = None
4039
test_ran = False
4140
device_set = list()
@@ -121,72 +120,41 @@ def junit_xml_parsing(xml_file):
121120
new_xml = xml_file.split('.')[0]
122121
tree.write(f'{logdir}/{new_xml}_refined.xml')
123122

124-
def build_device_port_mapping(possible_ports):
123+
def build_device_port_mapping():
125124
"""
126-
Build a mapping of devices to YKUSH hub ports by enabling each port and querying connected devices.
125+
Map device-name -> YKUSH hub port from rspy's current enumeration.
126+
127+
rspy resolves each device's hub port from its USB location during query()
128+
(done in find_devices_run_tests), so the mapping is read straight from the
129+
enumerated devices -- no need to power-cycle ports one at a time, and no
130+
direct ykushcmd calls.
127131
"""
128132
from rspy import devices
129133
mapping = {}
130-
131-
# Turn off all ports first
132-
for port in possible_ports:
133-
subprocess.run(f'ykushcmd ykush3 -d {port}', shell=True)
134-
time.sleep(2.5)
135-
136-
for port in possible_ports:
137-
log.i(f"Checking YKUSH port {port}...")
138-
139-
subprocess.run(f'ykushcmd ykush3 -u {port}', shell=True)
140-
time.sleep(5.0)
141-
142-
devices.query(hub_reset=True)
143-
144-
for device in devices._device_by_sn.values():
145-
key = device.name.upper()
146-
if key not in mapping:
147-
mapping[key] = port
148-
log.i(f"Detected device: {device.name} ({device._sn}) on port {port}")
149-
150-
subprocess.run(f'ykushcmd ykush3 -d {port}', shell=True)
134+
for device in devices._device_by_sn.values():
135+
if device.port is None:
136+
log.w(f"Could not resolve YKUSH port for {device.name} ({device._sn})")
137+
continue
138+
key = device.name.upper()
139+
if key not in mapping:
140+
mapping[key] = device.port
141+
log.i(f"Detected device: {device.name} ({device._sn}) on port {device.port}")
151142

152143
return mapping
153144

154145

155-
def disable_all_ports():
156-
"""
157-
Disable all ports on the YKUSH hub.
158-
"""
159-
log.i("Disabling all ports...")
160-
subprocess.run(f'ykushcmd ykush3 -d a', shell=True)
161-
time.sleep(2.5) # Wait for the system to unregister devices
162-
163-
164-
def enable_port_for_device(device, port):
146+
def run_tests_for_device(device, port, testname):
165147
"""
166-
Enable the port for the specified device.
148+
Enable only the target device's YKUSH port (through rspy's hub) and run its
149+
tests. rspy owns the hub, so there are no direct ykushcmd calls.
167150
"""
168-
if port:
169-
log.i(f"Enabling port {port} for device {device.upper()}")
170-
subprocess.run(f'ykushcmd ykush3 -u {port}', shell=True)
171-
time.sleep(5.0) # Wait for re-enumeration
172-
else:
151+
from rspy import devices
152+
if port is None:
173153
log.e(f"No port mapping found for device {device.upper()}")
154+
return
174155

175-
176-
def run_tests_for_device(device, testname):
177-
"""
178-
Run tests for a specific device by enabling its port and executing the test command.
179-
"""
180-
181-
# Define which ports are connected to YKUSH (e.g., 1, 2, 3...)
182-
possible_ports = [1, 2, 3]
183-
device_port_mapping = build_device_port_mapping(possible_ports)
184-
log.i("Device to port mapping:", device_port_mapping)
185-
186-
disable_all_ports() # Disable all ports first
187-
188-
port = device_port_mapping.get(device.upper())
189-
enable_port_for_device(device, port) # Enable the port for the target device
156+
if devices.hub:
157+
devices.hub.enable_ports([port], disable_other_ports=True, sleep_on_change=5)
190158

191159
cmd = command(device.lower(), testname)
192160
run_test(cmd, testname, device, stdout=logdir, append=False)
@@ -203,28 +171,35 @@ def find_devices_run_tests():
203171
try:
204172
os.makedirs(logdir, exist_ok=True)
205173

206-
# Update dict '_device_by_sn' from devices module of rspy
174+
# Let rspy own the YKUSH hub: discover it, enumerate the connected
175+
# devices and resolve each device's port. Skip the hub reset on the first
176+
# attempt -- the 'ykushcmd --reset' it runs prints 'cannot claim
177+
# interface' to the console while the board re-enumerates. Only reset as a
178+
# recovery step if the first enumeration comes up empty.
179+
first_attempt = True
207180
while max_retry and not devices._device_by_sn:
208-
subprocess.run('ykushcmd ykush3 --reset', shell=True)
209-
time.sleep(2.0)
210-
devices.query(hub_reset=hub_reset)
181+
devices.query(hub_reset=not first_attempt)
182+
first_attempt = False
211183
max_retry -= 1
212184

213185
if not devices._device_by_sn:
214186
assert False, 'No Camera device detected!'
215-
else:
216-
connected_devices = [device.name for device in devices._device_by_sn.values()]
217-
log.i('Connected devices:', connected_devices)
187+
188+
connected_devices = [device.name for device in devices._device_by_sn.values()]
189+
log.i('Connected devices:', connected_devices)
190+
device_port_mapping = build_device_port_mapping()
191+
log.i('Device to port mapping:', device_port_mapping)
218192

219193
testname = regex if regex else None
220194

221195
if device_set:
222196
# Loop through user-specified devices and run tests only on them
223197
devices_not_found = []
224198
for device in device_set:
225-
if device.upper() in connected_devices:
199+
port = device_port_mapping.get(device.upper())
200+
if port is not None:
226201
log.i('Running tests on device:', device)
227-
run_tests_for_device(device, testname)
202+
run_tests_for_device(device, port, testname)
228203
else:
229204
log.e('Skipping test run on device:', device, ', -- NOT found')
230205
devices_not_found.append(device)
@@ -233,7 +208,7 @@ def find_devices_run_tests():
233208
# Loop through all connected devices and run all tests
234209
for device in connected_devices:
235210
log.i('Running tests on device:', device)
236-
run_tests_for_device(device, testname)
211+
run_tests_for_device(device, device_port_mapping.get(device.upper()), testname)
237212
finally:
238213
if devices.hub and devices.hub.is_connected():
239214
devices.hub.disable_ports()

realsense2_camera/test/utils/pytest_live_camera_utils.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def get_color_profiles(long_data, start_index, end_index):
122122
return cap
123123

124124
NAME_LINE_INDEX = 1
125-
NAME_LINE_NAME_OFFSET = 4
125+
NAME_LINE_VALUE_OFFSET = 2 # tokens after the "Name :" prefix
126126
SERIAL_NO_LINE_INDEX = 2
127127
SERIAL_NO_VALUE_OFFSET = 3
128128
def parse_device_info(long_data, start_index, end_index, device_type, serial_no):
@@ -132,10 +132,14 @@ def parse_device_info(long_data, start_index, end_index, device_type, serial_no)
132132
name_line = long_data[start_index+NAME_LINE_INDEX].split()
133133
if name_line[0] != "Name":
134134
assert False, "rs-enumerate-devices output format changed"
135-
if name_line[4] != device_type:
136-
debug_print("device not matching:" + name_line[NAME_LINE_NAME_OFFSET])
135+
# Name value tokens follow the "Name :" prefix. The model token (e.g.
136+
# "D455") is present whether or not a vendor prefix is shown, so match
137+
# on it directly.
138+
name_value_tokens = name_line[NAME_LINE_VALUE_OFFSET:]
139+
if device_type not in name_value_tokens:
140+
debug_print("device not matching:" + " ".join(name_value_tokens))
137141
return None
138-
debug_print("device matched:" + name_line[NAME_LINE_NAME_OFFSET])
142+
debug_print("device matched:" + device_type)
139143
if serial_no != None:
140144
#next line after nameline should have the serial_no
141145
serial_no_line = long_data[start_index+SERIAL_NO_LINE_INDEX].split()
@@ -193,15 +197,17 @@ def get_camera_capabilities_short(device_type, serial_no=None):
193197
def check_if_camera_connected(device_type, serial_no=None):
194198
long_data = os.popen("rs-enumerate-devices -s").read().splitlines()
195199
debug_print(serial_no)
196-
index = 0
197-
for index in range(len(long_data)):
198-
name_line = long_data[index].split()
199-
if name_line[0] != "Intel":
200-
continue
201-
if name_line[2].casefold() != device_type.casefold():
202-
continue
203-
if serial_no is None or serial_no == name_line[3]:
204-
return True
200+
for line in long_data:
201+
tokens = line.split()
202+
# The camera visible name may or may not carry a vendor prefix, so
203+
# match the model token directly instead of relying on a fixed
204+
# column index.
205+
for i, token in enumerate(tokens):
206+
if token.casefold() != device_type.casefold():
207+
continue
208+
# The serial number is the token right after the model name.
209+
if serial_no is None or (i + 1 < len(tokens) and serial_no == tokens[i + 1]):
210+
return True
205211

206212
return False
207213

realsense2_camera_msgs/package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
33
<package format="3">
44
<name>realsense2_camera_msgs</name>
5-
<version>4.58.2</version>
5+
<version>4.58.3</version>
66
<description>RealSense camera_msgs package containing realsense camera messages definitions</description>
77
<maintainer email="rsswsdk@realsensecloud.onmicrosoft.com">LibRealSense ROS Team</maintainer>
88
<maintainer email="nir.azkiel@realsenseai.com">Nir Azkiel</maintainer>

realsense2_description/package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
33
<package format="3">
44
<name>realsense2_description</name>
5-
<version>4.58.2</version>
5+
<version>4.58.3</version>
66
<description>RealSense description package for RealSense 3D D400 cameras</description>
77
<maintainer email="rsswsdk@realsensecloud.onmicrosoft.com">LibRealSense ROS Team</maintainer>
88
<maintainer email="nir.azkiel@realsenseai.com">Nir Azkiel</maintainer>

realsense2_rgbd_plugin/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ if(RVIZ_RGBD_PLUGIN)
6868
target_compile_definitions(realsense_rviz_plugin PRIVATE "RVIZ_DEFAULT_PLUGINS_BUILDING_LIBRARY")
6969
target_compile_definitions(realsense_rviz_plugin PRIVATE RVIZ_RGBD_PLUGIN)
7070

71+
# The header 'cv_bridge/cv_bridge.hpp' was added in version 3.3.0. For older
72+
# cv_bridge versions, we have to use the header 'cv_bridge/cv_bridge.h'.
73+
if(${cv_bridge_VERSION} VERSION_GREATER_EQUAL "3.3.0")
74+
target_compile_definitions(realsense_rviz_plugin PRIVATE CV_BRDIGE_HAS_HPP)
75+
endif()
76+
7177
# --- Modern CMake: link all dependencies explicitly ---
7278
# NOTE: Use ROS 2 typesupport targets for message packages.
7379
target_link_libraries(realsense_rviz_plugin

0 commit comments

Comments
 (0)