Skip to content

Commit

Permalink
minor update
Browse files Browse the repository at this point in the history
  • Loading branch information
yuokamoto committed Oct 16, 2023
1 parent 5c77931 commit 408577d
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 50 deletions.
20 changes: 18 additions & 2 deletions Source/rclUE/Public/ROS2Publisher.h
Expand Up @@ -284,10 +284,26 @@ class RCLUE_API UROS2PublisherComponent : public UActorComponent
*
*/
UCLASS(Blueprintable, BlueprintType, ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class RCLUE_API UROS2CustomPublisherComponent : public UROS2PublisherComponent
class RCLUE_API UROS2CustomPublisherComponent : public UActorComponent
{
GENERATED_BODY()

public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UROS2Publisher* Publisher = nullptr;

//! this is pass to #UROS2Publisher::TopicName in #BeginPlay
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString TopicName = TEXT("");

//! this is pass to #UROS2Publisher::PublisherClass in #BeginPlay
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSubclassOf<UROS2Publisher> PublisherClass = UROS2Publisher::StaticClass();

//! this is pass to #UROS2Publisher::PublicationFrequencyHz in #BeginPlay
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float PublicationFrequencyHz = 1.f;

virtual void BeginPlay() override
{
if (Publisher == nullptr)
Expand All @@ -298,6 +314,6 @@ class RCLUE_API UROS2CustomPublisherComponent : public UROS2PublisherComponent
{
UE_LOG_WITH_INFO(LogTemp, Warning, TEXT("Publisher class is not created in BeginPlay."));
}
UActorComponent::BeginPlay();
Super::BeginPlay();
};
};
95 changes: 47 additions & 48 deletions docs/source/examples/publisher_example.rst
Expand Up @@ -3,7 +3,7 @@
Publisher Example
=============================

Please follow the instructions in :ref:`setup_and_run_ue_project` to set up the UE project
Please follow the instructions in :ref:`setup_and_run_ue_project` to set up the UE project
and open `ROS2TopicExample.umap <https://github.com/rapyuta-robotics/turtlebot3-UE/blob/devel/Content/Maps/ROS2TopicExamples.umap>`_.

-----------------------------
Expand Down Expand Up @@ -125,26 +125,26 @@ Code
Code explanations
^^^^^^^^^^^^^^^^^^

In the constructor,
the `UROS2NodeComponent <../doxygen_generated/html/d7/d68/class_u_r_o_s2_node_component.html>`_
is created using
`CreateDefaultSubobject <https://docs.unrealengine.com/4.26/en-US/API/Runtime/CoreUObject/UObject/UObject/CreateDefaultSubobject/2/>`_
In the constructor,
the `UROS2NodeComponent <../doxygen_generated/html/d7/d68/class_u_r_o_s2_node_component.html>`_
is created using
`CreateDefaultSubobject <https://docs.unrealengine.com/4.26/en-US/API/Runtime/CoreUObject/UObject/UObject/CreateDefaultSubobject/2/>`_
and its parameters such as Node Name and Namespace are set.

Although the UROS2NodeComponent is created,
the ROS2 Node is not yet initialized at this point.
Initialization of the ROS2 Node occurs during the
`BeginPlay <https://docs.unrealengine.com/5.1/en-US/API/Runtime/Engine/GameFramework/AActor/BeginPlay/>`_
Although the UROS2NodeComponent is created,
the ROS2 Node is not yet initialized at this point.
Initialization of the ROS2 Node occurs during the
`BeginPlay <https://docs.unrealengine.com/5.1/en-US/API/Runtime/Engine/GameFramework/AActor/BeginPlay/>`_
method, which is called when the simulation starts.

One reason to initialize in BeginPlay is to create a ROS2 Node when the simulation starts.
It is important to note that the UE Class constructor may also be called before simulation starts, for example,
One reason to initialize in BeginPlay is to create a ROS2 Node when the simulation starts.
It is important to note that the UE Class constructor may also be called before simulation starts, for example,
when an Actor is placed in the level. For a better understanding of Actor Lifecycle, please refer to the
`UE Actor LifeCycle <https://docs.unrealengine.com/5.1/en-US/unreal-engine-actor-lifecycle/>`_
`UE Actor LifeCycle <https://docs.unrealengine.com/5.1/en-US/unreal-engine-actor-lifecycle/>`_
However, understanding the entire lifecycle is not necessary to use rclUE.

Another significant difference is that by initializing in BeginPlay,
variables such as publication frequency can be set in the editor and
Another significant difference is that by initializing in BeginPlay,
variables such as publication frequency can be set in the editor and
their changes will be reflected when running the simulation.
If, in contrast, we initialize things in the constructor,
variables changed in the editor would not reflect in the simulation,
Expand All @@ -161,7 +161,7 @@ unless we restart the editor.
Node->Namespace = TEXT("cpp");
}

When simulation starts, BeginPlay is called. In the BeginPlay,
When simulation starts, BeginPlay is called. In the BeginPlay,
firstly create and initialize ROS2 Node by calling
`UROS2NodeComponent::Init <../doxygen_generated/html/d7/d68/class_u_r_o_s2_node_component.html#ab9b7b990c4ca38eb60acf8e0a53c3e52>`_
.
Expand All @@ -180,19 +180,19 @@ then starts adding publishers. We introduce 3 ways to add publisher here.
Non Loop Publisher
~~~~~~~~~~~~~~~~~~~~~~

This will create a publisher and publish a message once.
It is a straightforward way to publish a message,
This will create a publisher and publish a message once.
It is a straightforward way to publish a message,
involving creating a publisher, creating a message, and publishing the message.

To create a publisher, use
To create a publisher, use
`UROS2NodeComponent::CreatePublisher <../doxygen_generated/html/d7/d68/class_u_r_o_s2_node_component.html#a5a7cb19de75e1970894efe2dcb4ac57c>`_

Create a structure (FROSStr) for the contrasting message (UROSStrMsg) and
assign characters to the Data field.
Create a structure (FROSStr) for the contrasting message (UROSStrMsg) and
assign characters to the Data field.
Then, assign the structure to the message using the SetMsg method.

Finally, call the
`UROS2Publisher::Publish <../doxygen_generated/html/d6/dd4/class_u_r_o_s2_publisher.html#a1c80608e01c7bdeb74ffe3bb82112222>`_
Finally, call the
`UROS2Publisher::Publish <../doxygen_generated/html/d6/dd4/class_u_r_o_s2_publisher.html#a1c80608e01c7bdeb74ffe3bb82112222>`_
method to publish the topic.

.. code-block:: C++
Expand All @@ -212,10 +212,10 @@ method to publish the topic.
Loop Publisher
~~~~~~~~~~~~~~~~~~~~~~

You can create a loop publisher by using the
You can create a loop publisher by using the
`ROS2_CREATE_LOOP_PUBLISHER_WITH_QOS <../doxygen_generated/html/d1/d79/_r_o_s2_node_component_8h.html#aa037d93e1d31d5436f12553248889060>`_
macro.
This macro creates a publisher and adds it to the node,
macro.
This macro creates a publisher and adds it to the node,
and then it periodically calls the AROS2PublisherNode::UpdateMessage method.

.. code-block:: C++
Expand All @@ -231,8 +231,8 @@ and then it periodically calls the AROS2PublisherNode::UpdateMessage method.
UROS2QoS::Default,
LoopPublisher);

UpdateMessage method does similar things as a non-loop publisher.
Since the loop publisher automatically calls the "Publish()" method,
UpdateMessage method does similar things as a non-loop publisher.
Since the loop publisher automatically calls the "Publish()" method,
you only need to create and set the message.

.. code-block:: C++
Expand All @@ -244,9 +244,9 @@ you only need to create and set the message.
CastChecked<UROS2StrMsg>(InMessage)->SetMsg(msg);
}
The implementation of ROS2_CREATE_LOOP_PUBLISHER_WITH_QOS is as follows.
It uses Unreal Engine's dynamic delegate to call a bound function periodically.
You can find more information about Unreal Engine's dynamic delegate
The implementation of ROS2_CREATE_LOOP_PUBLISHER_WITH_QOS is as follows.
It uses Unreal Engine's dynamic delegate to call a bound function periodically.
You can find more information about Unreal Engine's dynamic delegate
`here <https://docs.unrealengine.com/5.1/en-US/dynamic-delegates-in-unreal-engine/>`_.

.. code-block:: C++
Expand All @@ -266,7 +266,7 @@ You can find more information about Unreal Engine's dynamic delegate
Custom Publisher class
~~~~~~~~~~~~~~~~~~~~~~

You can create a publisher by defining a child class of UROS2Publisher.
You can create a publisher by defining a child class of UROS2Publisher.
This is useful when you want to add some custom logic to the publisher that will be used in multiple places.

.. code-block:: C++
Expand All @@ -277,11 +277,11 @@ This is useful when you want to add some custom logic to the publisher that will
Node->CreateLoopPublisherWithClass(TopicName, URRROS2StringPublisher::StaticClass(), 1.f));
StringPublisher->Message = FString::Printf(TEXT("%s from custom class"), *Message);
The implementation of UROS2StringPublisher is as follows.
The implementation of UROS2StringPublisher is as follows.
UROS2StringPublisher is a child class of UROS2Publisher.

The constructor is used to set default publisher settings.
You can add user-defined logic by overriding the UpdateMessage method,
The constructor is used to set default publisher settings.
You can add user-defined logic by overriding the UpdateMessage method,
which is called periodically if PublicationFrequencyHz > 0.

.. code-block:: C++
Expand Down Expand Up @@ -311,7 +311,7 @@ which is called periodically if PublicationFrequencyHz > 0.
BP Publisher
-----------------------------

Blueprint implementation of a publisher is very similar to a C++ implementation.
Blueprint implementation of a publisher is very similar to a C++ implementation.
Blueprints allow you to set logic/processes, parameters, and other details from the editor.

You can add component such as UROS2Publisher from `Components` panel in the editor(left side in the fig below)
Expand All @@ -326,12 +326,12 @@ Overview of BP Publisher
.. image:: ../images/publisher_overview.png


Similar to the C++ implementation, the BP class has three types of publishers:
Similar to the C++ implementation, the BP class has three types of publishers:
Non-Loop Publisher, Loop Publisher, and Custom Publisher.

The main difference from the C++ implementation is that it uses
The main difference from the C++ implementation is that it uses
`UROS2PublisherComponent <../doxygen_generated/html/db/d27/class_u_r_o_s2_publisher_component.html>`_
instead of UROS2Publisher.
instead of UROS2Publisher.
As UROS2PublisherComponent is a child class of `UActorComponent <https://docs.unrealengine.com/5.1/en-US/API/Runtime/Engine/Components/UActorComponent/>`_
and has UROS2Publisher as a member variable, you can easily add it to the Actor and set parameters from the editor.

Expand All @@ -343,20 +343,20 @@ Details of BP Publisher

.. image:: ../images/publisher_node.png

Initialize the ROS2 Node using the BeginPlay event.
You can set the ROSNode parameters, such as Name and Namespace,
Initialize the ROS2 Node using the BeginPlay event.
You can set the ROSNode parameters, such as Name and Namespace,
from the `Details` panel on the right.

Non Loop Publisher
~~~~~~~~~~~~~~~~~~~~~~

.. image:: ../images/publisher_non_loop.png

Compared to C++, which uses CreatePublisher(),
in Blueprint, the Publisher is already generated as a Component before BeginPlay.
Therefore, we use
`UROS2NodeComponent::AddPublisher <../doxygen_generated/html/d7/d68/class_u_r_o_s2_node_component.html#a582299af64efaaa34b046c00b1c96828>_`
to initialize the Publisher instead.
Compared to C++, which uses CreatePublisher(),
in Blueprint, the Publisher is already generated as a Component before BeginPlay.
Therefore, we use
`UROS2NodeComponent::AddPublisher <../doxygen_generated/html/d7/d68/class_u_r_o_s2_node_component.html#a582299af64efaaa34b046c00b1c96828>_`
to initialize the Publisher instead.
The CreatePublisher function in C++ internally calls AddPublisher.

You can see that parameters such as Topic Name, Publisher Class, and Msg Class are set in the right `Details` panel.
Expand All @@ -366,13 +366,12 @@ Loop Publisher

.. image:: ../images/publisher_loop.png

Callback function is bound to a custom event, indicated by the red node in the center.
Callback function is bound to a custom event, indicated by the red node in the center.
This callback function is executed at regular intervals with a specified frequency.

Custom Publisher class
~~~~~~~~~~~~~~~~~~~~~~

.. image:: ../images/publisher_custom.png

To set parameters for a custom publisher object,
we need to create a variable of the custom publisher class and then assign it to the publisher component.
Since custom publisher class is alreay set class, callbak and etc, we just need to add it to the node.
Binary file modified docs/source/images/publisher_custom.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 408577d

Please sign in to comment.