diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 0d42d1b..47aeb24 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -14,6 +14,7 @@ jobs:
- humble
- iron
- jazzy
+ - kilted
include:
- ros_distribution: foxy
docker_image: ros:foxy-ros-base
@@ -23,6 +24,8 @@ jobs:
docker_image: ros:iron-ros-base
- ros_distribution: jazzy
docker_image: ros:jazzy-ros-base
+ - ros_distribution: kilted
+ docker_image: ros:kilted-ros-base
container:
image: ${{ matrix.docker_image }}
steps:
@@ -68,7 +71,7 @@ jobs:
RMW_IMPLEMENTATION: rmw_fastrtps_cpp
ROS_LOCALHOST_ONLY: 0
run: |
- . /opt/ros/${{ matrix.ros_distribution }}/setup.sh
+ . /opt/ros/${{ matrix.ros_distribution }}/setup.sh && \
dotnet test -c Release -p:BuildInParallel=false --no-build --verbosity normal --blame-crash-dump-type mini --blame-hang-dump-type none --blame-hang-timeout 1m
- name: Test (cyclonedds)
@@ -77,7 +80,7 @@ jobs:
RMW_IMPLEMENTATION: rmw_cyclonedds_cpp
ROS_LOCALHOST_ONLY: 0
run: |
- . /opt/ros/${{ matrix.ros_distribution }}/setup.sh
+ . /opt/ros/${{ matrix.ros_distribution }}/setup.sh && \
dotnet test -c Release -p:BuildInParallel=false --no-build --verbosity normal --blame-crash-dump-type mini --blame-hang-dump-type none --blame-hang-timeout 1m
windows:
@@ -90,7 +93,11 @@ jobs:
- humble
- iron
- jazzy
+ - kilted
include:
+ - ros_distribution: kilted
+ ros_archive: https://github.com/ros2/ros2/releases/download/release-kilted-20250728/ros2-kilted-20250728-windows-release-amd64.zip
+ is_legacy_distro: false
- ros_distribution: jazzy
ros_archive: https://github.com/ros2/ros2/releases/download/release-jazzy-20250820/ros2-jazzy-20250820-windows-release-amd64.zip
is_legacy_distro: false
@@ -107,7 +114,20 @@ jobs:
- uses: actions/checkout@v3
with:
submodules: true
-
+
+ - name: Restore cached ROS installation
+ id: ros-cache
+ uses: actions/cache@v3
+ with:
+ path: c:/dev/${{ matrix.ros_distribution }}/
+ key: ${{ matrix.ros_archive }}
+
+ - name: Download and install ROS
+ if: ${{ steps.ros-cache.outputs.cache-hit != 'true' }}
+ run: |
+ Invoke-WebRequest -Uri ${{ matrix.ros_archive }} -OutFile ros2-release.zip
+ Expand-Archive -Path ros2-release.zip c:/dev/${{ matrix.ros_distribution }}
+
- name: Install dependencies (Legacy)
if: ${{ matrix.is_legacy_distro }}
run: |
@@ -116,27 +136,28 @@ jobs:
choco install --limit-output --no-progress -y -s . tinyxml2
choco install --limit-output --no-progress -y openssl --version 1.1.1.2100
- - name: Install dependencies
+ - name: Install Pixi
if: ${{ !matrix.is_legacy_distro }}
run: |
Set-ExecutionPolicy ByPass
irm -useb https://pixi.sh/install.ps1 | iex
- irm https://raw.githubusercontent.com/ros2/ros2/refs/heads/jazzy/pixi.toml -OutFile pixi.toml
- $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
- pixi install
- - name: Restore cached ROS installation
- id: ros-cache
+ - name: Restore cached Pixi dependencies
+ if: ${{ !matrix.is_legacy_distro }}
+ id: pixi-cache
uses: actions/cache@v3
with:
- path: c:/dev/${{ matrix.ros_distribution }}/
- key: ${{ matrix.ros_archive }}
+ path: c:/dev/pixi/
+ key: pixi-${{ matrix.ros_distribution }}
- - name: Download and install ROS
- if: ${{ steps.ros-cache.outputs.cache-hit != 'true' }}
+ - name: Install dependencies
+ if: ${{ !matrix.is_legacy_distro }}
run: |
- Invoke-WebRequest -Uri ${{ matrix.ros_archive }} -OutFile ros2-release.zip
- Expand-Archive -Path ros2-release.zip c:/dev/${{ matrix.ros_distribution }}
+ mkdir c:/dev/pixi/
+ cd c:/dev/pixi/
+ irm https://raw.githubusercontent.com/ros2/ros2/refs/heads/${{ matrix.ros_distribution }}/pixi.toml -OutFile pixi.toml
+ $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
+ pixi install
- name: Setup .NET 8.0
uses: actions/setup-dotnet@v3
@@ -167,8 +188,8 @@ jobs:
RMW_IMPLEMENTATION: rmw_fastrtps_cpp
ROS_LOCALHOST_ONLY: 0
run: |
- refreshenv
- call c:/dev/${{ matrix.ros_distribution }}/ros2-windows/setup.bat
+ refreshenv && ^
+ call c:/dev/${{ matrix.ros_distribution }}/ros2-windows/setup.bat && ^
dotnet test -c Release -p:BuildInParallel=false --no-build --verbosity normal --blame-crash-dump-type mini --blame-hang-dump-type none --blame-hang-timeout 1m
- name: Test (cyclonedds) (Legacy)
@@ -179,8 +200,8 @@ jobs:
RMW_IMPLEMENTATION: rmw_cyclonedds_cpp
ROS_LOCALHOST_ONLY: 0
run: |
- refreshenv
- call c:/dev/${{ matrix.ros_distribution }}/ros2-windows/setup.bat
+ refreshenv && ^
+ call c:/dev/${{ matrix.ros_distribution }}/ros2-windows/setup.bat && ^
dotnet test -c Release -p:BuildInParallel=false --no-build --verbosity normal --blame-crash-dump-type mini --blame-hang-dump-type none --blame-hang-timeout 1m
- name: Test (fastrtps)
@@ -191,10 +212,9 @@ jobs:
RMW_IMPLEMENTATION: rmw_fastrtps_cpp
ROS_LOCALHOST_ONLY: 0
run: |
- refreshenv
- pixi shell
- call c:/dev/${{ matrix.ros_distribution }}/ros2-windows/setup.bat
- dotnet test -c Release -p:BuildInParallel=false --no-build --verbosity normal --blame-crash-dump-type mini --blame-hang-dump-type none --blame-hang-timeout 1m
+ refreshenv && ^
+ pixi run --manifest-path "c:/dev/pixi/" ^
+ cmd /c "call c:/dev/${{ matrix.ros_distribution }}/ros2-windows/setup.bat && dotnet test -c Release -p:BuildInParallel=false --no-build --verbosity normal --blame-crash-dump-type mini --blame-hang-dump-type none --blame-hang-timeout 1m"
- name: Test (cyclonedds)
if: ${{ !matrix.is_legacy_distro }}
@@ -204,10 +224,9 @@ jobs:
RMW_IMPLEMENTATION: rmw_cyclonedds_cpp
ROS_LOCALHOST_ONLY: 0
run: |
- refreshenv
- pixi shell
- call c:/dev/${{ matrix.ros_distribution }}/ros2-windows/setup.bat
- dotnet test -c Release -p:BuildInParallel=false --no-build --verbosity normal --blame-crash-dump-type mini --blame-hang-dump-type none --blame-hang-timeout 1m
+ refreshenv && ^
+ pixi run --manifest-path "c:/dev/pixi/" ^
+ cmd /c "call c:/dev/${{ matrix.ros_distribution }}/ros2-windows/setup.bat && dotnet test -c Release -p:BuildInParallel=false --no-build --verbosity normal --blame-crash-dump-type mini --blame-hang-dump-type none --blame-hang-timeout 1m"
#test_macos:
# runs-on: macos-latest
diff --git a/README.md b/README.md
index ef2d3fd..2bb7240 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,8 @@ rclnet is a fast and easy-to-use .NET wrapper over ROS 2 client library, allowin
## What's New in 2.0
- Added support for .NET 10 and changed minimum supported .NET version to 8.0
- - ROS2 Jazzy Support by @AlrayQiu ([#39](https://github.com/noelex/rclnet/pull/39))
+ - ROS 2 Kilted Support
+ - ROS 2 Jazzy Support by @AlrayQiu ([#39](https://github.com/noelex/rclnet/pull/39))
- Simplified message generation workflow by @ha-ves ([#38](https://github.com/noelex/rclnet/pull/38))
- String pooling is now disabled by default
@@ -48,6 +49,7 @@ Supported ROS 2 Distributions:
- Humble Hawksbill
- Iron Irwini
- Jazzy Jalisco
+- Kilted Kaiju
Supported Operating Systems:
- Ubuntu
diff --git a/src/Rcl.NET.Tests/kilted.Dockerfile b/src/Rcl.NET.Tests/kilted.Dockerfile
new file mode 100644
index 0000000..c526d63
--- /dev/null
+++ b/src/Rcl.NET.Tests/kilted.Dockerfile
@@ -0,0 +1,18 @@
+FROM ros:kilted-ros-core
+RUN apt-get update \
+ && apt-get -y install --no-install-recommends \
+ ros-kilted-rmw-cyclonedds-cpp \
+ ros-kilted-rmw-fastrtps-cpp \
+ ros-kilted-tf2-msgs \
+ ros-kilted-service-msgs \
+ wget \
+ && apt-get autoremove -y \
+ && apt-get clean -y \
+ && rm -rf /var/lib/apt/lists/* \
+ && wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh \
+ && chmod +x ./dotnet-install.sh \
+ && ./dotnet-install.sh --channel 10.0 --runtime dotnet \
+ && ./dotnet-install.sh --channel 9.0 --runtime dotnet \
+ && ./dotnet-install.sh --channel 8.0 --runtime dotnet
+ENV DOTNET_ROOT=/root/.dotnet
+ENV PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools
diff --git a/src/Rcl.NET.Tests/ubuntu.kilted.cyclonedds.runsettings b/src/Rcl.NET.Tests/ubuntu.kilted.cyclonedds.runsettings
new file mode 100644
index 0000000..35e576e
--- /dev/null
+++ b/src/Rcl.NET.Tests/ubuntu.kilted.cyclonedds.runsettings
@@ -0,0 +1,14 @@
+
+
+
+
+ kilted
+ 0
+ 3
+ 2
+ /opt/ros/kilted/opt/yaml_cpp_vendor/lib:/opt/ros/kilted/lib/x86_64-linux-gnu:/opt/ros/kilted/lib
+ /opt/ros/kilted
+ rmw_cyclonedds_cpp
+
+
+
\ No newline at end of file
diff --git a/src/Rcl.NET.Tests/ubuntu.kilted.fastrtps.runsettings b/src/Rcl.NET.Tests/ubuntu.kilted.fastrtps.runsettings
new file mode 100644
index 0000000..bc65570
--- /dev/null
+++ b/src/Rcl.NET.Tests/ubuntu.kilted.fastrtps.runsettings
@@ -0,0 +1,14 @@
+
+
+
+
+ kilted
+ 0
+ 3
+ 2
+ /opt/ros/kilted/opt/yaml_cpp_vendor/lib:/opt/ros/kilted/lib/x86_64-linux-gnu:/opt/ros/kilted/lib
+ /opt/ros/kilted
+ rmw_fastrtps_cpp
+
+
+
\ No newline at end of file
diff --git a/src/Rcl.NET/Interop/RclJazzy.cs b/src/Rcl.NET/Interop/RclJazzy.cs
index a6a05f9..ad344db 100644
--- a/src/Rcl.NET/Interop/RclJazzy.cs
+++ b/src/Rcl.NET/Interop/RclJazzy.cs
@@ -1,8 +1,16 @@
-using Rosidl.Runtime.Interop;
-using System.Runtime.InteropServices;
-using static Rcl.Interop.RclHumble;
+using System.Runtime.InteropServices;
namespace Rcl.Interop;
-// Same typedef with iron
-using RclJazzy = RclIron;
\ No newline at end of file
+unsafe static class RclJazzy
+{
+ [DllImport("rcl", CallingConvention = CallingConvention.Cdecl)]
+ public static extern rcl_ret_t rcl_timer_init2(
+ RclCommon.rcl_timer_t* timer,
+ RclCommon.rcl_clock_t* clock,
+ RclCommon.rcl_context_t* context,
+ long period,
+ delegate* unmanaged[Cdecl] callback,
+ RclCommon.rcl_allocator_t allocator,
+ bool autostart);
+}
\ No newline at end of file
diff --git a/src/Rcl.NET/Introspection/MessageIntrospection.cs b/src/Rcl.NET/Introspection/MessageIntrospection.cs
index 4f9d1d1..83f834c 100644
--- a/src/Rcl.NET/Introspection/MessageIntrospection.cs
+++ b/src/Rcl.NET/Introspection/MessageIntrospection.cs
@@ -39,7 +39,7 @@ public unsafe static IMessageIntrospection Create(MessageTypeSupport* typesuppor
{
return new HumbleMessageIntrospection(typesupport);
}
- else if (RosEnvironment.IsJazzy)
+ else if (RosEnvironment.IsJazzy || RosEnvironment.IsKilted)
{
return new JazzyMessageIntrospection(typesupport);
}
@@ -62,7 +62,7 @@ public unsafe static IMessageIntrospection Create(MessageMembers* messageMembers
{
return new HumbleMessageIntrospection(messageMembers);
}
- else if (RosEnvironment.IsJazzy)
+ else if (RosEnvironment.IsJazzy || RosEnvironment.IsKilted)
{
return new JazzyMessageIntrospection((MessageMembers_Jazzy*)messageMembers);
}
diff --git a/src/Rcl.NET/Parameters/Impl/ParameterService.cs b/src/Rcl.NET/Parameters/Impl/ParameterService.cs
index 00bc635..dc33878 100644
--- a/src/Rcl.NET/Parameters/Impl/ParameterService.cs
+++ b/src/Rcl.NET/Parameters/Impl/ParameterService.cs
@@ -98,7 +98,7 @@ internal unsafe ParameterService(RclNodeImpl node, IDictionary
{
return &((RclFoxy.rcl_node_options_t*)handle)->arguments;
}
- else if (RosEnvironment.IsHumble || RosEnvironment.IsIron || RosEnvironment.IsJazzy)
+ else if (RosEnvironment.IsHumble || RosEnvironment.IsIron || RosEnvironment.IsJazzy || RosEnvironment.IsKilted)
{
return &((RclHumble.rcl_node_options_t*)handle)->arguments;
}
diff --git a/src/Rcl.NET/RosEnvironment.cs b/src/Rcl.NET/RosEnvironment.cs
index 541944d..3f7a16f 100644
--- a/src/Rcl.NET/RosEnvironment.cs
+++ b/src/Rcl.NET/RosEnvironment.cs
@@ -14,7 +14,7 @@ internal enum VersionRequirement
///
public unsafe static class RosEnvironment
{
- private static readonly string[] SupportedDistributions = new[] { Foxy, Humble, Iron, Jazzy };
+ private static readonly string[] SupportedDistributions = [Foxy, Humble, Iron, Jazzy, Kilted];
///
/// ROS 2 Foxy Fitzroy.
@@ -36,6 +36,11 @@ public unsafe static class RosEnvironment
///
public const string Jazzy = "jazzy";
+ ///
+ /// ROS 2 Kilted Kaiju
+ ///
+ public const string Kilted = "kilted";
+
///
/// Gets whether the application is running in foxy.
///
@@ -50,11 +55,17 @@ public unsafe static class RosEnvironment
/// Gets whether the application is running in iron.
///
public static bool IsIron => Distribution == Iron;
+
///
- /// Gets whether the application is running in iron.
+ /// Gets whether the application is running in jazzy.
///
public static bool IsJazzy => Distribution == Jazzy;
+ ///
+ /// Gets whether the application is running in kilted.
+ ///
+ public static bool IsKilted => Distribution == Kilted;
+
///
/// Get the name of the rmw implementation being used.
///
diff --git a/src/Rcl.NET/SafeHandles/SafeNodeHandle.cs b/src/Rcl.NET/SafeHandles/SafeNodeHandle.cs
index a51a372..d5bc840 100644
--- a/src/Rcl.NET/SafeHandles/SafeNodeHandle.cs
+++ b/src/Rcl.NET/SafeHandles/SafeNodeHandle.cs
@@ -31,6 +31,7 @@ public SafeNodeHandle(SafeContextHandle context, string name, string @namespace,
case RosEnvironment.Humble:
case RosEnvironment.Iron:
case RosEnvironment.Jazzy:
+ case RosEnvironment.Kilted:
InitHumbleOrLater(namePtr, nsPtr, context, options);
break;
default: throw new NotImplementedException();
diff --git a/src/Rcl.NET/SafeHandles/SafeTimerHandle.cs b/src/Rcl.NET/SafeHandles/SafeTimerHandle.cs
index 3fa3fb0..fe3fb8e 100644
--- a/src/Rcl.NET/SafeHandles/SafeTimerHandle.cs
+++ b/src/Rcl.NET/SafeHandles/SafeTimerHandle.cs
@@ -1,4 +1,4 @@
-using Rosidl.Messages.Rosgraph;
+using Rcl.Interop;
namespace Rcl.SafeHandles;
@@ -10,15 +10,24 @@ public SafeTimerHandle(
SafeContextHandle context, SafeClockHandle clock, long period)
{
_clock = clock;
- * Object = rcl_get_zero_initialized_timer();
+ *Object = rcl_get_zero_initialized_timer();
try
{
using (ScopedLock.Lock(ref _clock.SyncRoot))
{
- RclException.ThrowIfNonSuccess(
- rcl_timer_init(Object, clock.Object, context.Object,
- period, null, RclAllocator.Default.Object));
+ if (RosEnvironment.IsSupported(RosEnvironment.Jazzy))
+ {
+ RclException.ThrowIfNonSuccess(
+ RclJazzy.rcl_timer_init2(Object, clock.Object, context.Object,
+ period, null, RclAllocator.Default.Object, true));
+ }
+ else
+ {
+ RclException.ThrowIfNonSuccess(
+ rcl_timer_init(Object, clock.Object, context.Object,
+ period, null, RclAllocator.Default.Object));
+ }
_clock.AddTimerRef();
}
}
diff --git a/src/testEnvironments.json b/src/testEnvironments.json
index bf79059..072df2d 100644
--- a/src/testEnvironments.json
+++ b/src/testEnvironments.json
@@ -35,6 +35,11 @@
"name": "Container - Jazzy",
"type": "docker",
"dockerFile": "Rcl.NET.Tests/jazzy.Dockerfile"
+ },
+ {
+ "name": "Container - Kilted",
+ "type": "docker",
+ "dockerFile": "Rcl.NET.Tests/kilted.Dockerfile"
}
]
}