본문 바로가기

KAIROS 2기

[카이로스 2기] ROS2 기초 : 시리얼 통신(ESP), URDF

이번에는 저번 포스팅에 이어, ROS를 활용한 시리얼 통신과 소켓 통신으로, ESP32와 ROS 간의 소통에 대한 부분과, 새로 배운 URDF에 대해 다루고자 한다.
간단히 순서는 아래와 같다. 🐫

1. ESP32 > ROS 간 Serial 통신
2. ROS > ESP32 간 통신(Webserver, Socket 통신), analog 제어
3. URDF 활용

 

1. ESP32 > ROS 간 Serial 통신

우선 ESP32 온습도센서에서 나온 온도, 습도 값을 ROS로 시리얼 통신으로 보낸 후, 받은 노드에서 또 Subscriber 노드로 Topic을 publish 하는 작업을 진행해보았다.
강사님께서 처음에는 아두이노로 작업해보라고 하셨는데, 아무래도 실습 환경이 가상환경(VirtualBox)을 사용하다 보니 연결 인식에 문제가 있었다. (포트가 안잡힘...) 그래서 ESP32로 하면 ESP 드라이버를 다운로드해야하는 불편이 있기는 했지만, 그래도 가능하였기 때문에 ESP32로 실습을 진행했다.
다만, 더 좋은 팁은! 💡 어차피 중요한건 ESP32에 물리적으로 코드를 업로드 하는 것이 중요하기 때문에 그 작업은 가상환경이 아니라 그냥 Windows 환경에서 해도 전혀 상관이 없다는 점! 그게 더 빠르고 훨씬 편했다.

 

우선 ESP에 올린 코드는 아래와 같다. (오랜만에 해본 온습도 배선..!)
- DHT11 라이브러리를 사용하여 온습도센서의 온도와 습도를 읽도록 했다.
- Serial 통신으로 보내줄때는 두 값이 쉼표로 구분된 하나의 문자열로 가도록 print문을 작성했다.⌨

#include <DHT11.h>
DHT11 dht11(18);

void setup()
{
    Serial.begin(115200);
}

void loop()
{
    int temperature = dht11.readTemperature();
    int humidity = dht11.readHumidity();
    
    Serial.print(temperature);
    Serial.print(",");
    Serial.println(humidity);
        
    delay(1000);
}

 
ESP에 코드가 잘 업로드되면, 온습도 결과는 esp가 계속 보내고 있는 상태로, 이제 ROS에서 publisher가 그걸 잘 받아오도록 하는 것이 그 다음 과제였다.
- subscriber 노드는 발행된 토픽을 받아오기만 하면 되니 이전 예제와 크게 다를 바 없다.
- publisher 노드에서 쉼표로 구분되어 넘어온 온습도 값을 str에서 float로 바꾸어 저장해주고, 인터페이스 생성한 msg에 각각 값을 저장하여 넘겨주었다. 이렇게 해야 문자열보다 다양한 가공을 할 수 있다.👸
- Serial 관련된 설정은 serial.Serial() 세팅 시 해주어야 한다. 사실 이후에도 계속 시리얼 관련 설정은 애를 많이 먹였는데.. 계속 똑같이 한 것 같아도 어떨때는 되고, 어떨때는 안되고.. 일단 여기서 사용한 설정은 아래와 같다.
- 가상환경에서 포트에 접근하는 권한문제가 있으면 sudo chmod 666 /dev/ttyUSB0

import rclpy
from rclpy.node import Node 
from interface_made.msg import Temp
import serial 

class MinimalPublisher(Node):
    def __init__(self):
        super().__init__('minimal_publisher')
        self.publisher_ = self.create_publisher(String, 'topic_serial', 10)
        self.ser = serial.Serial("/dev/ttyUSB0", baudrate = 115200, parity=serial.PARITY_NONE, 
                               stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, 
                               timeout=0.3)
        self.read_serial()

    def read_serial(self):
        while True:
            msg = Temp()
            line = self.ser.readline().decode('utf-8').strip()
            data = list(map(float, line.split(',')))
            if len(data) == 2:
            	temp, humi = data
                msg.temp = temp
                msg.humi = humi
            self.publisher_.publish(msg)

def main(args=None):
    rclpy.init(args=args)
    minimal_publisher = MinimalPublisher()
    rclpy.spin(minimal_publisher)
    minimal_publisher.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

 
🎀 최종 ROS 출력
- 오른쪽 publisher 노드에서 온습도 데이터를 보내면 왼쪽 subscriber 노드에서 float 값으로 나누어서 잘 표시되는 것을 확인할 수 있다. 완료!

 
2. ROS > ESP 간 통신(Webserver, Socket 통신), analog 제어

다음으로는 반대로, ROS에서 명령을 받아서 ESP에 연결된 모터를 돌리기를 진행했다.

이 경우에는 다양한 통신을 모두 사용해봤는데, 가장 익숙한 시리얼 통신부터, 웹서버 방식과 소켓 통신을 모두 해보았다.

그리고 ESP를 사용하기는김에, 작동된 값을 Wifi를 통해서 웹에 올리는 것까지도 오랜만에 해보고 싶어서 도전 완 🏹

최종 정리해보자면 아래와 같은 흐름이다.

- PUB --(Topic)--> SUB --(통신)--> ESP(motor) --(Wifi)--> Web

 

- 서비스 구조로 만들어서 서비스를 보낼때에 f(정방향), b(역방향), s(정지) 값을 넘겨주었다.

- subscriber에서 topic을 받으면 해당 값을 ESP에 통신으로 보내준다.

- 웹서버 방식에서 특이했던 것은 ESP가 자체 AP로서 동작한다는 점이었다! 그리고 확실히 웹처럼 get/post 방식을 사용하니 웹을 해본 나로서는 익숙해서 더 재밌었다.

- ESP는 받은 값에 따라 모터를 동작시키고, 각 방향으로 돌아간 시간만큼을 (millis 사용) wifi로 thinkspeak에 기록한다.

이에 따라 web에서 보이는 화면은 이렇게 그래프가 잘 찍히는 것을 볼 수 있다! 💯

(한 방향으로만 돌기 때문에 반대 방향으로 돌면 다른 방향 값은 0이 된다)

소켓통신으로는 더 나아가 모터의 속도를 아날로그 제어해보기로 했다.
- ROS에서 pub > sub으로 키보드 A/D를 누르른 것에 따라 10씩 증가하는 값을 전송했다.

- 이를 socket 통신으로 ESP 모터에 전달해서 받은 속도에 따라 모터 속도를 증가시켰다.

- (주의점) 속도를 100 이하로 시작하는 초기 동작을 위한 힘이 부족한지 삐 소리가 나며 동작하지 않았다. 😧 시작 값은 100 이상으로 하면 이후 속도를 내려도 잘 동작한다.

아래 동작 영상도 첨부하였다!

 


3. URDF 활용

마지막으로 URDF 파일과, 활용에 대해서도 배워보았다.
URDF란 unified robot description format으로 Rviz로 열수 있는 로봇 동작 구현을 위한 파일로, 일종의 시뮬레이션 같다.

HTML 파일처럼 열리는 태그 닫히는 태그로 구성되어서, 각 연결부에 대한 정의를 할 수 있어서 신기했다.🚀

확장자가 .urdf 파일이며, check_urdf 명령어로 잘 만들어졌는지를 아래와 같이 확인할 수 있다.

lauch.py 파일을 통해 model 값을 넣어주면 Rviz에서 아래 이미지처럼 이미지가 열린다.

👑 ubuntu@ubuntu-VirtualBox:~/robot_ws$ roslaunch urdf_tutorial display.launch.py model:=/home/ubuntu/robot_ws/src/myurdf.urdf

 

URDF를 통해서는 다양한 시뮬레이션이 가능했는데, 각 관절에 대한 이동을 GUI를 통해서도 제어할 수 있고, python 파일로 state publisher를 생성하여 특정 동작을 구동하고 있게도 할 수 있다.

가장 도움이 되었던 공식 사이트의 튜토리얼 링크를 함께 첨부하니 직접 해보는 것이 역시 가장 좋을 것 같다!

완료되면 아래와 같은 (인터스텔라같은) 로봇이 원을 그리며 걸어다닌다.👾
https://docs.ros.org/en/humble/Tutorials/Intermediate/URDF/Using-URDF-with-Robot-State-Publisher.html

 

 

ROS2 기초 2차 교육 후기 👀

- 통신은 정말 중요하고 어렵다! 하지만 여러 시스템 간 소통을 해야하는 프로젝트 상황에서는 절대 피할 수 없는 과제인데, 이번에 시리얼 통신, 웹서버 통신, 소켓 통신을 모두 시도해보며 자신감을 많이 쌓을 수 있었다.

- 이제 정말 교육의 막바지인데, 초반에 배웠던 아두이노, ESP가 다시 함께 다뤄지니 정말 로봇 프로그래밍 같은 기분이 들어서 즐거웠다. 타 시스템들로부터 받은 정보를 토대로 ROS publisher(or client)가 각 subscriber(or server) 노드에게 배분을 뿌리고 받아 관리하는 형태는 어떨까?

 

 

🌱 카이로스 2기에서 배운 ROS2 강의 1탄이 궁금하다면?

https://bagjo2884.tistory.com/27

 

[카이로스2기] ROS2 기초 : 드디어 만난 ROS를 배워보자

카이로스 2기 교육과정 중 다들 제일 기대가 컸던, 로봇을 개발한다면 가장 먼저 떠오르는 ROS!드디어 ROS와 SLAM까지 배워서, 기본 교육 과정은 거의 끝을 보이고 있다!😮이번주와 다음주 포스팅

bagjo2884.tistory.com

 

다음 시간에는 ROS 수업의 마지막! SLAM과 다른 기기들과의 연동까지 다뤄보겠습니다.😊