Phase 1 | ROS로 조명 및 공조 시스템 제어하기 |
rosserial로 아두이노에서 ROS 사용하기.
지금까지 ROS + roslibjs + Django 를 통해 ROS를 웹 환경에서 제어하는 데까지 성공했습니다. 이번에는 명령을 내리면, 실제로 그 작업을 수행하는 과정을 구현해보겠습니다. 아두이노에서 ROS를 Native로 사용하긴 어렵지만, rosserial을 이용하면 간단한 Publisher / Subscriber / Service / Action 등의 메시지 통신을 제한적으로 사용할 수 있습니다. 일단 이전 포스팅에서도 설명드렸겠지만, 다음의 명령어를 통해 rosserial을 설치합니다.
sudo apt-get install ros-melodic-rosserial
sudo apt-get install ros-melodic-rosserial-arduino
Arduino IDE 설치
여러가지 방법이 있겠지만, 가장 손쉬운 방법은 Ubuntu Software 앱 내에서 다운로드 받는 겁니다. 그냥 앱스토어에서 앱 다운로드 받듣 Arduino를 검색하고 설치하면 됩니다.
코드 작성
#include <ESP8266WiFi.h>
#include <ros.h>
#include <cranberry_topic/CommLight.h>
#define LIGHT_CODE 1 // LIGHT_CODE는 임의 지정
#define DHT_PIN D2
#define IR_PIN D3
#define RELAY1_PIN D4
#define RELAY2_PIN D5
#define MOTION_PIN D6
1. 필요한 파일을 include하고, 사용 용도에 따라 쓸 수 있도록 미리 define을 몇 가지 해줍니다. 추후 IR센서와, 릴레이를 2개 사용할 것, 모션센서까지 사용할 걸 감안해서 작성했습니다.
const char* ssid = "SSID";
const char* password = "Password";
IPAddress server(192, 168, 0, 122); //ROS가 실제로 작동하는 PC의 ip주소
const uint16_t serverPort = 11411; // ROS와 연결되는 포트 주소.
2. NodeMCU를 와이파이에 연결하기 위한 기본 세팅 과정입니다. 이때 ROS와 NodeMCU는 한 네트워크 상에 있어야 합니다.
//////////////ROS////////////////
ros::NodeHandle nh;
using cranberry_topic::CommLight;
// /comm_light 서버 콜백함수
void callback(const cranberry_topic::CommLight::Request &req, cranberry_topic::CommLight::Response &res){
if(req.target == LIGHT_CODE){
Serial.print("req is ");
Serial.println(req.target);
relayState = (long int)req.state;
digitalWrite(RELAY1_PIN, relayState);
res.result = relayState;
Serial.print("Req:");
Serial.print(req.target);
Serial.print("Res:");
Serial.println(relayState);
}
}
ros::ServiceServer<cranberry_topic::CommLight::target, cranberry_topic::CommLight::state> commLightServer("comm_light", &callback);
3. ROS 노드 핸들을 정의하고 콜백함수를 만듭니다. 구조는 대략 이전 포스팅에서 만들었던 comm_light_server.cpp 과 비슷합니다.
void setup()
{
//pinmode 설정
pinMode(RELAY1_PIN, OUTPUT);
// 시리얼 모니터 셋업
Serial.begin(115200);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
// wifi AP와 NodeMCU 연결
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// rosserial 소켓 서버와 연결 시도
nh.getHardware()->setConnection(server, serverPort);
nh.initNode();
// ip 얻어서 출력
Serial.print("IP = ");
Serial.println(nh.getHardware()->getLocalIP());
nh.advertiseService(commLightServer);
}
void loop()
{
if (nh.connected()) {
Serial.print("Connected.");
} else {
Serial.println("Not Connected");
}
nh.spinOnce();
delay(10); //100Hz 주기
}
4. setup, loop 함수를 설정합니다. AP와 연결이 되는대로 NodeMCU는 rosserial_server와의 연결을 시도합니다.
Done!
rosrun rosserial_python serial_node.py tcp
다음 명령어를 통해 NodeMCU가 ROS로 들어올 수 있도록 하는 길을 만들어줍니다. 이전 포스팅에서의 roslaunch rosbridge_server rosbridge_websocket.launch와 같은 역할입니다.
이제 NodeMCU에 업로드를 하고, 시리얼 모니터를 통해 상태를 확인해봅니다. /comm_light 서버와 제대로 통신하고 있으며, target이 1인 경우에 대해 웹에서 제어했을 때 시리얼모니터에 반응이 온다면 성공입니다.
긴 글 읽어주셔서 감사합니다. 도움이 되셨다면 왼쪽 아래 좋아요와, 광고 클릭 부탁드립니다.
고마움을 표현하는 가장 쉬운 방법입니다.