1) Her saniye yazı yazdırma. Eklediğim kod öncelikle Hello Cpp Node yazdıracak ardınca Hello ekleyecek.
benim .cpp dosyamın adı my_first_node.cpp
--------------------------------.cpp kısmına eklenecek kodlar-----------------------------
#include "rclcpp/rclcpp.hpp"
class MyNode: public rclcpp::Node
{
public:
MyNode(): Node("cpp_test"){
RCLCPP_INFO(this->get_logger(),"Hello Cpp Node");
timer_=this->create_wall_timer(std::chrono::seconds(1),
std::bind(&MyNode::timerCallback, this));
}
private:
void timerCallback()
{
RCLCPP_INFO(this->get_logger(), "Hello");
}
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<MyNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
------------------------------------CMAKELists.txt kısmına eklenecek kod---------------------------------------
cmake_minimum_required(VERSION 3.5)
project(my_cpp_pkg)
# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
add_executable(cpp_node src/my_first_node.cpp)
ament_target_dependencies(cpp_node rclcpp)
install (TARGETS
cpp_node
DESTINATION lib/${PROJECT_NAME}
)
ament_package()
--------------------------c_cpp_properties.json------------------------
eklenilen librarylerin olduğu kısım
{
"configurations": [
{
"browse": {
"databaseFilename": "",
"limitSymbolsToIncludedHeaders": true
},
"includePath": [
"/opt/ros/foxy/include/**",
"/usr/include/**"
],
"name": "ROS"
}
],
"version": 4
}
"bunları ekledikten sonra terminalden
~/ros2_ws$ colcon build --packages-select my_cpp_pkg
dosya uzantısına giderek build edin ve
ros2 run my_cpp_pkg cpp_node
çalıştararak kodunuzun çalışmasını görebilirsiniz.
+++Ek olarak gönderdiğiniz mesajları saydırmak istiyorsanız counter ekleyebilirsiniz
#include "rclcpp/rclcpp.hpp"
class MyNode: public rclcpp::Node
{
public:
MyNode(): Node("cpp_test"), counter_(0)
{
RCLCPP_INFO(this->get_logger(),"Hello Cpp Node");
timer_=this->create_wall_timer(std::chrono::seconds(1),
std::bind(&MyNode::timerCallback, this));
}
private:
void timerCallback()
{
counter_++;
RCLCPP_INFO(this->get_logger(), "Hello %d", counter_);
}
rclcpp::TimerBase::SharedPtr timer_;
int counter_;
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<MyNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
ros2 node list
ağınıza okunacak hangi mesajlar geliyor onu görmenizi sağlar
ros2 node info /cpp_test
mesajın içeriğini görebilirsiniz. biz şuan cpp_test bu mesajı gönderdiğimiz için bunu okuyabiliyoruz.
Dosyaları uzantısına gitmeden çalıştırmak için .bashrc dosyasına dosya yollarını kayıt etmemiz gerekiyor bu dosyayı bu şekilde görüntüleyebiliriz.
gedit ~/.bashrc
benim dosyamın içeriği bu şekilde
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
# ROS2
source /opt/ros/foxy/setup.bash
source ~/ros2_ws/install/setup.bash
source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash
#CUDA
export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
#Ros2
#export ROS_LOCALHOST_ONLY=1
Aynı yazılım farklı şekillerde kullanmak istiyorsanız bunu haberleşmede karmaşıklık yaşamamız adına farklı node isimleri vererek çözmeniz gerekir. İstemeden aynı node ismini kullanırsanız aşağıdaki komutta uyarı alırsınız.
ros2 node list
yine bir aşağıdaki komut ile cpp_node ismini değiştirebilir ve örneğin abc ismini verebilirsiniz. İki node da aynı kodu kullanarak çalıştırabilirsiniz
ros2 run my_cpp_pkg cpp_node --ros-args --remap __node:=abc
+++ colcon build --packages-select my_cpp_pkg --symlink-install
built etmek için aynı zamanda bu komutu da kullanabilirsiniz. Bu komutla sürekli değişkenleri otomatik built edecek siz teminali kapatana kadar yeni yazılımlarınızı doğrudan run ederek güncel verilerinizi görebileceksiniz. Ama bu sadece python da çalışıyor c++ da her seferinde compile etmek gerekiyor yani bu yazdığımız şekilde bizde sistem değişkenlik göstermeyecektir.
2) Turtelsim çalıştırma
Öncelikle turtelsim i indirelim
~$ sudo apt install ros-foxy-turtlesim
Simülasyonu çalıştıracağımız terminale bashrc yi sorcelayalım.
~$ source ~/.bashrc
Simülasyonu burdan çalıştırıyoruz.
~$ ros2 run turtlesim turtlesim_node
Klavye ile hareket komutu göndermek için
~$ ros2 run turtlesim turtle_teleop_key
Nodeların birbiri arasındaki iletişimi için
~$ rqt_graph
kullanabiliriz.
Node da kendi simülasyonunuza ayrı bir isim vermek istiyorsanız.
~$ ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
kullanarak isim verebilirsiniz. Burda verilen isim "my_turtle"
3) Publisher Subscriber Örneği
Öncelikle nodelarımızın içeriklerini paylaşalım
my_first_node.cpp
#include "rclcpp/rclcpp.hpp"
class MyNode: public rclcpp::Node
{
public:
MyNode(): Node("cpp_test"), counter_(0)
{
RCLCPP_INFO(this->get_logger(),"Hello Cpp Node");
timer_=this->create_wall_timer(std::chrono::seconds(1),
std::bind(&MyNode::timerCallback, this));
}
private:
void timerCallback()
{
counter_++;
RCLCPP_INFO(this->get_logger(), "Hello %d", counter_);
}
rclcpp::TimerBase::SharedPtr timer_;
int counter_;
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<MyNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
robot_news_station.cpp
#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/msg/string.hpp"
class RobotNewsStationNode : public rclcpp::Node
{
public:
RobotNewsStationNode() : Node("robot_news_station"), robot_name_("R2D2")
{
publisher_= this->create_publisher<example_interfaces::msg::String>("robot_news", 10);
timer_=this->create_wall_timer(std::chrono::milliseconds(500),
std::bind(&RobotNewsStationNode::publishNews, this));
RCLCPP_INFO(this->get_logger(), "Robot News Station has been started.");
}
private:
void publishNews()
{
auto msg = example_interfaces::msg::String();
msg.data=std::string("Hi, this is ") + robot_name_ + std::string("from the robot News Station");
publisher_ ->publish(msg);
}
std::string robot_name_;
rclcpp::Publisher<example_interfaces::msg::String>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<RobotNewsStationNode>(); //MODIFY NAME
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
smartphone.cpp
#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/msg/string.hpp"
class SmartphoneNode : public rclcpp::Node
{
public:
SmartphoneNode() : Node("smartphone")
{
subscriber_ = this->create_subscription<example_interfaces::msg::String>(
"robot_news", 10,
std::bind(&SmartphoneNode::callbackRobotNews, this, std::placeholders::_1));
RCLCPP_INFO(this->get_logger(), "Smartphone has been started.");
}
private:
void callbackRobotNews(const example_interfaces::msg::String::SharedPtr msg)
{
RCLCPP_INFO(this->get_logger(), "%s", msg->data.c_str());
}
rclcpp::Subscription<example_interfaces::msg::String>::SharedPtr subscriber_;
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<SmartphoneNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
pakcage.xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>my_cpp_pkg</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="caner.ezeroglu@isuzu.com.tr">isuzu</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>example_interfaces</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(my_cpp_pkg)
# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(example_interfaces REQUIRED)
add_executable(cpp_node src/my_first_node.cpp)
ament_target_dependencies(cpp_node rclcpp)
add_executable(robot_news_station src/robot_news_station.cpp)
ament_target_dependencies(robot_news_station rclcpp example_interfaces)
add_executable(smartphone src/smartphone.cpp)
ament_target_dependencies(smartphone rclcpp example_interfaces)
install (TARGETS
cpp_node
robot_news_station
smartphone
DESTINATION lib/${PROJECT_NAME}
)
ament_package()
Haberleşmenin sağlanacağı düğüm node unu çalıştıralım
ros2 run my_cpp_pkg robot_news_station
Mesajlaşmaya elverişli olan topic'leri görelim.
ros2 run my_cpp_pkg robot_news_station
node un etkin mesaj alanlarını görebilmek adına aşağıdaki komutu çalıştıralım
ros2 topic info /robot_news
Bu komutla sadece publisher aktif olduğunu gördük.
Echo komutu ile bir subscriber aktif hale getirebiliriz.
ros2 topic info /robot_news
Mesajın gönderme arayüzünün cinsini göstermak için aşağıdaki komut kullanılır.
ros2 interface show example_interfaces/msg/String
Mesajın gönderim sıklığını değiştirebilmek için
ros2 interface show example_interfaces/msg/String
Sistemdeki mesaj sayısını ölçmek amaçlı kullanılan komut ve aynı anda gönderilen mesaj gruplarının arasındaki süre farkını da buradan görülebilmesini sağlar.
ros2 topic bw / robot_news
Datalarınızı karmaşıklığın içinde takip edebilmek adına farklı ismilendirme verme yöntemlerini kullanabilirsiniz. Normal daha önce kayıtlı bir mesajın üstüne bu şekilde yeni bir mesaj publis edilebilir ama bu zamanlamalara uygun bir şekilde gerçekleşir yani iki mesaj da zamanına uygun şekilde mesajını gönderir ikisni de bu şekilde görmüş oluruz.
ros2 topic pub -r 10 /robot_news example_interfaces/msg/String "{data: 'hello from terminal'}"
Terminaldeki nodeları listeler
ros2 node list
Node un iiçndeki mesajları görmemizi sağlar.
ros2 node info /robot_news_station
4) Turtlesim Devamı
Turtlesim'i çalıştırdıktan sonra yayınlanmış node'ları listeleyelim.
ros2 node list
ros2 node'unun içindeki mesajları görebilmek adına terminale girilecek değer.
ros2 run turtlesim turtlesim_node
Açılan simülasyonda kaplumbağayı hareket ettirmek için kullandığımız komutun içerisinde yer alan mesajları bu şekilde görüntüleyebilirz.
ros2 node info /teleop_turtle
İçinde gönderilen nodeların içeriğini görüntüleyebiliriz.
ros2 node info /teleop_turtle
Şuan açık olan simülasyondaki nodeları listeleyebiliriz.
ros2 topic list
kaplumbağanın gittiği bölümlerin logunu almak için kulanılır.
ros2 topic echo /turtle1/cmd_vel