차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판 이전 판
activity:public:2021:ros:7 [2021/11/09 15:06:05] – package.xml 수정 반영 davidactivity:public:2021:ros:7 [2021/11/09 17:22:38] (현재) – 최종수정 david
줄 1: 줄 1:
 +======ROS STUDY #7======
  
 +=====1. ROS 스터디 전반 복습=====
 +
 +====1.1. ROS, 노드의 집합체====
 +
 +===1.1.1 노드===
 +  * 각 노드는 특정한 역할을 맡은 독립적인 프로그램
 +  * 노드끼리 Topic, Service, Action 등을 이용하여 **데이터를 교환하면서 "큰 프로그램" 구성**
 +
 +===1.1.2 Topic===
 +  * 기본개념 [[https://youtu.be/RVn6YZZsEZs?t=188|스터디 #2]] 참조
 +  * **Publisher에서 데이터 단방향 송신**
 +  * Subsciber에서 데이터 수신
 +  * 활용법 [[activity:public:2021:ros:5._topic_programming#3. topic 퍼블리시|ROS STUDY #4 : ROS 기초프로그래밍(topic 퍼블리시)]] 참조
 +
 +===1.1.3 Service===
 +  * 기본개념 [[https://youtu.be/RVn6YZZsEZs?t=230|스터디 #2]] 참조
 +  * Client에서 Server로 데이터 요청
 +  * **요청을 받은 Server는 Client에게 응답(데이터 전송)**
 +  * 활용법 [[activity:public:2021:ros:5|ROS STUDY #5 : ROS 기초프로그래밍 2(service)]] 참조
 +
 +===1.1.4 Action===
 +  * 기본개념 [[https://youtu.be/RVn6YZZsEZs?t=291|스터디 #2]] 참조
 +  * Clinet에서 Server로 데이터 요청
 +  * 요청을 받은 Server는 Client애개
 +    * **작업 진행 중 상황을 지속적으로 송신(feedback)**
 +    * 중간에 Client에서 취소 요청이 있을 경우 실행 중단
 +    * 작업 완료 후 Client에게 최종 응답(result)
 +  * ROS 기본 타입이기는 하나, 실제로는 Service와 Topic 여러 개가 조합되어있는 조립체로, Action을 사용하기 위해서는 Topic과 Service 사용 가능한 상태여야 함(include 시 주의)
 +  * 간단하게 다루기에는 불필요하게 길어지는 코드가 많아 본 스터디에서는 비중있게 다루지 않았음
 +
 +===1.1.5. 노드 사이의 통신===
 +  * 노드 서로의 정체를 확인하고 통신을 시작하는데 필요한 중계소 역할은 **마스터 노드**(''roscore''로 실행되는 노드)가 담당
 +  * 한 로봇을 완성하기 위한 여러 노드들이 *반드시 한 컴퓨터에서 실행될 필요는 없음* - 네트워크 상에서 각 노드가 실행되고 있는 각 컴퓨터들이 서로를 *볼 수 있는(자유롭게 통신 가능한)* 상황이면 여러 디바이스를 통합 사용 가능
 +    * ''~/.bashrc'' 파일 내 IP 설정이 잘못된 경우, ROS 노드들이 마스터 노드에 접속하지 못해 오류가 발생
 +      * ''nano ~./bashrc'' 명령으로 ''~/.bashrc'' 내 ''ROS_MASTER_URI''에 설정된 IP 수정 후 터미널 재시작하거나 ''source ~/.bashrc'' 명령으로 업데이트
 +  * 활용예
 +    * 라즈베리파이3B를 얹은 터틀봇3과 명령/연산/roscore 실행하는 PC를 한 네트워크 안에서 함께 동작
 +    * 로봇 위에 얹은 저사양 컴퓨터는 모터 제어 노드만 실행, 이미지 분석 등 고성능 연산 필요한 것은 별도 고성능 컴퓨터에서 실행하여 연동
 +
 +====1.2. ROS 노드 실행과 관리====
 +  * 명령어 목록은 [[activity:public:2021:ros:2#4. ROS 명령어|ROS 명령어]] 참조
 +  * 각종 명령어 활용 예제는 [[activity:public:2021:ros:4|ROS STUDY #3: ROS 노드 간의 구조2, 터틀봇 시뮬레이션]] 참조
 +
 +====1.3. ROS 프로그래밍 절차====
 +  * 제작하는 패키지는 ''~/catkin/ws''에 저장, ''catkin_create_pkg''로 프로젝트 빠르게 생성
 +  * 해당 패키지에서 필요한 의존 패키지는 ''CMakeLists.txt'' 파일과 ''package.xml''파일에 명시해야 함
 +  * 토픽(''*.msg''), 서비스(''*.srv'') 파일을 작성하고 ''CMakeLists.txt'' 파일에 명시
 +    * 토픽 구성은 [[activity:public:2021:ros:5._topic_programming#3. topic 퍼블리시|ROS STUDY #4 : ROS 기초프로그래밍(topic 퍼블리시)]] 참조
 +    * 서비스 구성은 [[activity:public:2021:ros:5|ROS STUDY #5 : ROS 기초프로그래밍 2(service)]] 참조
 +  * 노드 소스코드는 프로젝트 ''src'' 폴더 아래에 저장
 +  * 여러 노드와 설정 파일을 담아 한 번에 간편 실행하려면, ''*.launch'' 파일을 프로젝트 ''launch'' 폴더 아래에 저장
 +  * ''catkin_make''로 빌드
 +
 +====1.4. 예제분석====
 +[[activity:public:2021:ros:6|ROS STUDY #6 : Topic 퍼블리시 실습]]에서 작성했던 코드 다시 한 번 깊게 분석하기
 +===1.4.1. ROS 환경 준비===
 +오랫동안 Ubuntu 환경을 사용하지 않았다면 각종 업데이트가 밀려있을 것이다. 우선 밀린 업데이트를 설치해주도록 하자.
 +<sxh bash title:일반적인 업데이트 방법>
 +$ sudo apt update
 +$ sudo apt upgrade
 +</sxh>
 +<sxh bash title:KAsimov의 우분투 설치방법을 따라 설치했었다면 다음 두 글자로도 가능>
 +$ au
 +</sxh>
 +
 +===1.4.2. 프로젝트 생성===
 +//**[[activity:public:2021:ros:6|ROS STUDY #6]]에서 했던 내용과 동일한 코드입니다**. 다만 프로젝트 생성 방법과 구조가 확실하게 기억나지 않는다면 다시 한 번 연습해보시기 바랍니다.//
 +<sxh bash title:패키지 생성>
 +$ catkin_create_pkg cmd_vel_pub message_generation roscpp geometry_msgs message_runtime
 +</sxh>
 +**''cmd_vel_pub''는 패키지 이름이다.** 만약 기존 패키지 이름과 겹치다면 새로 만들어보고, 이후 설정에서도 반영해 보도록 하자.  
 +이번 실습에서는 터미널 창보다 VSCode 상에서 한 번에 프로그래밍할 예정이다. 방금 만든 패키지를 폴더 째로 열자.
 +<sxh bash title:VSCode 폴더 열기>
 +$ code cmd_vel_pub
 +</sxh>
 +**마찬가지로, 패키지명이 ''cmd_vel_pub''이 아니라면 폴더명도 다를 것이므로 알맞게 수정하도록 하자.**  
 +또는, 여러 패키지를 동시에 작업하고 싶다면, VSCode에서 ''폴더열기 (Ctrl+K Ctrl+O)''를 아예 ''~/catkin_ws/src''로 지정하거나 터미널에서
 +<sxh bash title:VSCode catkin_ws/src 열기>
 +$ code ~/catkin_ws/src
 +</sxh>  
 +
 +VSCode 폴더가 제대로 열렸는지 확인한다.
 +
 +===1.4.3. 메시지 파일 추가===
 +  * VSCode 좌측 파일 목록에서 ''cmd_vel_pub'' 또는 자신이 지정한 패키지명 폴더 아래 ''msg'' 폴더를 생성하고, 그 안에 새 파일을 만든다.
 +<sxh cpp title:msg/cmd_vel_msg.msg>
 +geometry_msgs/Twist cmd_vel
 +</sxh>
 +**''cmd_vel_msg.msg''라는 파일은 임의로 지정해도 상관 없다. 다만, 내용 중 ''cmd_vel''은 다른 패키지에서도 참조할 이름이므로 다른 이름을 사용하면 작동하지 않는다.** ''cmd_vel_msg.msg'' 외에 다른 이름을 사용해보고, 이후 ''CMakeLists.txt'' 파일과 노드 소스코드에서도 해당 변경사항을 반영해보자.
 +
 +===1.4.4. Publisher 노드 추가===
 +  * VSCode 좌측 파일 목록에서 패키지 폴더 내 ''src'' 폴더 내 새 파일을 만든다.
 +<sxh cpp title:src/cmd_vel_pub.cpp>
 +#include "ros/ros.h"
 +#include "cmd_vel_pub/cmd_vel_msg.h"
 + 
 +#define PUB_NODE_NAME "cmd_vel"      // name of node
 +#define SUB_NODE_NAME "cmd_vel_sub"  // name of node
 +#define TOPIC_NAME "cmd_vel_topic"   // name of topic : cmd_vel_pub
 +
 +float vel_x, vel_y;
 + 
 +int main(int argc, char **argv){
 +  ros::init(argc, argv, PUB_NODE_NAME);
 +  ros::NodeHandle nh;
 +  geometry_msgs::Twist cmd_vel; // variable to publish
 + 
 +  ros::Publisher cmd_vel_publisher = nh.advertise<geometry_msgs::Twist>(TOPIC_NAME, 100, true);
 +  ros::Rate loop_rate(0.3);
 + 
 +  cmd_vel.linear.x = 0;
 +  cmd_vel.linear.y = 0;
 + 
 +  while (ros::ok()){
 +    std::cout << "Input velocity: " << std::endl;
 +    std::cin >> vel_x >> vel_y;
 + 
 +    float current_x = cmd_vel.linear.x;
 +    float current_y = cmd_vel.linear.y;
 +
 +    loop_rate.sleep();// Goes to sleep according to the loop rate defined above.
 +  }
 +  return 0;
 +}
 +</sxh>
 +
 +===1.4.5. Subscriber 노드 추가===
 +  * VSCode 좌측 파일 목록에서 패키지 폴더 내 ''src'' 폴더 내 새 파일을 만든다.
 +
 +<sxh cpp title:src/topic_subscriber.cpp>
 +#include "ros/ros.h"
 +#include "cmd_vel_pub/cmd_vel_msg.h"
 + 
 +#define PUB_NODE_NAME "cmd_vel"     // name of node
 +#define SUB_NODE_NAME "cmd_vel_sub" // name of node
 +#define TOPIC_NAME "cmd_vel_topic"  // name of topic : cmd_vel_pub
 + 
 +void messageCb(const geometry_msgs::Twist& cmd_vel){
 +    ROS_INFO("linear.x : %f\n", cmd_vel.linear.x);
 +    ROS_INFO("linear.y : %f\n", cmd_vel.linear.y);
 +    ROS_INFO("linear.z : %f\n", cmd_vel.linear.z);
 +    ROS_INFO("angular.x : %f\n", cmd_vel.angular.x);
 +    ROS_INFO("angular.y : %f\n", cmd_vel.angular.y);
 +    ROS_INFO("angular.z : %f\n", cmd_vel.angular.z);
 +}
 + 
 +int main(int argc, char **argv){
 +    ros::init(argc, argv, SUB_NODE_NAME);
 +    ros::NodeHandle nh;
 +
 +    ros::Subscriber cmd_vel_subscriber = nh.subscribe(TOPIC_NAME, 10, messageCb);
 +     
 +    ros::spin();
 + 
 +    return 0;
 +}
 +</sxh>
 +
 +===1.4.6. CMakeLists.txt 수정===
 +  * VSCode 좌측 파일 목록에서 패키지 폴더 내 해당 파일을 연다.
 +  * 수정사항
 +    * ''add_message_files''에 우리가 사용할 메시지 파일들을 등록한다.
 +    * ''generate_messages''를 활성화한다
 +    * ''catkin_package''를 활성화하고, dependent 패키지들을 등록한다.
 +    * 노드를 등록한다. 각 노드에 대해...
 +      * ''add_executable'' 등록
 +      * ''add_dependencies'' 등록
 +      * ''target_links_libraries'' 등록
 +
 +<sxh cpp title:CMakeLists.txt>
 +cmake_minimum_required(VERSION 3.0.2)
 +project(cmd_vel_pub)           # 패키지 이름과 동일, 이름과 다르면 빌드가 안된다.
 +
 +find_package(catkin REQUIRED COMPONENTS
 +  geometry_msgs
 +  message_generation
 +  message_runtime
 +  roscpp
 +)
 +
 +## Generate messages in the 'msg' folder
 +add_message_files(
 +  FILES
 +  cmd_vel_msg.msg           # 새로 만들 메세지 이름
 +)
 +
 +## Generate services in the 'srv' folder
 +# add_service_files(
 +#   FILES
 +#   Service1.srv
 +#   Service2.srv
 +# )
 +
 +## Generate actions in the 'action' folder
 +# add_action_files(
 +#   FILES
 +#   Action1.action
 +#   Action2.action
 +# )
 +
 +## Generate added messages and services with any dependencies listed here
 +generate_messages(            # 의존성
 +  DEPENDENCIES
 +  geometry_msgs
 +)
 +
 +##캐킨 패키지 옵션으로 라이브러리, 캐킨 빌드 위존성, 시스템 의존 패키지를 기술한다
 +catkin_package( 
 + INCLUDE_DIRS include
 + LIBRARIES cmd_vel_pub
 + CATKIN_DEPENDS geometry_msgs message_generation message_runtime roscpp
 + DEPENDS system_lib
 +)
 +
 +
 +include_directories(
 +# include
 +  ${catkin_INCLUDE_DIRS}
 +)
 +
 +##실행파일
 +
 +add_executable(cmd_vel_pub src/cmd_vel_pub.cpp)           # cmd_vel_pub:노드, cmd_vel_pub.cpp: 노드를 만들 때 참고해야할 소스코드
 +add_dependencies(cmd_vel_pub ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
 +target_link_libraries(cmd_vel_pub ${catkin_LIBRARIES})
 +  
 +add_executable(topic_subscriber src/topic_subscriber.cpp)           # topic_subscriber:노드, topic_subscriber.cpp: 노드를 만들 때 참고해야할 소스코드
 +add_dependencies(topic_subscriber ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
 +target_link_libraries(topic_subscriber ${catkin_LIBRARIES})
 +</sxh>
 +
 +===1.4.7. package.xml 수정===
 +  * VSCode 좌측 파일 목록에서 패키지 폴더 내 해당 파일을 연다.
 +  * 패키지 생성 시 거의 자동으로 설정해 준 상태이다. 다음을 수정한다:
 +    * ''build_depend'', ''build_export_depend'', ''exec_depend''를 모두 ''depend''로 변경하고, 중복된 항목을 삭제해준다.
 +      * 원래는 각 파트별로 따로 dependent 패키지를 지정해주어야 하나, 그 수가 많지 않고 dependent 관련 오류를 줄이기 위해 단순화하였다.
 +      * ''depend''는 ''build_depend'', ''build_export_depend'', ''exec_depend''를 모두 포함하는 태그이다.
 +      * ''catkin'' 패키지는 빌드 시 필요하므로 ''buildtool_depend''는 되도록 수정하지 않는다.
 +<sxh xml title:pacakge.xml>
 +<?xml version="1.0"?>
 +<package format="2">
 +  <name>cmd_vel_pub</name>
 +  <version>1.0.0</version>
 +  <description>The cmd_vel_pub package</description>
 +  <maintainer email="TODO">TODO</maintainer>
 +  <license>TODO</license>
 +
 +  <buildtool_depend>catkin</buildtool_depend>
 +  <depend>geometry_msgs</depend>
 +  <depend>message_generation</depend>
 +  <depend>roscpp</depend>
 +  <depend>message_runtime</depend>
 +
 +  <export>
 +  </export>
 +</package>
 +
 +</sxh>
 +===1.4.8. 실행 준비: 빌드===
 +우선, 작업한 파일 모두 저장되었는지 확인하고 빌드를 진행한다. 터미널은 VSCode에서 단축키 ''CTRL+`''로 띄워 이용하자.
 +<sxh bash title:빌드>
 +$ cd ~/catkin_ws
 +$ catkin_make
 +</sxh>
 +<sxh bash title:KAsimov 방식으로 우분투와 ROS를 설치했다면 다음 축약명령어를 이용할 수 있다.>
 +$ makeros
 +</sxh>
 +위의 일반 명령어와 축약명령어는 완전히 동일하다. 축약명령어를 사용하면 ''~/catkin_ws''로 매번 이동한 후에 명령을 입력할 필요가 없어 편리하다.
 +
 +===1.4.9. 실행===
 +  * VSCode 터미널 창을 여러 개로 분할한다. 여러 노드를 실행할 예정이다.
 +  * ''CTRL+SHIFT+P''를 눌러 VSCode 자체 명령 리스트를 띄우고, **''ros start''**라고 검색한다. ''ROS: start'' 항목을 선택하면 터미널 창을 경유하지 않고도 ''roscore''를 실행할 수 있다. 화면 아래 ROS1.melodic이라는 표시 앞 ❎표시가 ✅가 되었다면 VSCode에서도 정상 인식한 것이다.
 +    * 해당 표시가 없다면, VSCode에 ROS Extension이 설치되어있지 않은 것이다. 좌측 Extension 메뉴에서 ROS Extension을 설치하도록 하자.
 +==1.4.9.1. Subscriber 노드 실행==
 +<sxh bash title:Subscriber 노드 실행>
 +$ rosrun cmd_vel_pub topic_subscriber
 +</sxh>
 +토픽이 Publish될때까지 아무런 출력이 없는 것이 정상이다.
 +==1.4.9.1. Subscriber 노드 실행==
 +<sxh bash title:Publisher 노드 실행>
 +$ rosrun cmd_vel_pub cmd_vel_pub
 +Input velocity: 
 +</sxh>
 +차례대로 x 병진속도와 y 병진속도를 입력하면 해당 값대로 cmd_vel이 Publish되는 것을 subscriber 노드를 통해 확인할 수 있다.
 +===1.4.10. 응용===
 +  * ''cmd_vel''을 Publish하므로 다른 패키지의 노드를 활용할 수 있다.
 +    * 예) ''turtlesim/turtlesim_node''
 +      * 해당 노드의 경우 토픽 이름을 ''/turtle1/cmd_vel''로 맞춰 publish해주어야 ''turtlesim_node''에서 정상적으로 값을 subscribe한다. 노드 소스코드상에서 토픽 이름을 바꿔보자.
 +  * 다른 패키지의 노드에 원하는 값을 publish하면 모든 노드를 전부 직접 만들지 않아도 원하는 기능을 쉽게 구현할 수 있다. ROS의 효과적인 활용을 위해서는 토픽 publish-subscribe, 서비스 server-client 구조를 잘 익혀두자.