Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Add Ros Publisher

ASecurity

Adds a new topic to CARLA's native ROS 2 interface — a publisher (BasePublisher + PublisherImpl, topic suffix, QoS, registration in ROS2::GetOrCreateSensor, a ProcessDataFrom* entry point and its call site in the UE4 plugin) or a subscriber that lets ROS drive an actor. Also covers adding a middleware (RMW) behind IPublisherMiddleware. Use when the user asks to "publish X to ROS from CARLA", "add a ROS topic/publisher/subscriber", "make the obstacle/lane-invasion sensor publish", "add odometr...

3 stars
0 votes
0 copies
0 views
Added 9/20/2026
designgobash

Works with

cli

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add carla-simulator/carla-agentic-tools --skill add-ros-publisher --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Add Ros Publisher?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Add Ros Publisher
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/carla-simulator-add-ros-publisher/badge)](https://www.skillsdirectory.com/skills/carla-simulator-add-ros-publisher)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: add-ros-publisher
description: Adds a new topic to CARLA's native ROS 2 interface — a publisher (BasePublisher + PublisherImpl, topic suffix, QoS, registration in ROS2::GetOrCreateSensor, a ProcessDataFrom* entry point and its call site in the UE4 plugin) or a subscriber that lets ROS drive an actor. Also covers adding a middleware (RMW) behind IPublisherMiddleware. Use when the user asks to "publish X to ROS from CARLA", "add a ROS topic/publisher/subscriber", "make the obstacle/lane-invasion sensor publish", "add odometry to ROS", or "add another RMW".
license: MIT
compatibility: A CARLA checkout whose LibCarla/source/carla/ros2 exists (native ROS 2 branch) and the toolchain to build LibCarla with --ros2 plus the UE4 plugin. Editing only. Proving a new topic on the wire needs a ROS 2 consumer (visualize-ros-rviz) and a server built with ROS 2.
metadata:
  group: ros2
  requires: add-ros-message-type
  prerequisites: scripts/check_env.sh
  reference: references/layers.md
---

# Add a ROS 2 publisher or subscriber

> **Paths.** `scripts/…` and `references/…` below are relative to the
> directory holding this SKILL.md. Your working directory is the user's
> project, not that directory, so prefix them with its absolute path or the
> command is not found.

A topic exists only when **four** things line up: a message type, a publisher
object, a registration so something creates it, and a call site that feeds it
data. Miss the last one and everything compiles while the topic never appears.

```
UE4 sensor/actor  --ProcessDataFrom*-->  ROS2 (dispatch, ROS2.cpp)
                                          |  GetOrCreateSensor / RegisterVehicle
                                          v
                            Carla<X>Publisher  (topic suffix + QoS)
                                          v
                            PublisherImpl<Traits>  -> MiddlewareFactory
                                          v
                     FastDDS | CycloneDDS | Zenoh middleware
```

Message types are [[add-ros-message-type]]; this skill is everything below the
type.

## On CARLA 0.10.0 (the UE5 line: 5.5 and 5.8)

The publisher layer was refactored on 0.10.0, so the file you copy from differs.
The right-hand column is UE 5.8; **UE 5.5 has the same `BasicPublisher` refactor
but no `middleware/` directory**, so its QoS type is the pre-`QosProfile.h` one
and it has none of the Autoware rows ([[check-ue5-limitations]]):

| | 0.9.x | 0.10.0 |
|---|---|---|
| base class to inherit | `CarlaPublisher` | `BasicPublisher` (and `BasicSubscriber` / `BasicListener`) |
| QoS type | `PublisherQos.h` | `QosProfile.h` |
| middleware | `IPublisherMiddleware` impls | same, plus `ActiveMiddleware.{h,cpp}` |
| map publisher | `CarlaMapPublisher` | **removed** — do not model a new publisher on it |
| DVS camera | `CarlaDVSPublisher` | `CarlaDVSCameraPublisher` |
| Autoware | — | `AutowareGNSSPublisher`, `AutowareVehicleStatusPublisher`, `AutowareControlSubscriber`, `AutowareSteeringCompensation.h` |

0.10.0 also factors the per-sensor maths out of the publishers into reusable
headers you should use rather than re-derive: `CameraIntrinsics`, `ImuMath`,
`DvsEventEncoding`, `OpticalFlowEncoding`, `PointCloudFieldsLayout`,
`RadarPolarToCartesian`, `TransformQuaternion`, and `AckermannControlConversion`
on the subscriber side. A new `listeners/` directory holds `BasicListener`.

The registration point, the `ProcessDataFrom*` entry points and the UE plugin call
sites work the same way on both.

## Instructions

```
Progress:
- [ ] Step 1: Check prerequisites (bash scripts/check_env.sh), clear FAILs
- [ ] Step 2: Confirm the message type exists in types/msg (else add-ros-message-type)
- [ ] Step 3: Write publishers/Carla<X>Publisher.h (+ .cpp for the Write logic)
- [ ] Step 4: Register it — GetOrCreateSensor case, or RegisterVehicle/Actor
- [ ] Step 5: Add the ProcessDataFrom<X> entry point in ROS2.h/.cpp
- [ ] Step 6: Call it from the UE4 side, inside `#if defined(WITH_ROS2)`
- [ ] Step 7: bash scripts/verify.sh, then rebuild the plugin (build-carla-ue4 ROS2=1)
- [ ] Step 8: Prove the topic — visualize-ros-rviz topics / hz
```

### Step 3: the publisher

Copy the shape of the simplest existing one (`CarlaGNSSPublisher`): derive from
`BasePublisher`, hold a `PublisherImpl<Traits>`, `Init` the topic in the
constructor, implement `Write(...)` and `Publish()`.

```cpp
class CarlaFooPublisher : public BasePublisher {
  public:
    struct FooMsgTraits { using msg_type = msg::Foo; };   // the only type binding

    CarlaFooPublisher(std::string base_topic_name, std::string frame_id):
      BasePublisher(base_topic_name, frame_id),
      _impl(std::make_shared<PublisherImpl<FooMsgTraits>>()) {
        // Suffix decides the topic; NO suffix means "publish on the base name",
        // which is what IMU/GNSS/collision do. Pass PublisherQos::SensorData()
        // for high-rate streams so a slow subscriber cannot stall the sim.
        if (!_impl->Init(GetBaseTopicName() + "/foo", PublisherQos::SensorData())) {
          log_warning("CarlaFooPublisher: Init failed for topic: ", GetBaseTopicName(), "/foo");
        }
    }
    bool Publish() { return _impl->Publish(); }
    bool Write(int32_t seconds, uint32_t nanoseconds, /* payload */);
  private:
    std::shared_ptr<PublisherImpl<FooMsgTraits>> _impl;
};
```

Header in `publishers/`, `Write` body in the matching `.cpp` if it is more than a
few lines. **No CMake edit is needed** — `LibCarla/cmake/ros2/CMakeLists.txt`
globs `publishers/*.cpp`, `subscribers/*.cpp`, `types/*.cpp`,
`middleware/*/*.cpp`. A brand-new *subdirectory* does need a glob entry.

Init failure is a **warning, not an error**: a typo'd topic leaves a live
publisher object that publishes nowhere. Watch for that line in the server log.

### Steps 4-6: wire it up

| For | Register in | Feed from |
|---|---|---|
| a sensor | a `case ESensors::<X>:` in `ROS2::GetOrCreateSensor` | `ProcessDataFrom<X>` called in that sensor's UE4 class |
| a vehicle/actor stream | `ROS2::RegisterVehicle` / `RegisterActor` | the actor's tick or an RPC path |
| a subscriber (ROS drives CARLA) | `RegisterVehicle`'s subscriber list | `ProcessMessages(callback)` → `ActorROS2Handler` |

The dispatch function is the seam: it takes the raw CARLA data, casts the base
publisher to the concrete type, `Write`s, `Publish`es, and (for sensors) also
updates the TF publisher. Copy `ProcessDataFromGNSS` — it is the shortest
complete example.

On the UE4 side the call must sit inside `#if defined(WITH_ROS2)` and be guarded
by `ROS2->IsEnabled()`; the transform passed is **relative to the attach parent**
when there is one:

```cpp
#if defined(WITH_ROS2)
auto ROS2 = carla::ros2::ROS2::GetInstance();
if (ROS2->IsEnabled()) {
  AActor* ParentActor = GetAttachParentActor();
  auto Transform = ParentActor ? GetActorTransform().GetRelativeTransform(ParentActor->GetActorTransform())
                               : GetActorTransform();
  ROS2->ProcessDataFromFoo(Stream.GetSensorType(), Transform, Data, this);
}
#endif
```

### Steps 7-8: verify

```bash
bash scripts/verify.sh                          # LibCarla + its tests, with --ros2
ROS2=1 bash ../../ue4/build-carla-ue4/scripts/06_build_editor.sh   # the plugin call site
# then, against a running ROS 2 server:
bash ../visualize-ros-rviz/scripts/ros_view.sh topics
bash ../visualize-ros-rviz/scripts/ros_view.sh hz /carla/<actor>/foo
```

`verify.sh` proves it compiles and the middleware layer still passes its tests.
**Only `hz`/`echo` proves the topic.** A publisher can build, register, and still
be silent: the most common reasons are the sensor not being enabled for ROS
([[create-sensor]] `--ros`), a UE4 call site that never runs, and a sensor whose
`Tick` is skipped because nothing listens.

## Sensors with no publisher yet

`ROS2::GetOrCreateSensor` deliberately returns `nullptr` for these, so they are
the natural targets — and each already has a `ProcessDataFrom*` or needs one:

| Sensor | Note |
|---|---|
| `other.lane_invasion` | `CarlaLineInvasion` message type already exists |
| `other.obstacle` | `ProcessDataFromObstacleDetection` exists in `ROS2.h` |
| `other.rss` | no message type yet |
| world observer | high volume; think before publishing |

## Adding a middleware (RMW)

Same layer, one level down: implement `IPublisherMiddleware` /
`ISubscriberMiddleware`, add the include + `case` in `MiddlewareFactory`, a
`Middleware` enum value and its `MiddlewareFromString` mapping, and a
`CARLA_ROS2_MIDDLEWARE_<NAME>` compile definition in
`LibCarla/cmake/ros2/CMakeLists.txt` (all three are defined at once, so
`IsMiddlewareAvailable` answers correctly at run time). Extend
`test_ros2_middleware.cpp`. Per-RMW quirks — Zenoh's router and wire format,
CycloneDDS's sertype, FastDDS's shared participant — are in
[`references/layers.md`](references/layers.md).

## Examples

**Example 1: publish the obstacle sensor**

User says: "make the obstacle detection sensor publish to ROS"

`CarlaLineInvasion`/a suitable type exists → write `CarlaObstaclePublisher` →
replace the `nullptr` case for `ESensors::ObstacleDetectionSensor` → fill in
`ProcessDataFromObstacleDetection` (declared already) → the call site in
`ObstacleDetectionSensor.cpp` already exists → verify → `hz`.

**Example 2: let ROS steer via a new command topic**

User says: "add a ROS topic to set the ego's target speed"

Type first ([[add-ros-message-type]]) → subscriber modelled on
`AckermannControlSubscriber` → register it in `RegisterVehicle` → extend
`ROS2CallbackData` and `ActorROS2Handler` to apply it → verify → `ros2 topic pub`.

**Example 3: a fourth RMW**

User says: "add support for another DDS implementation"

Follow "Adding a middleware": interface pair, factory case, enum + string, CMake
definition, test. No publisher changes at all — that is the point of the layer.

## Troubleshooting

**Problem: it all compiles but the topic never appears**
Cause: usually the call site, not the publisher — the `#if defined(WITH_ROS2)`
block is missing, unreachable, or the plugin was rebuilt without `ROS2=1`.
Solution: confirm `Ros2 ON` in `Config/OptionalModules.ini`, rebuild step 06 with
`ROS2=1`, then check the sensor is `enable_for_ros`-ed.

**Problem: `PublisherImpl: Failed to create middleware publisher`**
Cause: `MiddlewareFactory` has no case for the active middleware, or the RMW is
not compiled in.
Solution: check `IsMiddlewareAvailable` and the `CARLA_ROS2_MIDDLEWARE_*`
definitions in `LibCarla/cmake/ros2/CMakeLists.txt`.

**Problem: `Init failed for topic: …` in the server log, everything else fine**
Cause: an invalid topic name (empty `ros_name`, double slash) — Init only warns.
Solution: fix the name; remember unnamed actors become `actor<id>`.

**Problem: subscriber never receives, publisher works**
Cause: QoS mismatch (the peer is reliable+transient_local against a volatile
publisher), or the topic string differs by a suffix.
Solution: `visualize-ros-rviz info <topic>` shows endpoint counts and QoS on both
sides.

**Problem: a new `.cpp` is not compiled**
Cause: it is in a new subdirectory; the CMake glob lists directories explicitly.
Solution: add the glob line in `LibCarla/cmake/ros2/CMakeLists.txt`.

## Outputs

Edited sources in the checkout, a green `check.LibCarla`, and — after the plugin
rebuild — a new topic visible from ROS 2.

Layer-by-layer detail (publisher/subscriber contracts, QoS profiles, dispatch,
the middleware interfaces and their quirks) in
[`references/layers.md`](references/layers.md).

Attribution

carla-simulatorcarla-simulator
View sourceMore from carla-simulator →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Responsive Design

Implement modern responsive layouts using container queries, fluid typography, CSS Grid, and mobile-first breakpoint strategies. Use when building adaptive interfaces, implementing fluid layouts, or creating component-level responsive behavior.

393432 votes

Mermaid Diagrams

Creating and refining Mermaid diagrams with live reload. Use when users want flowcharts, sequence diagrams, class diagrams, ER diagrams, state diagrams, or any other Mermaid visualization. Provides best practices for syntax, styling, and the iterative workflow using mermaid_preview and mermaid_save tools.

2032 votes

sleek-design-mobile-apps

Use when the user wants to design a mobile app, create screens, build UI, or interact with their Sleek projects. Covers high-level requests ("design an app that does X") and specific ones ("list my projects", "create a new project", "screenshot that screen").

5711 votes

swiftui-design-skill

SwiftUI frontend visual design skill. Creates beautiful, distinctive iOS/macOS interfaces that avoid generic AI slop patterns. Covers design direction, layout systems, typography, color, spacing, brand integration, and design review. Use when designing new SwiftUI views, reviewing UI quality, creating iOS prototypes, choosing visual styles, improving app aesthetics, or when the UI looks generic or AI-generated.

1801 votes

Ios Hig

Use when designing iOS interfaces, implementing accessibility (VoiceOver, Dynamic Type), handling dark mode, ensuring adequate touch targets, providing animation/haptic feedback, or requesting user permissions. Apple Human Interface Guidelines for iOS compliance.

761 votes
View all in design →