언제든지 Remind할 수 있게 기초적인 것만 압축해서 정리 하고자 한다
참고영상
https://www.youtube.com/watch?v=Twsi0XNSsnY&list=PLoc4bSmQajN-y88btKBK6lvAbrTtJDrYs
Ros의 정의
Robot Operating System : 로봇운영체제
- 로봇관련 프로세스를 실행/종료 혹은 관리하는 것이 가능하다
- 로봇 소프트웨어를 구축하는데 도움이 되는 라이브러리 (로봇 소프트웨어 제작툴)
- 모듈화가 쉽다(간단한 소스코드의 변화로 다양한 로봇에 적용이 가능하다)
- SLAM 및 Navigation 등 다양한 오픈소스를 제공해준다
Ros Node
Ros Node란 ROS에서 실행되는 단위 프로세스로서 소스코드를 작성하고 실행하면 그것이 노드이다
ROS Node 실행방법
- roscore 실행
- rosrun [패키지 이름] [실행파일 이름] 실행
roscore
컴퓨터의 전원을 켜듯이 ROS를 돌리고 싶으면 roscore를 켜야한다
rosrun
ROS Node를 실행하는 명령어
ex) turtlesim 패키지의 turtlesim_node를 실행
rosrun turtlesim turtlesim_node
//파란색 배경에 거북이가 나오는 노드 실행
rosrun turtlesim turtle_teleop_key
//방향키에 따라 거북이가 도는 노드 실행
ROS Node를 관리하는 명령어
실행 중인 Node 보기
rosnode list
Node 정보 보기
rosnode info [노드_이름]
Node 종료
rosnode kill [노드이름]
위에 예시로 이어서 작성을 해보면
roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key
각각 터미널 마다 위에 코드를 실행시키고
새 터미널을 열어서 실행중인 node를 살펴보면
kist@kist-MS-7D96:~$ rosnode list
/rosout
/teleop_turtle
/turtlesim
다음과 같고
/rosout : roscore 실행 시 기본으로 실행되는 node
/turtlesim : turtlesim_node 에서 실행되는 node
/teleop_turtle : turtle_teleop_key 에서 실행되는 node
이다
이중에 Node가 무엇을 Publish하고 Subscribe하고 있는지 보고 싶으면 (예시 : turtlesim)
rosnode info /turtlesim
위의 명령어로 확인가능하다
만약 이 node를 끄고 싶으면
rosnode kill /turtlesim
ROS 환경설정
1. 작업하고 싶은 곳에서 워크스페이스 폴더를 생성해주자 (보통 이름을 "catkin_ws" 로 만든다)
mkdir catkin_ws
2. Workspace폴더로 경로를 이동을 하여 src폴더를 만들어준다
mkdir src
3. src 폴더로 이동을 하여 ROS 패키지를 생성해주자
catkin_create_pkg [생성할 패키지 이름] [의존성패키지1] [의존성패키지2]...
예시
catkin_create_pkg basic_tutorial roscpp
4. 생성된 패키지의 경로로 접근
cd basic_tutorial
5. 생성된 패키지의 내부에 있는 src 폴더로 이동 후 cpp 파일을 생성하고 소스코드를 작성
cd src
nano basic.cpp
6. 예제 코드 작성
#include <ros/ros.h>
int main(int argc, char **argv)
{
ros::init(argc, argv, "basic_node");
ros::NodeHandle n;
ros::Rate loop_rate(60);
while (ros::ok())
{
ROS_INFO("Hello world!");
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
7. 소스코드를 컴파일하기 (CMakeLists.txt 수정)
ROS 패키지는 컴파일을 위해 CMake라는 도구를 사용한다
이를 위해서 CMakelists.txt 파일에 내가 작성한 파일의 정보를 등록하는 과정이 필요하다
(CMakeLists.txt는 이미 패키지를 만들 때 자동으로 생성되어 있다) -> catkin_ws / src / basic_tutorial
nano CMakeLists.txt
아래로 내리다 보면
이렇게 적힌 부분이 있는데 이 아래에 다가
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
add_executable(basic_node src/basic.cpp)
target_link_libraries(basic_node ${catkin_LIBRARIES})
와 같이 적어 주자
- add_executable([실행파일 이름] [소스코드 상대경로]) 예시 : add_executable(basic_node src/basic.cpp)
- 패키지의 상대 경로에 해당하는 소스코드의 컴파일 결과물을 basic_node라는 실행파일 이름으로 생성하겠다
- 여기서 적힌 실행파일의 이름은 rosrun 명령에서 " rosrun [패키지 이름] [실행파일 이름] " 에 [실행파일 이름]에 사용된다
- 팁: 실행파일의 이름을 소스코드에 ros::init에 정의한 node 이름과 동일하게 해야 헷갈리지 않는다
- target_link_libraries([실행파일 이름] ${실행파일에 링크될 라이브러리}) 예시 : arget_link_libraries(basic_node ${catkin_LIBRARIES})
- 실행 파일에 링크될 라이브러리를 지정
- ros를 사용한다면 일반적으로 ${catkin_LIBRARIES}를 사용한다
- 여기서 실행 파일의 이름은 위의 add_executable과 같도록 해야한다
8. Workspace의 경로로 이동 (catkin_ws) 후에 소스코드 컴파일
catkin_make
catkin_make는 반드시 워크스페이스 경로에서 입력을 해야한다
컴파일이 완료되면 결과물 build , devel 이 생성된다
하지만 이렇게 한다고 해서 이 터미널에서는 내가 만든 결과물을 인식할 수 없다
예를 들어 새로운 터미널을 열어서 roscore 해주고
이 터미널에서 rosrun basic 까지만 누르고 tab을 눌러도 자동완성되지 않는다
9. 컴파일된 결과물을 인식시켜주기
source devel/setup.bash
일반적으로 워크 스페이스 경로에서 devel/setup.bash를 이용하여 인식시켜준다
(source setup.bash는 터미널을 새로 열면 초기화 되는 휘발성 명령어이다)
이거 할 때마다 안하고 싶으면 ~/.bashrc 에 적어주면 된다 (단. bashrc를 건드리면 source ~/.bashrc 꼭 해야한다)
예시)
source ~/catkin_ws/devel/setup.bash
이러면 아래 실행에서
//새 터미널
roscore
//기존 터미널
rosrun basic_tutorial basic_node
rosrun basic까지만 입력하고 tab을 누르면 basic_tutorial이 자동완성 된다
이래도 자동완성이 안되면 ROS 패키지를 찾아주면 된다
rospack find [패키지 이름]
ex) rospack find basic_tutorial
10. 위에서 만든 실행파일 실행시키기
rosrun basic_tutorial basic_node
이렇게 실행 되고 있을 때 새로운 터미널을 열어서
rosnode list
다음을 입력하면 ros::init 에서 정의한 basic_node라는 이름으로 실행되고 있는 것을 확인할 수 있다
위에 보충설명
roscpp
ROS 사용을 위한 의존성 패키지는 roscpp 이다 (http://wiki.ros.org/roscpp)
roscpp is a C++ implementation of ROS. It provides a client library that enables C++ programmers to quickly interface with ROS Topics, Services, and Parameters
물론 파이썬을 위한 의존성 패키지 rospy도 존재한다(http://wiki.ros.org/rospy)
nano 편집툴
nano는 리눅스에 기본으로 설치되어 있는 편집툴이다
source devel/setup.bash
위 명령어는 ROS패키지 경로를 설정하는 환경설정 명령어이다
ROS패키지 경로를 설정해야지 rosrun 명령에서 패키지와 노드를 인식할 수 있기 때문이다
예제 코드 설명
//Ros라이브러리 사용을 위한 헤더파일
#include <ros/ros.h> //C나 C++에서 자주 사용하는 라이브러리도 들어있다
int main(int argc, char **argv) //이 매개변수의 의미는 찾아보기
{
ros::init(argc, argv, "basic_node");
ros::NodeHandle n;
ros::Rate loop_rate(60);
while (ros::ok())
{
ROS_INFO("Hello world!");
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
ros:: init
예제 : ros::init(argc, argv, "basic_node");
"basic_node" : rosnode list를 입력했을 때 나타나는 "노드의 이름"
ros::NodeHandle (https://enssionaut.com/board_robotics/942)
예제 : ros::NodeHandle n;`
Topic이나 Service Node등에서 사용 (위에 코드에서는 사용되지 않음) -> ros::spinOnce또한 마찬가지
소스 내에서 실제로 publisher 선언을 하는 부분은 ros::Nodehandle 클래스의 advertise()를 이용합니다. advertise()가 호출되면 마스터가 해당 토픽의 메시지를 subscribe하고자 하는 노드에게 그 토픽으로 publish하고자 하는 노드가 있음을 전달합니다. 그 이후에 publisher와 subscriber가 직접 연결됩니다. advertise()는 해당 토픽으로 publish 가능한 객체인 ros::Publisher 클래스를 반환하며 그 객체의 publish()를 이용하여 원하는 메시지를 발행할 수 있습니다
ros:: Rate
예제 : ros::Rate loop_rate(60);
노드가 몇 Hz로 동작할 것인지 정의를 해준다
(아래의 loop_rate.sleep()에 사용되면서 이떄 60Hz를 쉬어준다)
ros:: ok()
노드가 종료되었을 때 False, 나머지는 True
ros:: loop_rate.sleep()
무한 반복문에서 이 구문을 만나면 정의한 Hz가 될 때까지 기다렸다가 다음으로 넘어감
ros:: ROS_INFO()
일종의 Print 문이라고 생각할 수 있다
Ros 워크 스페이스 구조
Workspace : 위에서 catkin_ws 라고 만든 폴더를 워크스페이스라고 한다
이 워크 스페이스는 아래와 같은 구조를 가진다
즉 워크스페이스 아래 src 폴더가 있고
이 src 안에 여러 개의 패키지가 존재하며
이 패키지는 기본적으로 include, src, CMakeLists.txt, package.xml을 가진다
catkin_ws
├── build
├── devel
└── src
├── Package 1
├ └── CMakeLists.txt
├ └── src
├ └── include
├ └── package.xml
└── Package 2
여기서 build 와 devel은 위에서 workspace에서 catkin_make를 통해 컴파일을 하면 생기는 파일로
여기서 devel 폴더내에 결과물이 생긴다
실행파일 또한
devel / lib / 패키지명 /
에 실행파일이 저장이 된다
이걸 실행하고 싶으면
,/실행파일명 으로 실행할 수 있다
./basic_node
rosrun 명령과 동일한 기능을 하지만
이렇게 경로를 접근하는 것이 귀찮은 일이기 때문에
rosrun 명령은 실행파일을 쉽게 찾아 실행할 수 있도록 해준다
그러면 위에서 진행했던 Turtlesim(내장패키지)는 어디에 있을까?
ROS가 설치된 경로에 있다
ros의 설치경로는
/opt/ros/noetic
이다. 여기에 들어가 보면
이곳에 위와 같이 컴파일된 실행파일의 결과물 들이 저장된 곳은 lib 이며
여기에는 미리 컴파일된 결과물들이 있다
cd turtlesim
그에 대한 예시로 turtlesim 패키지에 접근해보면
초반에 사용하였던 turtlesim_node가 있다
source devel/setup.bash 로 Ros 패키지 경로를 따로 지정을 안해줬는데 어떻게 접근을 했을까?
nano ~/.bashrc
이때 사용된 파일은 bashrc 파일이다
bashrc
터미널이 실행될 때 자동으로 실행되는 스크립트 파일
우리가 처음 다운로드 받을 때 bashrc 에 다음 문장을 추가하라고 했었다
source /opt/ros/noetic/setup.bash
이 자체가 ROS가 설치된 경로( /opt/ros/noetic )를 가르키고 있고
이것을 통해 turtlesim을 통해 할 수 있다
만약 위의 문장을 추가하지 않는다면
turtlesim 뿐만 아니라 roscore도 돌아가지 않는다
추가로 . bashrc를 건드렸다면 아래의 명령어
source ~/.bashrc
를 꼭 실행해야한다
Ros 패키지 경로
현재 ROS 패키지 경로 확인하는 명령어
export |grep ROS
| 는 엔터 위에 있는 shift + \ 이다
여기서 ROS_PAKAGE_PATH를 확인할 수 있다
나는 두가지를 :를 통해 적었는데
/opt/ros/noetic/share
이거는 ROS가 설치된 경로
/home/kist/catkin_ws/src
이거는 내가 작업하던 workspace 의 경로이다 (직접 bashrc를 수정하였다)
신기한 것은 위에서 작업하던 practice_ros / catkin_ws 의 workspace로 와서
source devel/setup.bash
source setup.bash를 진행해 주고
다시 ROS_PACKAGE_PATH를 확인해주면
Package path가 한개 더 생긴다
이러면 다음 세개
- /home/kist/practice_ros/catkin_ws/src
- /home/kist/catkin_ws/src
- /opt/ros/noetic/share"
ROS가 설치된 경로의 패키지도 사용할 수 있고
내가 원래 작업하던 경로의 패키지도 사용할 수 있고
지금 새로 만든 경로의 패키지 모두 사용할 수 있다
그러면 다음과 같은 오해를 할 수 있는데
위의 그림과 같이 원래 있던거에 source setup.bash 를 통해 차례로 누적시키는 것이 아니라
컴파일을 진행하면
Workspace의 src 폴더 안에 CMakeLists.txt 가 패키지 폴더 옆에 있는 것을 볼 수 있다 (패키지 내부에 있는 CMakeLists.txt 아니다)
이 workspace/src/CMakeLists.txt 파일을 통해 setup.bash의 ROS 패키지 경로가 만들어 지는 것이다
즉, workspace/src/CMakeLists.txt (catkin_ws/src/CMakeLists.txt)는 현재 ROS 패키지 경로에 워크스페이스 경로를 추가하여 생성한다
만약 CMakeLists.txt 가 없다면 (아마도 컴파일을 진행하지 않아서 없는 경우가 대다수 이다)
catkin_init_workspace
를 통해 만들 수 있다 (컴파일 진행시 CMakeLists.txt가 없다면 자동으로 생성한다)
이를 응용하면 ROS 패키지 경로를 아래와 같이
/opt/ros/noetic/share:/home/kist/catkin_ws/src:/home/kist/catkin_ws2/src:/home/kist/catkin_ws3/src
/opt/ros/noetic/share
/home/kist/catkin_ws/src
/home/kist/catkin_ws2/src
/home/kist/catkin_ws3/src
이런 식으로 만들 수도있다
Ros Topic
ROS Topic은 ROS에서 Node와 Node 사이에 연속적으로 데이터를 주고 받을 수 있는 방법 중 하나이다
즉, 각각의 소스코드가 서로 데이터를 주고 받을 수 있는 방법이다
이런식으로
특정 노드에서 Topic 형태로 데이터를 뿌리면
다른 여러개의 노드에서 그 데이터를 받아서 처리하는 구조이다
Ros Topic 명령어
예시는 다음 코드를 진행
//Terminal 1
roscore
//Terminal 2
rosrun turtlesim turtlesim_node
//Terminal 3
rosrun turtlesim turtle_teleop_key
다음 3개의 node를 확인할 수 있는데
/rosout 는 roscore 실행하면 생기는 거고
/turtlesim 과 teleop_turtle node가 실행되고 있는 것을 볼 수 있고
거북이가 정상적으로 방향키를 통해 움직이는 것으로 보아 토픽을 통해 데이터를 주고 받고 있음을 알 수 있다
직관적인 이해를 위해 rqt_graph를 띄워보면
rqt_graph
그럼 어떤 Topic을 주고 받고 있을까?
Topic 리스트 보기
rostopic list
여기서 turtle1/cmd_vel 을 통해 거북이를 움직이게 한다
만약이 이 cmd_vel 에 대해 자세히 알고 싶으면
Topic 정보 보기
rostopic info [토픽_이름]
밑에 IP가 나와있는데 그냥 local에서 본인이 던지고 받고 하는 상황이다
발신자는 teleop_turtle 이고 수신자는 turtlesim 이다
추가로 Topic 의 타입이 조금 특이한걸 알 수 있는데
geometry_msgs/Twist
이는 ROS에서 기본으로 제공하는 Message 타입으로 (http://docs.ros.org/en/noetic/api/geometry_msgs/html/msg/Twist.html)

다음과 같은 구조를 가진다
Topic 데이터 확인
rostopic echo [토픽_이름]
다음과 같이 아래의 명령어를 입력하고
rostopic echo /turtle1/cmd_vel
teleop_turtle을 실행하고 있는 터미널로 가서 방향키를 움직여보면 (정보를 쏴준다)
이렇게 정보가 받아진다
Publisher Node
Publisher Node는 ROS에서 Topic을 발신하는 Node 이다
위에서의 같은 패키지가 아닌 Publisher Node를 위한 pkg를 다시만 들어 보면
catkin_ws / src 안에 basic_publish_tutorial이라는 패키지를 만들자
catkin_create_pkg basic_publish_tutorial roscpp
Publisher Node 작성방법
1. 패키지 하위 경로에 있는 CMakelists.txt의 find_package 수정
위 사진에 있는 CMakeLists.txt를 nano로 열어보면
find_package 부분에 Topic 사용을 위한 종속성 패키지 roscpp 가 이미 있다
여기에 사용한 메세지 패키지인 geometry_msgs 를 추가한다 (그때마다 다름)
2. package.xml 수정
이 패키지 내부를 보면 CMakeLists.txt 뿐만 아니라 package.xml 또한 있는데 이를 텍스트 에디터로 열어서
이 세 항목을 roscpp에서 위에서 추가한 CMakeLists.txt 의 find_package에 적은 종속성 패키지 이름 geometry_msgs를 아래와 같이 추가한다
<build_depend>roscpp</build_depend>
<build_depend>geometry_msgs</build_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>geometry_msgs</build_export_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>geometry_msgs</exec_depend>
3. Publisher Node 소스코드 작성
패키지의 src 경로에서 cpp 파일을 생성 (이름은 basic_publish.cpp로 지정)
4. 패키지의 CMakelists.txt의 add_executable, target_link_libraries를 추가
패키지안에 있는 CMakeLists.txt
를 열어서 다음 과 같이 추가해준다
add_executable(basic_publish_node src/basic_publish.cpp)
target_link_libraries(basic_publish_node ${catkin_LIBRARIES})
5. workspace(catkin_ws)까지 나와서 컴파일 후 setup bash source 해준다
catkin_make
source devel/setup.bash
6. roscore & rosrun
roscore
rosrun basic_publish_tutorial basic_punblish_node
이렇게 실행하면 출력이 없어서 멈춘 것 처럼 보이지만
rostopic list
rostopic info 확인할 토픽이름
위의 명령어로 토픽의 이름 및 정보를 확인 할 수 있다
어떤 값을 보내는지 확인하기 위해
rostopic echo 확인할 토픽이름
우리가 지정한 값을 잘 보내고 있다
예제 코드
//Ros라이브러리 사용을 위한 헤더파일
#include <ros/ros.h> //C나 C++에서 자주 사용하는 라이브러리도 들어있다
#include <geometry_msgs/Twist.h> //geometry_msgs 패키지에 Twist 메시지 타입을 사용
int main(int argc, char **argv) //이 매개변수의 의미는 찾아보기
{
ros::init(argc, argv, "basic_publish_node");
ros::NodeHandle n;
geometry_msgs::Twist cmd_vel;
//geometry_msgs::Twist 타입을 가지는 cmd_vel변수 선어
ros::Publisher publisher_cmd_vel = n.advertise<geometry_msgs::Twist>("cmd_vel", 1000);
ros::Rate loop_rate(60);
while (ros::ok())
{
//cmd_vel에 값을 할당
cmd_vel.linear.x = 10;
cmd_vel.angular.z = 10;
//
publisher_cmd_vel.publish(cmd_vel);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
코드 설명
Publisher 선언부
ros::Publisher publisher_cmd_vel = n.advertise<geometry_msgs::Twist>("cmd_vel", 1000)
Publisher의 선언은 NodeHandle n의 advertise를 통해 정의할 수 있다
ex) n.advertise<geometry_msgs::Twist>("cmd_vel", 1000) 이 부분
<> 안에는 어떤 메세지 타입을 사용할 것인지
("rostopic list를 입력할 때 나오는 topic 이름", 메세지 대기열의 크기)
geometry_msgs/Twist
위에 geometry_msgs/Twist 구조는 아래와 같다고 했는데
여기서 Vector 3 는
float64 x
float64 y
float64 z 이다
Publisher 호출부
publisher_cmd_vel.publish(cmd_vel);
위에서 선언한 ros::Publisher의 publish를 호출하면 ROS에 토픽이 인자에 전달된 메시지의 값(cmd_vel)을 publish 된다
-> 여기서 인자 의 값 cmd_vel 이 선언 될 때 geometry_msgs::Twist cmd_vel 사용된 타입과
publisher에 정의된 메세지 타입 ros::Publisher publisher_cmd_vel = n.advertise<geometry_msgs::Twist>("cmd_vel", 1000)
가 일치해야한다
<추가자료>
Publisher 와 Subscriber
https://enssionaut.com/board_robotics/942
Error shooting 1
만약
이런거 뜨면 소스코드에 이상 없는지 다시 확인하자
이게 정상적인 출력
Error shooting 2
만약 roscore를 띄우고 rosrun을 하는데
다음 과 같이 실행이 안될 때
먼저 패키지가 있는지 확인
잘 들어 있다
그러면 setup.bash를 안올려서 그렇다
위에 했던 예시를 들어보면
export |grep ROS
를 통해 패키지 경로를 볼 수 있고 이 경우
지금 작업하고 있는 워크스페이스 경로 즉 "/home/kist/practice_ros/catkin_ws/src" 가 없는 것을 확인할 수 있다
해결 방법 : setup.bash를 source 해주자
source devel/setup.bash
위에 명령어를 진행하면
rosrun basic 만 치고 tab 키 누르면 자동완성 된다
패키지 경로 제대로 올라가 있다
'Robotics > ROS' 카테고리의 다른 글
[Robotics] ROS 다운로드 및 환경 설정(+python 예제 코드) (0) | 2023.05.18 |
---|---|
[Robotics] Real sense 공부하는 자료들 + .ROS + 해야할거 + 질문 (0) | 2023.04.07 |
[Robotics] Depth camera 정보 python에 받아오기 (0) | 2023.04.07 |
[Robotics] Depth Camera Rviz 띄워보기 (0) | 2023.04.06 |
[Robotics] 기존 프로젝트 분석 (0) | 2023.04.05 |