-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #91 from cactusdynamics/ros2
Added ROS2 integration by allowing a real-time thread to publish
- Loading branch information
Showing
17 changed files
with
569 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,5 @@ build/ | |
.cache/ | ||
|
||
.vscode/settings.json | ||
log/ | ||
install/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
find_package(ament_cmake REQUIRED) | ||
find_package(rclcpp REQUIRED) | ||
|
||
target_sources(cactus_rt | ||
PRIVATE | ||
src/cactus_rt/ros2/ros2_adapter.cc | ||
src/cactus_rt/ros2/app.cc | ||
) | ||
|
||
ament_target_dependencies(cactus_rt | ||
PUBLIC | ||
rclcpp | ||
) | ||
|
||
add_subdirectory(examples/ros2/publisher) | ||
|
||
ament_package() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
cmake-args: | ||
- "-DENABLE_ROS2=ON" | ||
- "-DENABLE_EXAMPLES=OFF" |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
ROS2 integration with cactus-rt | ||
=============================== | ||
|
||
![cactus-rt ROS2 integration object ownership diagram](imgs/ROS2Ownership.svg) | ||
|
||
![cactus-rt ROS2 publisher data flow](imgs/ROS2Publisher.svg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
find_package(std_msgs REQUIRED) | ||
|
||
add_executable(rt_ros2_publisher | ||
main.cc | ||
) | ||
|
||
target_link_libraries(rt_ros2_publisher | ||
PRIVATE | ||
cactus_rt | ||
) | ||
|
||
setup_cactus_rt_target_options(rt_ros2_publisher) | ||
|
||
ament_target_dependencies(rt_ros2_publisher | ||
PUBLIC | ||
std_msgs | ||
) | ||
|
||
install( | ||
TARGETS rt_ros2_publisher | ||
DESTINATION lib/${PROJECT_NAME} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#include <cactus_rt/ros2/app.h> | ||
#include <cactus_rt/rt.h> | ||
|
||
#include <chrono> | ||
#include <iostream> | ||
#include <memory> | ||
#include <std_msgs/msg/int64.hpp> | ||
#include <thread> | ||
|
||
using cactus_rt::CyclicThread; | ||
using cactus_rt::ros2::App; | ||
|
||
struct RealtimeData { | ||
int64_t data; | ||
|
||
explicit RealtimeData(int64_t d) : data(d) {} | ||
}; | ||
using RosData = std_msgs::msg::Int64; | ||
|
||
namespace { | ||
void RealtimeToROS2ConverterFunc(const RealtimeData& rt_data, RosData& ros_data) { | ||
// A bit of a silly example, but gets the point across. | ||
ros_data.data = rt_data.data; | ||
} | ||
} // namespace | ||
|
||
class RealtimeROS2PublisherThread : public CyclicThread, public cactus_rt::ros2::Ros2ThreadMixin { | ||
int64_t loop_counter_ = 0; | ||
std::shared_ptr<cactus_rt::ros2::Publisher<RealtimeData, RosData>> publisher_; | ||
|
||
static cactus_rt::CyclicThreadConfig CreateThreadConfig() { | ||
cactus_rt::CyclicThreadConfig thread_config; | ||
thread_config.period_ns = 1'000'000; | ||
thread_config.cpu_affinity = std::vector<size_t>{2}; | ||
thread_config.SetFifoScheduler(80); | ||
|
||
// thread_config.tracer_config.trace_sleep = true; | ||
thread_config.tracer_config.trace_wakeup_latency = true; | ||
return thread_config; | ||
} | ||
|
||
public: | ||
RealtimeROS2PublisherThread(const char* name) : CyclicThread(name, CreateThreadConfig()) {} | ||
|
||
void InitializeForRos2() override { | ||
publisher_ = ros2_adapter_->CreatePublisher<RealtimeData, RosData>("/hello", rclcpp::QoS(10), RealtimeToROS2ConverterFunc); | ||
} | ||
|
||
int64_t GetLoopCounter() const { | ||
return loop_counter_; | ||
} | ||
|
||
protected: | ||
bool Loop(int64_t /*now*/) noexcept final { | ||
loop_counter_++; | ||
if (loop_counter_ % 1000 == 0) { | ||
LOG_INFO(Logger(), "Loop {}", loop_counter_); | ||
|
||
const auto span = Tracer().WithSpan("Publish"); | ||
publisher_->Publish(loop_counter_); | ||
} | ||
return false; | ||
} | ||
}; | ||
|
||
int main(int argc, char* argv[]) { | ||
rclcpp::init(argc, argv); | ||
|
||
App app; | ||
app.StartTraceSession("build/data.perfetto"); | ||
|
||
auto thread = app.CreateROS2EnabledThread<RealtimeROS2PublisherThread>("RTROS2PublisherThread"); | ||
app.RegisterThread(thread); | ||
|
||
constexpr unsigned int time = 30; | ||
std::cout << "Testing RT loop for " << time << " seconds.\n"; | ||
|
||
app.Start(); | ||
|
||
std::this_thread::sleep_for(std::chrono::seconds(time)); | ||
|
||
app.RequestStop(); | ||
app.Join(); | ||
|
||
std::cout << "Number of loops executed: " << thread->GetLoopCounter() << "\n"; | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#ifndef CACTUS_RT_ROS2_APP_H_ | ||
#define CACTUS_RT_ROS2_APP_H_ | ||
#include <memory> | ||
#include <optional> | ||
#include <type_traits> | ||
|
||
#include "../app.h" | ||
#include "ros2_adapter.h" | ||
|
||
namespace cactus_rt::ros2 { | ||
|
||
class Ros2ThreadMixin { | ||
protected: | ||
std::shared_ptr<Ros2Adapter> ros2_adapter_; | ||
|
||
public: | ||
void SetRos2Adapter(std::shared_ptr<Ros2Adapter> ros2_adapter) { | ||
ros2_adapter_ = ros2_adapter; | ||
} | ||
|
||
virtual void InitializeForRos2() = 0; | ||
virtual ~Ros2ThreadMixin() = 0; | ||
}; | ||
|
||
class Ros2ExecutorThread : public cactus_rt::Thread, public cactus_rt::ros2::Ros2ThreadMixin { | ||
std::optional<rclcpp::executors::SingleThreadedExecutor> executor_; | ||
|
||
static cactus_rt::ThreadConfig CreateThreadConfig(); | ||
|
||
public: | ||
Ros2ExecutorThread(); | ||
|
||
void Run() override; | ||
|
||
void InitializeForRos2() override {} | ||
}; | ||
|
||
class App : public cactus_rt::App { | ||
std::shared_ptr<Ros2Adapter> ros2_adapter_; | ||
std::shared_ptr<Ros2ExecutorThread> ros2_executor_thread_; | ||
|
||
public: | ||
explicit App( | ||
std::string name = "RTROS2App", | ||
cactus_rt::AppConfig config = cactus_rt::AppConfig(), | ||
Ros2Adapter::Config ros2_adapter_config = Ros2Adapter::Config() | ||
); | ||
|
||
template <typename ThreadT, typename... Args> | ||
std::shared_ptr<ThreadT> CreateROS2EnabledThread(Args&&... args) { | ||
static_assert(std::is_base_of_v<Ros2ThreadMixin, ThreadT>, "Must derive ROS2 thread from Ros2ThreadMixin"); | ||
std::shared_ptr<ThreadT> thread = std::make_shared<ThreadT>(std::forward<Args>(args)...); | ||
|
||
thread->SetRos2Adapter(ros2_adapter_); | ||
thread->InitializeForRos2(); | ||
|
||
return thread; | ||
} | ||
|
||
void Start(int64_t start_monotonic_time_ns = -1) override; | ||
|
||
void RequestStop() override; | ||
|
||
void Join() override; | ||
}; | ||
|
||
} // namespace cactus_rt::ros2 | ||
#endif |
Oops, something went wrong.