Ros ve Fake Turtlebot 3 Node kullanılarak Uygulama Örneği
Bu dokümanda ROS Kinetic sürümü ve Fake Turtlebot 3 kullanılarak harita üzerinde işaretlenen yerlere göre turtlebot 3 robotunun en yakın olduğu nesnenin ismini ve uzaklığını ekrana mesaj yazdıran bir uygulama geliştirilecektir. Önceden Gazebo ile hazırlanmış bir haritadaki nesnelerin konumlarının kayıt altına alınması gerekmektedir. Turtlebot 3 robotu Şekil 1’deki gibi nesnelere yaklaştığında önceden tanımlanmış nesne ismi ekrana yazdırılacaktır.
Şekil 1 Gazebo ile hazırlanmış bir haritada nesnelerin konumları
Bu dokümandaki adımları uygulamadan önce Ros Kinetic Kurulumu ve Turtlebot 3 Fake Node Uygulaması adımlarını tamamlamış olmanız gerekmektedir.
Aşağıdaki komutu Linux terminal ekranında çalıştırarak bilgisayarınıza Ros Kinetic ve Turtlebot 3 Fake node uygulamalarının eksiksiz yüklendiğinden emin olabilirsiniz. Gerçek bir turtlebot 3 robotuna gerek kalmadan daha önce tanınmlanmış bir dünya üzerinde çalışmalarımız gerçekleştirilecektir.
roslaunch turtlebot3_gazebo turtlebot3_world.launch
Eğer yukarıdaki komut çalıştırıldığında “environment variable ‘TURTLEBOT3_MODEL’ is not set” hatası alıyorsanız
Linux terminal penceresinde aşağıdaki komutu çalıştırmanız gerekmektedir. Fakat her yeni pencere açıldığında bu işlemin yapılması gerektiğinden eb kısayolu ile veya gedit .bashrc komutu ile .bashrc dosyasına aşağıdaki satırı eklemeniz tavsiye edilir. source .bashrc ile tekrar .bashrc komutlarını aktif hale getirebilirsiniz.
export TURTLEBOT3_MODEL=burger
Geliştirilecek uygulamanın çalışabilmesi için yukarıdaki komutun çalışır durumda kalması gerekmektedir.
Odometri Nedir ?
Odometri, zaman içindeki pozisyonu değiştirmek için hareket sensörlerinden gelen verilerin kullanılmasıdır. Bir başlangıç noktasına göre pozisyonlarını tahmin etmek için robotikte bazı bacaklı veya tekerlekli robotlar tarafından kullanılır. Bu yöntem, hız ölçümlerinin zamana göre konumlandırılması için zamana bağlı entegrasyona bağlı olarak hatalara duyarlıdır. Hızlı ve doğru veri toplama, cihaz kalibrasyonu ve işleme, çoğu durumda etkin bir şekilde kullanılması için gereklidir.
Ros Master çalıştığından emin olduktan sonra aşağıdaki komutlar Linux Terminal ekranından yazılarak topic listesi alınarak, odom topic ile ilgili bilgi alınabilir.
rostopic list rostopic info odom
Odom Topic nav_msgs/Odometry nav_msgs paketi içinde Odometry tipinde mesaj yayınladığı bilgisi görülmektedir. http://docs.ros.org/api/nav_msgs/html/msg/Odometry.html adresinde bu mesaj tipi ile ilgili bilgi bulunmaktadır.
Ros mesajları ile Linux Terminal ekranından da yardım alınabilmektedir. Bunun için rosmsg komutu kullanılmalıdır.
Ön Kabul : kullanıcının ev dizininde catkin_ws/src klasörünün olması gerekmektedir.
Geliştirilecek uygulama için catkin_ws çalışma uzayı (workspace) içinde yeni bir paket açılmalıdır. Paket ismi olarak robotun_konumu seçilmiştir. Bu paket için std_msgs , roscpp ve nav_msgs isimli bağımlılıklar gerekmektedir. Yeni bir paket aşağıdaki komut Linux Terminal ekranından girilerek açılır.
catkin_create_pkg robotun_konumu std_msgs roscpp nav_msgs
Açılan paket içerisinde robotun_konumu.cpp isimli dosyada ros c++ tutorial adresindeki başlangıç kodları ile başlanmalıdır.Fakat önce robotun konumunu odom topic’e abone olarak yayınlayan bir kod geliştirilecektir. Şekil 2’deki kod parçasını robotun_konumu.cpp isimli bir dosyaya kaydedip, derleyip çalıştırınız.
cd ~/catkin_ws/src/robotun_konumu/src gedit robotun_konumu.cpp &
#include "ros/ros.h" #include "nav_msgs/Odometry.h" void OdomCallback(const nav_msgs::Odometry::ConstPtr& msg){ double x=msg->pose.pose.position.x; double y=msg->pose.pose.position.y; ROS_INFO("x: %f, y: %f",x,y); } int main (int argc, char** argv){ ros::init(argc,argv,"robotun_konumu"); ros::NodeHandle nh; ros::Subscriber sub=nh.subscribe("odom",10,OdomCallback); ros::spin(); return 0; }
Şekil 2. Robotun konumunu ekrana yazdıran c++ kodu
Yazılan kodun derleme işleminin yapılabilmesi için CMakeLists.txt dosyasının içinde robotun_konumu.cpp dosyası ile ilgili değişikler yapılması gerekmektedir. src klasörü içindeki CMakeLists.txt dosyası bir metin düzenleyici ile açılır. Aşağıdaki satırların tamamını CMakeLists.txt dosyasının içeriği ile değiştirmeniz gerekmektedir.
cd ~/catkin_ws/src/robotun_konumu gedit CMakeLists.txt &
cmake_minimum_required(VERSION 2.8.3) project(robotun_konumu) find_package(catkin REQUIRED COMPONENTS nav_msgs roscpp std_msgs ) include_directories( ${catkin_INCLUDE_DIRS} ) add_executable(${PROJECT_NAME} src/robotun_konumu.cpp) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME robotun_konumu PREFIX "") add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES} )
Derleme işlemi için cm kısayolu çalıştırılabilir veya aşağıdaki komut çalıştırılmalıdır.
cd ~/catkin_ws && catkin_make
Derleme hatası verilmediyse geliştirilen uygulamanın çalıştırılması için aşağıdaki komut Linux terminal penceresinden çalıştırılmalıdır. robotun_konumu isimli paketin içinden robotun_konumu isimli düğüm çalıştırılmış oldu.
rosrun robotun_konumu robotun_konumu
Robotun konumu sürekli ekrana yazdırılacaktır. Robotun konumunu değiştirmek için teleop işlemi yapılabilir. Aşağıdaki komut ile teleop ekranından verilen komutlara göre turtlebot3 robotun konumu değiştirilebilmektedir.
roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch
Projenin 2. Aşaması
Ön Kabul: kullanıcının ev dizininde catkin_ws/src klasörünün olması gerekmektedir.
Geliştirilecek uygulama için catkin_ws çalışma uzayı (workspace) içinde yeni bir paket açılmalıdır. Paket ismi olarak location_monitor seçilmiştir. Bu paket için std_msgs ve roscpp bağımlılıkları tanımlanmıştır. Fakat nav_msgs isimli bağımlılık ise sonradan elle eklenecektir. Yeni bir paket aşağıdaki komut Linux Terminal ekranından girilerek açılır.
catkin_create_pkg location_monitor std_msgs roscpp
Açılan paket içerisinde location_monitor.cpp isimli dosyada ros c++ tutorial adresindeki başlangıç kodları ile başlanmalıdır.Fakat önce robotun konumunu odom topic’e abone olarak yayınlayan bir kod geliştirilecektir. Şekil 2’deki kod parçasını robotun_konumu.cpp isimli bir dosyaya kaydedip, derleyip çalıştırınız.
#include <vector> #include <string> #include <math.h> #include "ros/ros.h" #include "nav_msgs/Odometry.h" #include "location_monitor/LandmarkDistance.h" using std::vector; using std::string; using location_monitor::LandmarkDistance; class Landmark { public: Landmark(string name, double x, double y) : name(name), x(x), y(y) {} string name; double x; double y; }; class LandmarkMonitor { public: LandmarkMonitor(): landmarks_() { InitLandmarks(); } void odomCallback(const nav_msgs::Odometry::ConstPtr& msg) { double x = msg->pose.pose.position.x; double y = msg->pose.pose.position.y; LandmarkDistance ld = FindClosest(x, y); ROS_INFO("name: %s, distance: %f", ld.name.c_str(), ld.distance); } private: vector<Landmark> landmarks_; LandmarkDistance FindClosest(double x, double y) { LandmarkDistance result; result.distance = -1; for (size_t i = 0; i < landmarks_.size(); ++i) { const Landmark& landmark = landmarks_[i]; double xd = landmark.x - x; double yd = landmark.y - y; double distance = sqrt(xd*xd + yd*yd); if (result.distance < 0 || distance < result.distance) { result.name = landmark.name; result.distance = distance; } } return result; } void InitLandmarks() { landmarks_.push_back(Landmark("Engel1", 0.31, 0.31)); landmarks_.push_back(Landmark("Engel2", 0.31, 0.31)); landmarks_.push_back(Landmark("Engel3", 0.31, 0.31)); landmarks_.push_back(Landmark("Engel4", 0.31, 0.31)); } }; int main(int argc, char **argv) { ros::init(argc, argv, "location_monitor"); ros::NodeHandle n; LandmarkMonitor monitor; ros::Subscriber sub = n.subscribe("odom", 10, &LandmarkMonitor::odomCallback, &monitor); ros::spin(); return 0; }
Yazılan kodun derleme işleminin yapılabilmesi için CMakeLists.txt dosyasının içinde location_monitor.cpp dosyası ile ilgili değişikler yapılması gerekmektedir. src klasörü içindeki CMakeLists.txt dosyası bir metin düzenleyici ile açılır. Aşağıdaki satırların tamamını CMakeLists.txt dosyasının içeriği ile değiştirmeniz gerekmektedir.
cd catkin_ws/src/location_monitor/src gedit CMakeLists.txt &
Açılan CMakeLists.txt dosyasında aşağıdaki resimde görüldüğü gibi değişiklikler yapılması gerekmektedir.
CMakeList.txt dosyasının en son hali yukarıda verilen resimlerde olduğu gibi olması gerekir.
cmake_minimum_required(VERSION 2.8.3) project(location_monitor) find_package(catkin REQUIRED COMPONENTS roscpp std_msgs nav_msgs message_generation ) ## Generate messages in the 'msg' folder add_message_files( FILES LandmarkDistance.msg ) ## Generate added messages and services with any dependencies listed here generate_messages( DEPENDENCIES #std_msgs ) include_directories( # include ${catkin_INCLUDE_DIRS} ) ## Declare a C++ executable ## With catkin_make all packages are built within a single CMake context ## The recommended prefix ensures that target names across packages don't collide add_executable(${PROJECT_NAME}_node src/location_monitor.cpp) ## Add cmake target dependencies of the executable ## same as for the library above add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) ## Specify libraries to link a library or executable target against target_link_libraries(location_monitor_node ${catkin_LIBRARIES} )
package.xml dosyasında ise aşağıdaki değişikliklerin yapılması gerekmektedir :
Projenin bulunduğu lokasyonda msg adlı bir klasör oluşturulur ve bunun altında LandmarkDistance.msg adında bir belge açılır ve Resim ’de görülen kodlar girildikten sonra uygulamaya devam edilir.
mkdir msg cd msg gedit LandmarkDistance.msg
string name # Name of the landmark float64 distance # Distance to the landmark, in meters.
catkin_ws/devel/include/location_monitor içerisinde bulunan LandmarkDistance.h resim’de verildiği gibi düzenlenir.
cd catkin_ws/devel/include/location_monitor gedit LandmarkDistance.h
cd ~/catkin_ws catkin_make
rosrun location_monitor location_monitor_node
Geliştirilen node problemsiz olarak çalışmalıdır. Bundan sonraki adım olarak .launch dosyasında değişiklik yaparak turtlebot3_world.world dosyası yerine kendi world dosyanızı çalıştırmanız gerekmektedir. Ayrıca c++ kodundaki engel isimlerini ve konumlarını da güncelleyerek kodu derleyip tekrar çalıştırmanız gerekecektir.