no image
TCS3200 컬러 감지 센서 2
프로세싱 설치 필요 2022.08.30 - [Arduino] - 프로세싱 설치 (Install Processing) 스케치 총 2개 필요 = 아두이노 동작 스케치 + PC 동작 프로세싱 IDE 스케치 아두이노 동작 스케치 = 영점 조정 값설정, 주기적 색 감지, RGB 갑스올 바꾸고 시리얼 통신 통해 PC 전달 PC 동작 프로세싱 IDE 스케치 = 전달받은 데이터에서 3개 정수 값 분리해 실행 창 배경색으로 설정 아두이노 스케치 /* TCS230 Color Sensing 색 감지 & PC 전달 & Processing 스케치 배경색 예제 Calibrate 스케치로 얻어낸 영점 조정 데이터 사용 = 먼저 Calibrate 스케치 실행 */ #include #include // 연결된 핀 번호들: S0_OUT..
2022.08.29
no image
TCS3200 컬러 감지 센서 1
TCS3200 컬러 감지 센서 : RFG 감도 주파수 출력 센서 TCS230 업그레이드 버전, TCS3200 칩 탑재. S2, S3 = High / Low 로 포토다이오드 R, G, B 선택 → S0, S1 = 최대 출력 주파수 선택, 색상 판별. 이 과정 * 3번 = R, G, B 각 값을 읽은 후 조합 = 칼라값 감지. 메인칩 : TCS3200 전원 공급 : 3~5V 출력주파수 : 12KHz, 120KHz, 600KHz 선택 조명 : 화이트 LED 인터페이스 : TTL 마이컴직결 또는 주파수 카운터 감도최적거리 : 10mm 회로 센서 모드 선택 S0, S1 핀 = HIGH 공급 → 제일 높은 해상도 감지 모드 (=굳이 아두이노와 연결할 필요 없음) 전원 공급 2군데 (한 곳만 공급해도 동작) +5V ..
2022.08.29
no image
파일 확장자 변환 사이트 (무료)
https://convertio.co/kr/png-ico/ PNG ICO 변환 (온라인 무료) — Convertio png 파일(들) 업로드 컴퓨터, Google Drive, Dropbox, URL에서 선택하거나 이 페이지에서 드래그하여 선택해 주세요. convertio.co 바탕화면 아이콘 변경 시 사용 중 1일 10회 제한
2022.08.29
no image
로터리형 엔코더 모듈 (Encoder Sensor)
로터리형 엔코더 모듈 : 전기모터, 엔진 회전 각도 / 속도 측정 시 사용 노브를 수직으로 눌러 출력 값 변경 가능 축이 일정량 회전 시 펄스 발생, 펄스 수 세어 축 각도 측정 사용 예시) 마우스 휠, 스피커 볼륨, 전자 피아노 설정 조절 버튼, 자동차 노브 축 회전 = 핀 A, B가 공통 핀과 접촉 = 2개 디지털 신호 출력 신호 펄스 계산 = 두 출력 中 1개 만 사용 but 회전 방향 결정 위해 2개 고려 좌측 시계방향 초(동시)파 우측 반시계방향 파(동시)초 핀 구성 : CLK / DT / SW / VCC / GND 특징 : 회전부를 회전시켜 전기신호 발생, 360도 무한 회전 실습 예제 결선 회로도 GND = GND VCC = 5V SW = D4 DT = D3 CLK = D2 int LED_T..
2022.08.29
no image
ROS 초음파 센서 프로그래밍
● Sonar Sensors Gazebo 시뮬레이션 uptrasoni sensor 모델링 → 장애물 감지 ● sensor_msgs/Range.msg - 0일 때 = ULTRASOUND - 1일 때 = INFRARED - field_of_view = 각도 [rad] ex) 좌우 30º = 15[rad] - float32 min/max_range = 최소/대 측정범위 float32 형태 ultrasonic_array_sensor 다운 파일 위치 참고 sonar_msg_talker.cpp +) 수정 #include #include #include #include char frameid[] ="/sonar_ranger"; //frame name int main(int argc, char **argv) { ros..
2022.08.23
ROS
no image
ROS C++ 기초 3
rosrun my_second_pkg std_msgs_talker_node ROS 실행구조 ● launch - 일반 node 실행 ROS = node 단위 파일 실행 프로젝트 크기 ↑ = 노드 각각 실행 = 번거로움 - Launch 실행 한 번에 여러 node 실행 / 같은 node 여러 개 쓰기 가능 ● 작성 방법 - 파일명.launch launch 파일 작성하고자 하는 패키지 폴더에 생성 xml 태그 이용 - ROS launch 실행문 roslaunch 패키지명 파일명.launch roslaunch 패키지명 파일명.launch -screen(화면 실행 표시 옵션) - launch 작성 마우스 우클릭 - 새 파일 launch 생성 Geany 저장 (상단 저장 주소 유의) my_first_launch.l..
2022.08.21
ROS
no image
ROS C++ 기초 2
talker.cpp http://wiki.ros.org/std_msgs ros 메시지 타입 정보 사이트 std_msgs - ROS Wiki melodic noetic Show EOL distros: EOL distros: electric fuerte groovy hydro indigo jade kinetic lunar diamondback: Only showing information from the released package extracted on Unknown. No API documentation available. Please see this page for in wiki.ros.org talker.cpp 코드 설명 int main(int argc, char **argv) #Receive co..
2022.08.21
ROS
no image
ROS C++ 기초 1
Tip 복붙 = ctrl shift C/V ● 작업 공간 만들기 $ source /opt/ros/melodic/setup.sh $ mkdir -p ~/test_catkin_ws/src // -p = 하위 폴더까지 다 만듦 $ cd ~/test_catkin_ws/src // cd = 이동 $ catkin_init_workspace // scr 폴더에 CMakeLists.txt 파일 생성 =>폴더가 ROS 환경에 등록 ● Package & Node 만들기 $ catkin_create_pkg my_first_pkg std_msgs rospy roscpp my _first_pkg 패키지 생성 ● Geany 새 파일 생성 → http://wiki.ros.org/ROS/Tutorials/WritingPublishe..
2022.08.20
ROS
no image
ROS 기초 이론
ROS = 로봇 응용 프로그램 개발할 때 필요한 소프트웨어 제공 플랫폼 : 하드웨어 추상화 (같은 종류 하드웨어 공통 명령어 집합으로 묶는 것) & 하위 디바이스 제어 & 일반 사용 기능 구현 & 프로세스간 메시지 패싱 & 패키지 관리 & 개발 환경 필요한 라이브러리 & 다양한 개발 및 디버깅 도구 제공 장점 : 오픈 소스 = 누구나 사용 가능 목적 = 전 세계 레벨에서 공동작업가능한 환경 구축 (코드 재사용 극대화에 초점을 둠) 기능 ● 분산 프로세스 = 여러 노드 독립 실행, 노드 형태 프로그램이 분산 움직임 ● 패키지 단위 관리 = 여러 프로세스를 패키지 단위 관리 (배포, 공유, 수정) ● 공개 레파지토리 = Github 공개 & 라이센스 밝힘 ● API(application Programming..
2022.08.20
ROS

프로세싱 설치 필요

2022.08.30 - [Arduino] - 프로세싱 설치 (Install Processing)

스케치

총 2개 필요 = 아두이노 동작 스케치 +  PC 동작 프로세싱 IDE 스케치

아두이노 동작 스케치 = 영점 조정 값설정, 주기적 색 감지, RGB 갑스올 바꾸고 시리얼 통신 통해 PC 전달

PC 동작 프로세싱 IDE 스케치 = 전달받은 데이터에서 3개 정수 값 분리해 실행 창 배경색으로 설정


아두이노 스케치

/* 
  TCS230 Color Sensing 
   
  색 감지 & PC 전달 & Processing 스케치 배경색 예제 
   
  Calibrate 스케치로 얻어낸 영점 조정 데이터 사용 = 먼저 Calibrate 스케치 실행
   
*/ 

#include <MD_TCS230.h> 
#include <FreqCount.h> 
 
// 연결된 핀 번호들: S0_OUT <-> 8, S1_OUT <-> 9 
#define  S2_OUT  12 
#define  S3_OUT  11 
#define  LED     13  // HIGH = ENABLED 
 
// TCS230 객체인 CS 사용 핀 선언
MD_TCS230 CS(S2_OUT, S3_OUT, /* S0_OUT, S1_OUT, */ LED); 
 
// Calibrate 스케치 실행 얻은 영점 조정 데이터. 
// TCS3200 컬러 감지 센서 1 게시물에서 나온 본인 결과값 적어야함.

sensorData sdBlack = { 40, 50, 50 }; 
sensorData sdWhite = { 2640, 1370, 1980 }; 
 
// 전역 변수들: 
colorData rgb; 
 
void setup() 
{ 
  // 시리얼 포트 초기화 
  Serial.begin(115200); 
 
  // 컬러 센서 초기화 begin()
  // 영점 조정 위한 검정색, 흰색 값 설정 
  CS.begin(); 
  CS.setDarkCal(&sdBlack); 
  CS.setWhiteCal(&sdWhite); 
} 
 
void loop() 
{ 
  // 색 감지, RGB 값 읽기
  CS.read(); 
   
  // 읽을 데이터 준비 때까지 기다림
  while(!CS.available()) ; 
   
  // RGB 데이터 값 읽기
  CS.getRGB(&rgb); 
   
  // 쉼표 분리된 값 출력
  Serial.print(rgb.value[TCS230_RGB_R]); 
  Serial.print(","); 
  Serial.print(rgb.value[TCS230_RGB_G]); 
  Serial.print(","); 
  Serial.println(rgb.value[TCS230_RGB_B]); 
   
  delay(100); 
}

프로세싱 스케치

import processing.serial.*; 
 
int redValue = 0;        // Red 컬러 값 
int greenValue = 0;      // Green 컬러 값 
int blueValue = 0;       // Blue 컬러 값 
 
Serial myPort; 
 
void setup() { 
  size(200, 200); 
 
  // 사용 가능 모든 시리얼 포트 출력
  println(Serial.list()); 
 
  // PC 두번째 시리얼 포트가 아두이노와 연결된 시리얼 포트라 Serial.list()[2] 사용 
  // 다른 포트를 사용 시 그 포트 숫자 작성
  myPort = new Serial(this, Serial.list()[6], 115200); 
  // '\n' 받을 때까지 serialEvent() 발생 X 
  myPort.bufferUntil('\n'); 
} 
 
void draw() { 
  // 아두이노 RGB 데이터 배경색 설정
  background(redValue, greenValue, blueValue); 
} 
 
void serialEvent(Serial myPort) {  
  // 시리얼 포트 ~ 새 줄문자 = inString 문자열 받음 
  String inString = myPort.readStringUntil('\n'); 
 
  if (inString != null) { 
    // 문자열 있다면 앞 뒤 공백 문자 삭제
    inString = trim(inString); 
    // 쉼표 분리 integer 값 만듦 
    int[] colors = int(split(inString, ",")); 
    // 3개의 값 받으면 RGB 모든 값 받아 들인 것 
    // 각 redValue, greenValue, blueValue 넣고 콘솔 출력
     
    if (colors.length >=3) { 
      redValue = colors[0]; 
      greenValue = colors[1]; 
      blueValue = colors[2]; 
      System.out.println(String.format("RGB(%d, %d, %d)", redValue, greenValue, blueValue)); 
    } 
  } 
}

 

+) [ ] 안에 들어가야 할 숫자

 

 

아두이노와 연결된 포트 = COM6

COM6 = 위에서부터 2번째에 있음

[ ] 안에 2가 들어가면 됨

 


아두이노 업로드 → 프로세싱 업로드


결과

 

TCS3200 컬러 감지 센서

: RFG 감도 주파수 출력 센서
TCS230 업그레이드 버전, TCS3200 칩 탑재.

S2, S3 = High / Low 로 포토다이오드 R, G, B 선택 → S0, S1 = 최대 출력 주파수 선택, 색상 판별.

이 과정 * 3번 =  R, G, B 각 값을 읽은 후 조합 =  칼라값 감지.


  • 메인칩 : TCS3200
  • 전원 공급 : 3~5V
  • 출력주파수 : 12KHz, 120KHz, 600KHz 선택
  • 조명 : 화이트 LED
  • 인터페이스 : TTL 마이컴직결 또는 주파수 카운터
  • 감도최적거리 : 10mm

회로

센서 모드 선택 S0, S1 핀 = HIGH 공급 → 제일 높은 해상도 감지 모드 (=굳이 아두이노와 연결할 필요 없음)

전원 공급 2군데 (한 곳만 공급해도 동작)

+5V & GND 연결


S2 = D12

S3 = D11

LED = D13

OUT = D5 (출력 주파수를 측정 위해)

아두이노 우노 = D5번 핀 / 아두이노 메가 = 47번 핀

VCC = V5

GND = GND


라이브러리 설치

스케치 - 라이브러리 포함하기 - 라이브러리 관리 (Ctrl + Shift+ I)

 

MD_TCS230

 

 

FreqCount

 


스케치 (영점 조절)

/* 
  TCS230 sensor calibration (TCS230 센서 영점 조정) 
 
  영점 조정 진행, 영점 조정 위한 상수 값 = 시리얼 모니터 출력 
   
*/ 
#include <MD_TCS230.h> 
#include <FreqCount.h> 
 
#define BLACK_CAL 0 
#define WHITE_CAL 1 
 
// 연결된 핀 번호들: S0_OUT <-> 8, S1_OUT <-> 9
#define  S2_OUT  12 
#define  S3_OUT  11 
#define  LED     13  // HIGH = ENABLED 
 
MD_TCS230 CS(S2_OUT, S3_OUT, /* S0_OUT, S1_OUT, */ LED); 
 
sensorData sdBlack; 
sensorData sdWhite; 
 
void setup() 
{ 
  Serial.begin(9600); 
  Serial.print(F("\n[TCS230 영점 조정 예제]")); 
 
  // 컬러 센서 초기화 
  CS.begin(); 
} 
 
char getChar() 
// 시리얼 포트 문자 받아 대문자로 바꿔 리턴
{ 
  while (Serial.available() == 0); //0이 아니면 while문 벗어남
  return (toupper(Serial.read())); //toupper = 대문자 변경
} 
 
void clearInput() 
// 시리얼 포트 데이터 읽고 삭제 
{ 
  while (Serial.read() != -1); //-1이면 while문 벗어남
} 
 
void outputHeader(void) 
// 영점 조정 값+컬러 & RGB 감지 값 = 헤더 파일 사용, 시리얼 모니터 출력 
{ 
  Serial.print(F("\n\n// 영점 조정 데이터")); 
  Serial.print(F("\nsensorData sdBlack = { ")); 
  Serial.print(sdBlack.value[0]); Serial.print(F(", ")); 
  Serial.print(sdBlack.value[1]); Serial.print(F(", ")); 
  Serial.print(sdBlack.value[2]); Serial.print(F(" };")); 
 
  Serial.print(F("\nsensorData sdWhite = { ")); 
  Serial.print(sdWhite.value[0]); Serial.print(F(", ")); 
  Serial.print(sdWhite.value[1]); Serial.print(F(", ")); 
  Serial.print(sdWhite.value[2]); Serial.print(F(" };")); 
} 
 
uint8_t fsmReadValue(uint8_t state, uint8_t valType) 
//unitx_t = 문자가 아닌 숫자 담겠다, x=bit
{ 
  static uint8_t selChannel; 
  static uint8_t readCount; 
 
  switch (state) { 
    case 0: // Prompt for the user to start 
      Serial.print(F("\n\n값을 읽는 중: ")); 
      switch (valType) { 
        case BLACK_CAL: Serial.print(F("검정색 영점 조정")); break; 
        case WHITE_CAL: Serial.print(F("하얀색 영점 조정")); break; 
        default: Serial.print(F("??")); break; 
      } 
       
      clearInput(); 
 
      Serial.print(F("\n시작하려면 어떤 키든 눌러주세요 ...")); 
      getChar(); 
      clearInput(); 
       
      state++; 
      break; 
 
    case 1: // 센서 값 읽기 시작
      CS.read(); 
      state++; 
      break; 
 
    case 2: // 값 읽어 들일 때까지 기다림
      if (CS.available()) { 
        switch (valType) { 
          case BLACK_CAL: 
            CS.getRaw(&sdBlack); 
            CS.setDarkCal(&sdBlack); 
            break; 
 
          case WHITE_CAL: 
            CS.getRaw(&sdWhite); 
            CS.setWhiteCal(&sdWhite); 
            break; 
        } 
        state++; 
      } 
      break; 
 
    default: // reset fsm 
      state = 0; 
      break; 
  } 
  return (state); 
} 
 
void loop() 
{ 
  static uint8_t runState = 0; 
  static uint8_t readState = 0; 
 
  switch (runState) { 
    case 0: // 검정색 영점 조정 
      readState = fsmReadValue(readState, BLACK_CAL); 
      if (readState == 0) runState++; 
      break; 
 
    case 1: // 하얀색 영점 조정 
      readState = fsmReadValue(readState, WHITE_CAL); 
      if (readState == 0) runState++; 
      break; 
       
    case 2: // 헤더 파일 사용위해 시리얼 모니터 출력
      outputHeader(); 
      runState++; 
      break; 
 
    default:    // 잘못되었다면 다시 시작 
      runState = 0;  
  } 
}​

시리얼 모니터 결과값

 

검정색 대고 영점 조정

그 다음 흰색을 대고 영점 조정

 

 

https://m.blog.naver.com/msyang59/220161793024

 

색 감지 센서 TCS3200 모듈을 붙이다 - 1

아두이노 보드에 컬러(색)를 감지하여 감지한 컬러에 따라 각기 다른 주파수를 갖는 파형(波形)으로 변환하...

blog.naver.com

참고사이트

https://convertio.co/kr/png-ico/

 

PNG ICO 변환 (온라인 무료) — Convertio

png 파일(들) 업로드 컴퓨터, Google Drive, Dropbox, URL에서 선택하거나 이 페이지에서 드래그하여 선택해 주세요.

convertio.co

 

바탕화면 아이콘 변경 시 사용 중

1일 10회 제한

로터리형 엔코더 모듈

:  전기모터, 엔진 회전 각도 / 속도 측정 시 사용

노브를 수직으로 눌러 출력 값 변경 가능

축이 일정량 회전 시 펄스 발생, 펄스 수 세어 축 각도 측정

사용 예시) 마우스 휠, 스피커 볼륨, 전자 피아노 설정 조절 버튼, 자동차 노브

축 회전 = 핀 A, B가 공통 핀과 접촉 = 2개 디지털 신호 출력

신호 펄스 계산 = 두 출력 中 1개 만 사용 but 회전 방향 결정 위해 2개 고려

좌측 시계방향 (동시)파

우측 반시계방향 (동시)초 

 


핀 구성 : CLK / DT / SW / VCC / GND

특징 : 회전부를 회전시켜 전기신호 발생, 360도 무한 회전


실습 예제

결선 회로도

GND = GND

VCC = 5V

SW = D4

DT = D3

CLK = D2 

int LED_T = 10;     // 위 LED
int LED_B = 9;      // 아래 LED
 
int CLK = 2;        // CLK
int DT = 3;         // DT
int SW = 4;         // SW
 
static int oldCLK = LOW;  // CLK 값 저장 변수
static int oldDT = LOW;   // DT 값 저장 변수
 
int brightness = 143;    // LED 밝기 값(=중간(0~255))
int location = 0;        // 켜진 LED 위치 저장 변수 (0(=위) 초기화)
 
void setup() {
  pinMode(CLK, INPUT_PULLUP); // 내장 풀업 저항 사용하는 입력
  pinMode(DT, INPUT_PULLUP); 
  pinMode(SW, INPUT_PULLUP);  

  pinMode(LED_T, OUTPUT);
  pinMode(LED_B, OUTPUT);
}
 
void loop() {
  if (digitalRead(SW) == LOW) { // 노브 눌렸을 때
    changeLED();                // changeLED 함수 호출, LED 켜기
    location++;                 // LED 위치 바꾸기
    delay(300);                 // 중복 입력 방지
  }
  
  else {                              // 노브 돌렸을 때
    brightness += (getDirection()*5); // 밝기 조절
    if(brightness < 0)                // LED 밝기 최솟값(0)이하 떨어지는 것 방지
      brightness = 0;
    if(brightness > 255)              // LED 밝기 최댓값(255)이상 올라가는 것 방지
      brightness = 255;
    changeLED();                      // 변화한 밝기값 적용
  }
}
 
//방향 반환 함수
int getDirection() {
  int direct = 0;                 // 방향 초기화
  int newCLK = digitalRead(CLK);  // 현재 CLK 값 저장 변수
  int newDT = digitalRead(DT);    // 현재 DT 값 저장 변수
  
  if (newCLK != oldCLK) {         // CLK 값 변한 경우
    if (oldCLK == LOW) {          // LOW에서 HIGH 경우
      direct = oldDT * 2 - 1;     // direct 값 변경 
    }
  }
  
  oldCLK = newCLK;  // 갱신
  oldDT = newDT;
  
  return direct; // 시계방향 = -1, 반시계방향 = +1 반환
} 
 
// LED 위치 조절 함수
void changeLED() {
  if(location%2 == 1) {               // 변수를 2로 나눈 나머지 = 1
    analogWrite(LED_T, brightness);   // 위 LED만 ON
    analogWrite(LED_B, LOW);          
  }
  else {                              // 나머지 = 0
    analogWrite(LED_T, LOW);          
    analogWrite(LED_B, brightness);   // 아래 LED만 ON
  }
}

실행 결과

 

'Arduino' 카테고리의 다른 글

TCS3200 컬러 감지 센서 2  (0) 2022.08.29
TCS3200 컬러 감지 센서 1  (0) 2022.08.29
피에조 부저  (0) 2022.08.19
리드 스위치 모듈 KY-025 (Dry Reed Switch Sensor)  (0) 2022.08.19
적외선 PIR센서 (인체 감지 모션 센서)  (0) 2022.08.19

● Sonar Sensors

Gazebo 시뮬레이션

uptrasoni sensor 모델링 → 장애물 감지


● sensor_msgs/Range.msg

- 0일 때 = ULTRASOUND

- 1일 때 = INFRARED

- field_of_view = 각도 [rad]

    ex) 좌우 30º = 15[rad]

- float32 min/max_range = 최소/대 측정범위 float32 형태


ultrasonic_array_sensor 다운

파일 위치 참고


sonar_msg_talker.cpp +) 수정

#include <ros/ros.h>
#include <ros/xmlrpc_manager.h>
#include <sensor_msgs/Range.h>
#include <sstream>

char frameid[] ="/sonar_ranger";
//frame name

int main(int argc, char **argv)
{
  ros::init(argc, argv, "Sonar_range_test_pub");
 //Sonar_range_test_pub = node name

  ros::NodeHandle n;
   
  sensor_msgs::Range sonar_msg;
//sonar_msg라는 변수
  
  ros::Publisher pub_sonar1 = n.advertise<sensor_msgs::Range>("/RangeSonar1",1000);

  
  ros::Rate loop_rate(2);
   
  std::cout<<ros::XMLRPCManager::instance()->getServerURI()<<std::endl;
  
  sonar_msg.header.frame_id =  frameid;
  sonar_msg.radiation_type = sensor_msgs::Range::ULTRASOUND;
  sonar_msg.field_of_view = (float)(10.0/180.0) * 3.14;
  sonar_msg.min_range = 0.0;
  sonar_msg.max_range = 3.0; //[m]
  sonar_msg.range = -1.0;

  int count = 0;
  srand(time(NULL)); // random function initilizaition

  while (ros::ok())
  {

    sonar_msg.header.stamp = ros::Time::now();    
    sonar_msg.range = (double)(rand()%30+1)/10;
    ROS_INFO("Sonar range =[%6.3lf]", sonar_msg.range);
    pub_sonar1.publish(sonar_msg);

    ros::spinOnce();
    loop_rate.sleep();
    ++count;
  }

  return 0;
}

터미널

ctw
ctm

결과


roscore

다른 터미널

ctw
rospack list

ultra_sonar_test 등록 확인

rosrun ultra_sonar_test ultra_sonar_test_node

새 터미널

ctw
rostopic list
rostopic echo /RangeSonal1
//rostopic echo /이름

새 터미널

rostopic info /RangeSonar1
//rostopic info /이름

새 터미널

rqt_graph

rqt_graph 창 끔

rqt

Plugins - Topics - Topic Monitor

Topic & Type 정보가 나옴

Topic Monitor 창 끔

rviz

Add(좌측 하단) - By topic - Range

By dispaly type - Range -OK

좌측 Topic - /Rangeonar1

파일 test_catkin_ws/src/ultrasonic_array/sensor/src

frame name 찾기

frame name = /sonar_ranger

'ROS' 카테고리의 다른 글

초음파 센서를 이용한 AEB 구현 1  (0) 2022.09.12
Gazebo 시뮬레이션 구동  (0) 2022.09.06
ROS C++ 기초 3  (0) 2022.08.21
ROS C++ 기초 2  (0) 2022.08.21
ROS C++ 기초 1  (0) 2022.08.20

ROS C++ 기초 3

exp()
|2022. 8. 21. 19:11
rosrun my_second_pkg std_msgs_talker_node

ROS 실행구조

 

 

● launch

- 일반 node 실행

     ROS = node 단위 파일 실행

     프로젝트 크기 ↑ = 노드 각각 실행 = 번거로움

- Launch 실행

    한 번에 여러 node 실행 / 같은 node 여러 개 쓰기 가능

 

● 작성 방법

 

- 파일명.launch

    launch 파일 작성하고자 하는 패키지 폴더에 생성

    xml 태그 이용

 

<launch> 
<node pkg=“패키지 명” type=“실행 노드명(노드이름, 설정 노드)”name=“실행노드 부를 이름(실행명, rqt_graph 표시될 노드명)”/> 
</launch>

 

- ROS launch 실행문

    roslaunch 패키지명 파일명.launch

    roslaunch 패키지명 파일명.launch -screen(화면 실행 표시 옵션)

 

- launch 작성 

마우스 우클릭 - 새 파일 launch 생성

 

 

Geany

 

<launch>

<node pkg=“my_first_pkg” type=“talker_node" name="talker_node1” output="screen"/> 
<node pkg=“my_first_pkg” type=“listener_node" name="listener_node1” output="screen"/> 

</launch>

 

저장 (상단 저장 주소 유의) my_first_launch.launch

 

이름 수정 필요

 

터미널

 

ctw
roslaunch my_first_pkg my_first_launch.launch

 

if) output 부분을 지우면?

 

 

아무것도 나타나지 않음

 

-scr 스크린 옵션 사용시

 

 

= 복수 node 이용 가능한 launch

 


다양한 변수 사용할 my_second_pkg 제작

 

https://github.com/ros-industrial/cros/tree/master/resources/cros_testbed/src

예제 프로그램 참고

 

 

std_msgs_talker.cpp 클릭

 

 

1000 = 크기 정한 것

why? 임베디드 시스템은 용량이 넉넉하지 않기 때문에 최적화 하는 것

 

std_msgs_talker.cpp 전체 복사

 

터미널 - src에 my_second_pkg 생성

 

catkin_create_pkg my_second_pkg std_msgs rospy roscpp

 

주소 확인

 

Geany - std_msgs_talker.cpp 붙여넣기

 

#include <ros/ros.h>
#include <ros/xmlrpc_manager.h>
#include <std_msgs/Bool.h>
#include <std_msgs/Byte.h>
#include <std_msgs/Char.h>
#include <std_msgs/Duration.h>
#include <std_msgs/Header.h>
#include <std_msgs/Int16.h>
#include <std_msgs/Int32.h>
#include <std_msgs/Int64.h>
#include <std_msgs/Int8.h>
#include <std_msgs/Time.h>
#include <std_msgs/UInt16.h>
#include <std_msgs/UInt32.h>
#include <std_msgs/UInt64.h>
#include <std_msgs/UInt8.h>
#include <std_msgs/Float32.h>
#include <std_msgs/Float64.h>

#include <sstream>

int main(int argc, char **argv)
{
  ros::init(argc, argv, "std_msgs_talker");
  ros::NodeHandle n;
  ros::Publisher chatter1 = n.advertise<std_msgs::Bool>("bool", 1000);
  ros::Publisher chatter2 = n.advertise<std_msgs::Byte>("byte", 1000);
  ros::Publisher chatter3 = n.advertise<std_msgs::Char>("char", 1000);
  ros::Publisher chatter4 = n.advertise<std_msgs::Duration>("duration", 1000);
  ros::Publisher chatter5 = n.advertise<std_msgs::Header>("header", 1000);
  ros::Publisher chatter6 = n.advertise<std_msgs::Int16>("int16", 1000);
  ros::Publisher chatter7 = n.advertise<std_msgs::Int32>("int32", 1000);
  ros::Publisher chatter8 = n.advertise<std_msgs::Int64>("int64", 1000);
  ros::Publisher chatter9 = n.advertise<std_msgs::Int8>("int8", 1000);
  ros::Publisher chatter10 = n.advertise<std_msgs::Time>("time", 1000);
  ros::Publisher chatter11 = n.advertise<std_msgs::UInt16>("uint16", 1000);
  ros::Publisher chatter12 = n.advertise<std_msgs::UInt32>("uint32", 1000);
  ros::Publisher chatter13 = n.advertise<std_msgs::UInt64>("uint64", 1000);
  ros::Publisher chatter14 = n.advertise<std_msgs::UInt8>("uint8", 1000);
  ros::Publisher chatter15 = n.advertise<std_msgs::Float32>("float32", 1000);
  ros::Publisher chatter16 = n.advertise<std_msgs::Float64>("float64", 1000);
  ros::Rate loop_rate(1);
  std::cout<<ros::XMLRPCManager::instance()->getServerURI()<<std::endl;

  int count = 0;
  while (ros::ok())
  {
    std_msgs::Bool msg1;
    msg1.data = true;
    chatter1.publish(msg1);

    std_msgs::Byte msg2;
    msg2.data = -3;
    chatter2.publish(msg2);

    std_msgs::Char msg3;
    msg3.data = 'a';
    chatter3.publish(msg3);

    std_msgs::Duration msg4;
    msg4.data.sec = 2;
    msg4.data.nsec = 3;
    chatter4.publish(msg4);

    std_msgs::Header msg5;
    msg5.seq = 2;
    msg5.stamp.sec = 6;
    msg5.stamp.nsec = 21;
    msg5.frame_id = "Ciao";
    chatter5.publish(msg5);

    std_msgs::Int16 msg6;
    msg6.data = -1024;
    chatter6.publish(msg6);

    std_msgs::Int32 msg7;
    msg7.data = -10000000;
    chatter7.publish(msg7);

    std_msgs::Int64 msg8;
    msg8.data = -10000000001;
    chatter8.publish(msg8);

    std_msgs::Int8 msg9;
    msg9.data = -5;
    chatter9.publish(msg9);

    std_msgs::Time msg10;
    msg10.data.sec = 4;
    msg10.data.nsec = 12;
    chatter10.publish(msg10);

    std_msgs::UInt16 msg11;
    msg11.data = 1024;
    chatter11.publish(msg11);

    std_msgs::UInt32 msg12;
    msg12.data = 10000000;
    chatter12.publish(msg12);

    std_msgs::UInt64 msg13;
    msg13.data = 10000000001;
    chatter13.publish(msg13);

    std_msgs::UInt8 msg14;
    msg14.data = 5;
    chatter14.publish(msg14);

    std_msgs::Float32 msg15;
    msg15.data = 0.3f;
    chatter15.publish(msg15);

    std_msgs::Float64 msg16;
    msg16.data = 0.5;
    chatter16.publish(msg16);

    ros::spinOnce();

    loop_rate.sleep();
    ++count;
  }


  return 0;
}

 

저장 (위치 유의)

 

 

listener.cpp도 동일하게 생성

 

#include <ros/ros.h>
#include <std_msgs/Bool.h>
#include <std_msgs/Byte.h>
#include <std_msgs/Char.h>
#include <std_msgs/Duration.h>
#include <std_msgs/Time.h>
#include <std_msgs/Int16.h>
#include <std_msgs/Int32.h>
#include <std_msgs/Int64.h>
#include <std_msgs/Int8.h>
#include <std_msgs/Header.h>
#include <std_msgs/UInt16.h>
#include <std_msgs/UInt32.h>
#include <std_msgs/UInt64.h>
#include <std_msgs/UInt8.h>
#include <std_msgs/Float32.h>
#include <std_msgs/Float64.h>

void chatter1(const std_msgs::Bool::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data ? "true" : "false");
}

void chatter2(const std_msgs::Byte::ConstPtr& msg)
{
  ROS_INFO("I heard: [%i]", msg->data);
}

void chatter3(const std_msgs::Char::ConstPtr& msg)
{
  ROS_INFO("I heard: [%i]", msg->data);
}

void chatter4(const std_msgs::Duration::ConstPtr& msg)
{
  ROS_INFO("I heard: sec=[%i] nsec=[%i]", msg->data.sec, msg->data.nsec);
}


void chatter5(const std_msgs::Header::ConstPtr& msg)
{
  ROS_INFO("I heard: seq = [%i], time = [%i, %i], frame_id = [%s]", msg->seq, msg->stamp.sec, msg->stamp.nsec, msg->frame_id.c_str());
}

void chatter6(const std_msgs::Int16::ConstPtr& msg)
{
  ROS_INFO("I heard: [%i]", msg->data);
}

void chatter7(const std_msgs::Int32::ConstPtr& msg)
{
  ROS_INFO("I heard: [%i]", msg->data);
}

void chatter8(const std_msgs::Int64::ConstPtr& msg)
{
  ROS_INFO("I heard: [%lli]", msg->data);
}

void chatter9(const std_msgs::Int8::ConstPtr& msg)
{
  ROS_INFO("I heard: [%i]", msg->data);
}

void chatter10(const std_msgs::Time::ConstPtr& msg)
{
  ROS_INFO("I heard: sec=[%i] nsec=[%i]", msg->data.sec, msg->data.nsec);
}

void chatter11(const std_msgs::UInt16::ConstPtr& msg)
{
  ROS_INFO("I heard: [%i]", msg->data);
}

void chatter12(const std_msgs::UInt32::ConstPtr& msg)
{
  ROS_INFO("I heard: [%i]", msg->data);
}

void chatter13(const std_msgs::UInt64::ConstPtr& msg)
{
  ROS_INFO("I heard: [%lli]", msg->data);
}

void chatter14(const std_msgs::UInt8::ConstPtr& msg)
{
  ROS_INFO("I heard: [%i]", msg->data);
}

void chatter15(const std_msgs::Float32::ConstPtr& msg)
{
  ROS_INFO("I heard: [%f]", msg->data);
}

void chatter16(const std_msgs::Float64::ConstPtr& msg)
{
  ROS_INFO("I heard: [%f]", msg->data);
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "std_msgs_listener");

  ros::NodeHandle n;
  ros::Subscriber sub1 = n.subscribe("bool", 1000, chatter1);
  ros::Subscriber sub2 = n.subscribe("byte", 1000, chatter2);
  ros::Subscriber sub3 = n.subscribe("char", 1000, chatter3);
  ros::Subscriber sub4 = n.subscribe("duration", 1000, chatter4);
  ros::Subscriber sub5 = n.subscribe("header", 1000, chatter5);
  ros::Subscriber sub6 = n.subscribe("/int16", 1000, chatter6);
  ros::Subscriber sub7 = n.subscribe("/int32", 1000, chatter7);
  ros::Subscriber sub8 = n.subscribe("/int64", 1000, chatter8);
  ros::Subscriber sub9 = n.subscribe("/int8", 1000, chatter9);
  ros::Subscriber sub10 = n.subscribe("/time", 1000, chatter10);
  ros::Subscriber sub11 = n.subscribe("/uint16", 1000, chatter11);
  ros::Subscriber sub12 = n.subscribe("/uint32", 1000, chatter12);
  ros::Subscriber sub13 = n.subscribe("/uint64", 1000, chatter13);
  ros::Subscriber sub14 = n.subscribe("/uint8", 1000, chatter14);
  ros::Subscriber sub15 = n.subscribe("/float32", 1000, chatter15);
  ros::Subscriber sub16 = n.subscribe("/float64", 1000, chatter16);

  ros::spin();

  return 0;
}

 

CMakeLists.txt 편집 (ROS C++ 기초 1 글 참고)

 

add_executable(std_msgs_talker_node src/std_msgs_talker.cpp)
add_dependencies(std_msgs_talker_node ${std_msgs_talker_node_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(std_msgs_talker_node ${catkin_LIBRARIES})

add_executable(std_msgs_listener_node src/std_msgs_listener.cpp)
add_dependencies(std_msgs_listener_node ${std_msgs_listener_node_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(std_msgs_listener_node ${catkin_LIBRARIES})

 

launch 생성

 

<launch>

<node pkg="my_second_pkg" type="std_msgs_talker_node" name="std_msgs_talker_node1" output="screen"/> 
<node pkg="my_second_pkg" type="std_msgs_listener_node" name="std_msgs_listener_node1" output="screen"/> 

</launch>

 

터미널

 

ctm
catkin_make

 

터미널 추가

 

roscore
rosrun my_second_pkg std_msgs_talker_node

 

아무일도 일어나지 않음

 

=> cntl shift T

 

ctw
rostopic list

 

16개 변수

 

rostopic echo /bool

 

rosrun my_second_pkg std_msgs_listener_node

 

다른 터미널 창

 

rosrun my_second_pkg std_msgs_talker_node

 

listener 터미널 창 돌아가기

 

 

작동 완료

'ROS' 카테고리의 다른 글

Gazebo 시뮬레이션 구동  (0) 2022.09.06
ROS 초음파 센서 프로그래밍  (0) 2022.08.23
ROS C++ 기초 2  (0) 2022.08.21
ROS C++ 기초 1  (0) 2022.08.20
ROS 기초 이론  (0) 2022.08.20

ROS C++ 기초 2

exp()
|2022. 8. 21. 17:07

talker.cpp 

http://wiki.ros.org/std_msgs  ros 메시지 타입 정보 사이트

 

std_msgs - ROS Wiki

melodic noetic   Show EOL distros:  EOL distros:   electric fuerte groovy hydro indigo jade kinetic lunar diamondback: Only showing information from the released package extracted on Unknown. No API documentation available. Please see this page for in

wiki.ros.org

 

talker.cpp 코드 설명

int main(int argc, char **argv) #Receive constant at program startup
// 프로그램 시작 시 변수 받기 위한 것
{
  ros::init(argc, argv, "talker");
// 노드 이름 talker
  ros::NodeHandle n;
// n이라는 핸들러
 ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
// cahtter_pub(Publisher name) = string형태 ("topic name", Buffer num);
// publisher name & string 변경
 ros::Rate loop_rate(10);
// 1초에 10번 수행
  int count = 0;
  while (ros::ok()) #ok = ctrl C 들어올 때 까지 반복
  {
    chatter_pub.publish(msg); //msg publish

    ros::spinOnce(); //spinOnce = 다음에 나오는 call back 함수 1번만 실행

    loop_rate.sleep(); //1초 10번 제어 = sleep
    ++count;
  }
  return 0;
}

 


실행

1. talker 변경

2. rosrun my_first_pkg talker_node &  listener_node 실행

3. rqt graph 실행

talker -> talker1 바뀐 것 확인

 

4.  chatter -> chatter1

5. rosrun talker & listener 재실행

6. listener = 받지 않음

why? = chatter1으로 해서 연결 불가

Answer = listener.cpp에 가서 똑같이 chatter->chatter1으로 바꿔줘야함

 

7. 다시 make -> rosrun listener 재실행

연결 완료

 

8. rate 바꿈 (1초 2번)

9. talker_node 터미널 부분 재실행

rate10일 때보다 속도 느리게 나옴


listener.cpp

//string형 topic 받으면 실행되는 함수
void chatterCallback(const std_msgs::String::ConstPtr& msg)
//std_mags String 받음, 메시지 포인트 받아서 표시
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
//받은 topic 출력
}
  ros::Subscriber sub = n.subscribe("chatter1", 1000, chatterCallback);
//subscribe 함수 등록, chatter topic 입력 = cahtterCallback 실행 ("topic name", buffer, Callback함수)

  ros::spin();
//spin = 계속 호출

  return 0;

 

talker와 달리 while문 안 들어감 (간단)

'ROS' 카테고리의 다른 글

Gazebo 시뮬레이션 구동  (0) 2022.09.06
ROS 초음파 센서 프로그래밍  (0) 2022.08.23
ROS C++ 기초 3  (0) 2022.08.21
ROS C++ 기초 1  (0) 2022.08.20
ROS 기초 이론  (0) 2022.08.20

ROS C++ 기초 1

exp()
|2022. 8. 20. 01:13

Tip

복붙 = ctrl shift C/V


● 작업 공간 만들기

 

$ source /opt/ros/melodic/setup.sh

$ mkdir -p ~/test_catkin_ws/src

// -p = 하위 폴더까지 다 만듦

$ cd ~/test_catkin_ws/src

// cd = 이동

$ catkin_init_workspace

// scr 폴더에 CMakeLists.txt 파일 생성

 

=>폴더가 ROS 환경에 등록


● Package & Node 만들기

 

$ catkin_create_pkg my_first_pkg std_msgs rospy roscpp

my _first_pkg 패키지 생성

 

● Geany

새 파일 생성 → http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29 1.1 복붙

//간단한 메시지 전송 시연

#include "ros/ros.h"
#include "std_msgs/String.h"

#include <sstream>

int main(int argc, char **argv)
{
  ros::init(argc, argv, "talker");
  
  //The ros::init() = Command line에 제공된 모든 ROS 인수 & 이름 재매핑 수행 위해 argc & argv 확인.
  //프로그래밍 방식 재매핑 = init() 다른 버전도 가능하나 argc & argv 전달=가장 쉬운 방법
  //init() 3번째 인수 = 노드 이름
  //ROS 시스템 다른 부분 사용 전 ros::init()버전 中 하나 호출 필요
  
  ros::NodeHandle n;
 
  //NodeHandle = ROS 통신 기본 액세스 지점
  //첫 번째 NodeHandle = 이 노드를 초기화, 마지막 NodeHandle 파괴 시 노드 종료
  
  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

  //advertise()=해당 토픽으로 publish(송신) 가능 객체 ros::Publisher 클래스 반환, 객체 publish() 이용=원하는 메시지 발행
  //ros 마스터 노드 호출, 게시/구독 중 사용자 레지스트리 유지
  //호출 후 마스터 노드 = 구독 사용자에게 알림 → 
  //반환된 게시자 개체 모든 복사본 삭제 → 자동 알림 해제
  //advertise() 2번 파라미터 = 메시지 게시 사용, 메시지 대기열 크기
  //게시 속도 >> 가능 전송 속도 = 메시지 버리긴 전, 버퍼링 메시지 수 지정

  ros::Rate loop_rate(10); //루프 10Hz 실행 설정
  
  //전송 메시지 개수, 고유 문자열 제작 시 사용
  
  int count = 0;
  while (ros::ok())
  {
    //메시지 개체. 데이터 채운 후 게시
    
    std_msgs::String msg;

    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();

    ROS_INFO("%s", msg.data.c_str());

    chatter_pub.publish(msg);
    
    //publish() = 메시지 보내는 방법
    //parameter = 메시지 개체
    //이 개체 유형 = advertise<>() 호출 템플릿 매개 변수 유형과 일치 필요

    ros::spinOnce();

    loop_rate.sleep();
    ++count;
  }
  return 0;
}

→ ctrl S → ampt/test_catkin_ws/src/my_first_pkg/src → 이름 설정 (talker.cpp)

 

int arge = main() 전달 데이터 개수

char* argv[] = main() 전달 실제 데이터, char형 포인터 배열 구성. 첫 문자열=프로그램 실행경로 

 

하나 더 생성 ( 이번엔 2.1 복붙)

#include "ros/ros.h"
#include "std_msgs/String.h"

void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");
  
  ros::NodeHandle n;

  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
  
  //subscribe()=주어진 topic에 대한 메시지 받고 싶을 때 ros에게 말하는 방법
  //ros 마스터 노드 호출, 게시/구독 사용자 레지스트리 유지
  //메시지 → chatterCallback 
  //subscribe() = 구독 취소 까지 보류해야 하는 구독자 개체 반환
  //구독자 개체 모든 복사본 범위 이탈 시 콜백 자동 구독 취소
  
  //2번째 매개 변수 = 메시지 Q 크기
  //처리 속도<<도착 속도 = 가장 오래된 메시지 버리기 전에 버퍼링되는 메시지 수
  
  ros::spin();

  return 0;
}

같은 위치 listener.cpp 생성


컴파일 위해 생성한 CMakeLists.txt 파일 수정

주석 # 풀어주기 (매번 패키지 만들때마다 해야함)

 

줄 152~ (Install & Testing) 삭제

 

줄 136 복사

add_executable(${PROJECT_NAME}_node src/my_first_pkg_node.cpp)
//빌드 대상 바이너리 추가

줄 128 붙여넣기 & 이름변경

add_executable(talker_node src/talker.cpp)

줄 135 복사

add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
//Target간 의존성 정의
//Top-level Target간 의존성 지장
//Top-levl Target = ADD_~ 명령으로 정의한 Target 의미

★여기까지 했음

 

줄 129 붙여넣기 & 이름변경

add_dependencies(talker_node ${talker_node_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

줄 마지막 복사

target_link_libraries(${PROJECT_NAME}_node
  ${catkin_LIBRARIES}
)

줄 130 붙여넣기 & 이름변경

target_link_libraries(talker_node ${catkin_LIBRARIES})

전체 복붙해서 listener 것도 생성


eb

alias ctw='cd ~/test_catkin_ws && source ~/test_catkin_ws/devel/setup.bash'
alias cts='cd ~/test_catkin_ws/src && source ~/test_catkin_ws/devel/setup.bash'
alias ctm='cd ~/test_catkin_ws && catkin_make && source ~/test_catkin_ws/devel/setup.bash'
catkin_make


터미널 2개 각각

roscore
ctm
rospack list
//my_first_pkg check
rosrun my_first_pkg talker_node


새 터미널

rosrun my_first_pkg listener_node


노드 & 토픽 그래프

rqt_graph


토픽 보여줌

ros topic list


토픽 확인

rostopic echo /chatter

'ROS' 카테고리의 다른 글

Gazebo 시뮬레이션 구동  (0) 2022.09.06
ROS 초음파 센서 프로그래밍  (0) 2022.08.23
ROS C++ 기초 3  (0) 2022.08.21
ROS C++ 기초 2  (0) 2022.08.21
ROS 기초 이론  (0) 2022.08.20

ROS 기초 이론

exp()
|2022. 8. 20. 00:20

ROS = 로봇 응용 프로그램 개발할 때 필요한 소프트웨어 제공 플랫폼

: 하드웨어 추상화 (같은 종류 하드웨어 공통 명령어 집합으로 묶는 것) & 하위 디바이스 제어 & 일반 사용 기능 구현

& 프로세스간 메시지 패싱 & 패키지 관리 & 개발 환경 필요한 라이브러리 & 다양한 개발 및 디버깅 도구 제공

 

장점 : 오픈 소스 = 누구나 사용 가능


목적 = 전 세계 레벨에서 공동작업가능한 환경 구축

(코드 재사용 극대화에 초점을 둠)


기능

분산 프로세스 = 여러 노드 독립 실행, 노드 형태 프로그램이 분산 움직임

패키지 단위 관리 = 여러 프로세스를 패키지 단위 관리 (배포, 공유, 수정)

공개 레파지토리 = Github 공개 & 라이센스 밝힘

API(application Programming Interface, 애플리케이션 프로그램 인터페이스, 컴퓨터 or 컴퓨터 프로그램 사이 연결)

     = API 불러와 자신이 사용하던 코드 쉽게 적용

복수 프로그래밍 지원 = Python, C++, Lisp, java, C#, lua, ruby ...


사용 버전 = Melodic


ROS = 리눅스 작동 (Window X)


http://wiki.ros.org

ROS 정보 사이트


중요 개념

● Node = 최소 프로그램 단위

     (sensor / actuator driver, map building, planner, UI ...)

     독립적 컴파일 & 실행 &관리

     roscpp = C++ client library

     rospy = python client library

     Topic => Publish(내보내기) Subscriber(받기)

Messages and Topics = 노드 사이 주고받는 정보

Services

     양방향 동기 통신

     서비스 서버, 서비스 클라이언트간 통신

     1 to 1 request response

     클라이언트 요청 있을 시만 서버 응답

     요청, 응답 끊김 = 노드 접속 끊김

Actions

ROS Master = 작동법: roscore

Parameters

Packages and Stacks

Topic = 노드 간 메시지 

     단방향 비동기 통신

     Publish(메시지 통신) Subscriber(메시지 수신)

 

'ROS' 카테고리의 다른 글

Gazebo 시뮬레이션 구동  (0) 2022.09.06
ROS 초음파 센서 프로그래밍  (0) 2022.08.23
ROS C++ 기초 3  (0) 2022.08.21
ROS C++ 기초 2  (0) 2022.08.21
ROS C++ 기초 1  (0) 2022.08.20