# 1. Ubuntu 18.04 이미지 다운로드
docker pull ubuntu:bionic
# 2. Ubuntu 이미지를 이용한 컨테이너 생성
docker run -it --name ros ubuntu:bionic
# 3. ROS 설치
apt-get update
apt-get install lsb -y --fix-missing # fix-missing option 을 넣어줄 것
# 4. 공식 페이지에 있는 코드 사용 (sudo를 모두 뺄 것)
sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
apt install curl
curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add -
apt update
apt install ros-melodic-desktop-full # 오래 걸리는 작업
# 5. 환경 셋업
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
source ~/.bashrc
# 6. 의존성 파일 설치 (python2)
apt install python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential
rosdep update
rosdep init
# 7. 매크로 설정
echo "alias cm='cd ~/catkin_ws && catkin_make'" >> ~/.bashrc
echo "eb='vim ~/.bashrc'" >> ~/.bashrc
echo "sb='source ~/.bashrc'" >> ~/.bashrc
# 8. 설치 완료 확인
roscore
# 컨테이너를 이미지로 변환
docker commit -a "commit name" {CONTAINER IR} {IMAGE NAME:TAG}
# image 저장 및 불러오기
docker save -o "file_name.tar" image_name
docker load -i tar file_name.tar
# container 저장 및 불러오기
docker export container_name > file_name.tar
docker import file_name.tar > - image_name
https://hub.docker.com/r/osrf/ros/tags?page=3
http://wiki.ros.org/ROS/Tutorials
ROS node: ROS에서 실행되는 하나의 실행 가능한 프로그램
package: ros를 구성하는 기본단위, ROS의 기본 프로그램은 패키지 단위로 개발되며 하나의 node 이거나 다른 패키지의 노드를 실행하기 한 프로그램으로 구성
catkin: ROS의 빌드시스템. CMakeList.txt라는 파일에 빌드 환경을 작성후 catkin_make 를 실행하면 flow 대로 생성이 됨
roscore: ROS 마스터를 구동하는 명령어. 각각의 패키지를 실행하기 전에 master를 실행해야 함.
rosrun: 하나의 node를 실행하는 명령어
roslaunch: roscore를 포함하여 여러 노드를 실행할 때 사용
package.xml: 패키지의 정보를 담은 파일로 패키지 이름, 저작자, 라인센스 등의 정보가 있는 파일
Topic: 단방향 송수신 방식으로 publish, subscribe 형태로 되어 있음
Service: 양방향 통신이나 일회성 메세지, 서비스의 요청과 응답이 완료되면 두 노드의 접속이 끊임
Action: 양방향이지만 통신을 계속 하는 방식
# Version check
printenv | grep ROS
# bsetup bash 실행
source /opt/ros/melodic/setup.bash
# 기본 명령어: rospackage 의 위치 확인
rospack find [rosnam_name]
# 기본 명령어: pkg 경로로 이동
roscd [package_name]
# creating a catkin package (패키지 만들기)
# catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
cd ~/catkin_ws/src
catkin_create_pkg **beginner_tutorials** std_msgs rospy roscpp
# building a catkin workspace and sourcing the setup file
# 생성된 package로 build 실행
cd ~/catkin_ws
catkin_make
# 환경 변수 추가
source ~/catkin_ws/devel/setup.bash
# package dependency 설정
rospack depends1 beginner_tutorials
# pkg dependency
roscd beginner_tutorials
# dependency가 패키지에 저장됨을 확인
cat pakcage.xml
rospack depends1 rospy
source /opt/ros/melodic/setup.bash # for melodic for instance
# catkin_make : CMake file의 flow 대로 빌드해주는 명령어
catkin_make [make_targets]
catkin_make --source my_src
catkin_make install --source my_src
# 1번 창에서 실행
roscore
# 2번 창에서 실행 => turtlesim
rosrun turtlesim turtlesim_node
# 3번 창에서 실행 => 거북이를 움직일 수 있게 됨
rosrun turtlesim turtle_teleop_key
# node와 topic간의 관계를 보여줌
$ rosrun rqt_graph rqt_graph
위 과정을 통해 tutlesim_node와 turtle_teleop_key node는 ros topic을 통해 communicating을 한다. tuetle_teleop_key는 key를 topic에 publishing하고, turtlesim 은 이를 subscribe하여 사용한다.
rostopic -h
rostopic echo [topic]
rostopic echo /turtle1/cmd_vel
rosservice list
rosservice type /clear
rosparam list
rosparam get /turtlesim/background_g
rosrun rqt_console rqt_console
rospack depends1 beginner_tutorials
roscd beginner_tutorials
cat package.xml
rospack depends1 rospy
rosed roscpp <tab><tab>
roscd beginner_tutorials
# msg 폴더 만들기
mkdir msg
echo "int64 num" > msg/Num.msg
# package.xml 에 아래 두 줄 삽입
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
# CMakeLists.txt 에 아래 두 줄 삽입
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
# 의존성 패키지 설치
carkin_create_pkg custom_msg_pkg std_msgs rospy roscpp
# 해당 패키지 폴더로 이동
cd /catkin_ws/src/custom_msg_pkg
# 하위 폴더에 아래의 두 *.msg 파일 생성 (스크립트 이용)
first_msg.msg
second_msg.msg
## first_msg.msg 의 내부
tims start_time
uint16 msg_seq
uint16 original_num
## second
time start_time
uint16 msg_seq
uint16 original_num
float32 square_num
float32 sqrt_num
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import rospy
import random
from custom_msg_pkg.msg import first_msg
def main():
rospy.init_node('start_node', anonymous=False)
pub = rospy.Publisher('first_topic', first_msg, queue_size=10)
rate = rospy.Rate(1) # 전송 속도 (1Hz)
msg = first_msg()
count = 1
while not rospy.is_shutdown():
msg.start_time = rospy.Time.now()
msg.msg_seq = count
msg.original_num = random.randrange(1,101)
# 터미널에 출력
rospy.loginfo("------")
rospy.loginfo("Start Time(sec): %d", msg.start_time.secs)
rospy.loginfo("Message Sequence: %d", msg.msg_seq)
rospy.loginfo("Original Number: %d", msg.original_num)
# 메시지를 퍼블리시
pub.publish(msg)
# 정해둔 주기(hz)만큼 일시중단
rate.sleep()
if __name__ == '__main__':
try:
main()
except rospy.ROSInterruptException:
pass
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import rospy # ROS 라이브러리
import random # 랜덤 수를 추출하기 위한 라이브러리
import math
from custom_msg_pkg.msg import first_msg, second_msg
# 서브스크라이브하는 first_msg.msg 파일과, 퍼블리시하는 second_msg.msg 파일 불러오기
class Calc:
def __init__(self):
rospy.Subscriber("/first_topic", first_msg, self.first_topic_callback)
self.pub = rospy.Publisher("/second_topic", second_msg, queue_size=10)
self.start_time = rospy.Time.now()
self.msg_seq = 0
self.original_num = 0
self.square_num = 0
self.sqrt_num = 0
# 퍼블리셔 노드로부터 토픽을 받아들이는 콜백 함수
def first_topic_callback(self, data):
self.start_time = data.start_time
self.msg_seq = data.msg_seq
self.original_num = data.original_num
self.square_num = math.pow(self.original_num, 2)
self.sqrt_num = math.sqrt(self.original_num)
# 받은 내용(data)를 터미널에 출력
rospy.loginfo("------")
rospy.loginfo("Message Sequence: %d", self.msg_seq)
rospy.loginfo("Original Number: %d", self.original_num)
rospy.loginfo("Square Number: %d", self.square_num)
rospy.loginfo("Square Root Number: %d", self.sqrt_num)
def second_msg_publish(self):
msg = second_msg() # 메시지 변수 선언
# 메시지 내용 담기
## start_time: start_node가 메시지를 생성해 publish 하는 시각
## msg_seq: 메시지 순서(번호)
## original_num: 계산의 대상이 될 수
## square_num: original_num의 제곱
## sqrt_num: original_num의 제곱근
msg.start_time = self.start_time
msg.msg_seq = self.msg_seq
msg.original_num = self.original_num
msg.square_num = self.square_num
msg.sqrt_num = self.sqrt_num
self.pub.publish(msg)
def main():
# 노드 초기화.
rospy.init_node('middle_node', anonymous=False)
rate = rospy.Rate(1)
calc = Calc()
while not rospy.is_shutdown():
calc.second_msg_publish()
rate.sleep()
if __name__ == '__main__':
try:
main()
except rospy.ROSInterruptException:
pass
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import rospy # ROS 라이브러리
from custom_msg_pkg.msg import second_msg # 서브스크라이브하는 second_msg.msg 파일 불러오기
# 퍼블리셔 노드로부터 토픽을 받아들이는 콜백 함수
def second_topic_callback(data):
# 받은 내용(data)를 터미널에 출력
rospy.loginfo("------")
rospy.loginfo("Processing Time(nsec): %d", rospy.Time.now().nsecs - data.start_time.nsecs)
rospy.loginfo("Message Sequence: %d", data.msg_seq)
rospy.loginfo("Original | Square | Square Root: %d | %d | %d", data.original_num, data.square_num, data.sqrt_num)
def main():
rospy.init_node('end_node', anonymous=False)
rospy.Subscriber("second_topic", second_msg, second_topic_callback)
rospy.spin()
if __name__ == '__main__':
main()
유익한 자료 감사합니다.