2015년 7월 31일 금요일

ICRA 2015 컨퍼런스에서 소개된 최신 로봇 기술들

로봇 컨퍼런스 중 가장 유명한 곳 중 하나인 International Conference on Robotics and Automation 의 소개 동영상이다. 재미있는 로봇들이 매우 많다. 

The state of the art in robotics - highlights from the ICRA 2015 conference

펜텀 3 프로페셔널 사용기

3차원 객체 역설계(reverse engineering) 연구 목적으로 펜텀 3 프로페셔널을 구입해, 사용기를 정리한다.


1. 펜텀 3 재원
DJI사에서 개발한 펜텀 3는 4K HD 사진과 동영상을 촬영할 수 있다. 6 km 상공까지 올라갈 수 있으며, 원격제어 범위는 2 km, 배터리 타임은 약 20분 정도이다. 무게는 1.28 kg, 최대 가속 속도는 5 m/s, 3축 짐벌, 모바일 앱 등을 지원한다.

상세한 스펙은 다음과 같다.

Phantom 3 spec

기타 장난감으로 사용할 만한 드론을 정리해 본다.

2. H12C드론. 75달러. HD동영상 촬영.





2015년 7월 29일 수요일

저렴한 모터 드라이버와 RF 기반 로봇 개발 방법

가끔, Open Home Automation 등 사이트에서 좋은 글이 올라오는 데, 그 중에 매우 싼 가격에 무언가를 만들 수 있다는 식의 내용이 공유될 때가 있다.

이 글은 싼 가격으로 무선 로봇을 개발하는 방법에 대해 정리한다.
예를 들어 무선조정 탱크와 같은 것들을 3~4만원 이하가격으로 만들 수 있다. 여기에 몇 십원정도하는 광센서를 이용하면, 라인트레이서 기능을 추가할 수 있다. 또한, 초음파 센서를 사용하면, 장애물을 자율적으로 피해다니는 스마트 기능을 추가할 수 있다.

이런 기능을 개발하기 위해서는 다음과 같은 장치가 필요하다.

  • 모터 드라이버: 모터 속도, 방향을 제어한다.
  • 무선 통신 칩: 데이터를 통신하여, 모터를 제어한다.
  • 아두이노 보드: 모터와 무선 통신칩을 제어한다. 
  • 기타: DC모터, 로버 프레임, 배터리 등

1. 모터 드라이버

아래 글은 매우 싼 모터 드라이버를 이용해, 일반 DC모터의 속도, 방향을 제어할 수 있는 방법을 설명한 글이다.

여기서 사용하는 드라이버 칩은 L293D이고, 대략 3000원 이하로 구할 수 있다.

이 보다 더 손쉽게 제어할 수 있는 SN754410NE를 사용할 수도 있다. 이 칩은 두개의 모터 방향을 각각 제어할 수 있다. 

2. 테스트
다음 링크의 글을 참고하여, SN754410NE를 이용해, 모터를 제어해 본다.  
우선, 글에 표시한 대로, 회로를 결선한다. 그리고, 아두이노 코딩을 한다. 동작은 1초 전진, 1초 후진, 1초 좌회전, 2초 우회전을 계속 반복하게 코딩되어 있다. 

// Use this code to test your motor with the Arduino board:
// if you need PWM, just use the PWM outputs on the Arduino
// and instead of digitalWrite, you should use the analogWrite command
// —————————————————————————  Motors
int motor_left[] = {2, 3};
int motor_right[] = {7, 8};
int ledPin =  13;    // LED connected to digital pin 13

// ————————————————————————— Setup
void setup() {
  Serial.begin(9600);
  // Setup motors
  int i;
  for(i = 0; i < 2; i++){
    pinMode(motor_left[i], OUTPUT);
    pinMode(motor_right[i], OUTPUT);
    pinMode(ledPin, OUTPUT);
  }
}

// ————————————————————————— Loop
void loop() {
  drive_forward();
  delay(1000);
  motor_stop();
  Serial.println("1");

  drive_backward();
  delay(1000);
  motor_stop();
  Serial.println("2");

  turn_left();
  delay(1000);
  motor_stop();
  Serial.println("3");

  turn_right();
  delay(1000);
  motor_stop();
  Serial.println("4");

  motor_stop();
  delay(1000);
  motor_stop();
  Serial.println("5");

  digitalWrite(ledPin, HIGH);   // set the LED on
  delay(1000);                  // wait for a second
  digitalWrite(ledPin, LOW);    // set the LED off
  delay(1000);                  // wait for a second
}

void motor_stop(){
digitalWrite(motor_left[0], LOW);
digitalWrite(motor_left[1], LOW);

digitalWrite(motor_right[0], LOW);
digitalWrite(motor_right[1], LOW);
delay(25);
}

void drive_forward(){
  digitalWrite(motor_left[0], HIGH);
  digitalWrite(motor_left[1], LOW);
  digitalWrite(motor_right[0], HIGH);
  digitalWrite(motor_right[1], LOW);
}

void drive_backward(){
  digitalWrite(motor_left[0], LOW);
  digitalWrite(motor_left[1], HIGH);
  digitalWrite(motor_right[0], LOW);
  digitalWrite(motor_right[1], HIGH);
}

void turn_left(){
  digitalWrite(motor_left[0], LOW);
  digitalWrite(motor_left[1], HIGH);
  digitalWrite(motor_right[0], HIGH);
  digitalWrite(motor_right[1], LOW);
}

void turn_right(){
  digitalWrite(motor_left[0], HIGH);
  digitalWrite(motor_left[1], LOW);
  digitalWrite(motor_right[0], LOW);
  digitalWrite(motor_right[1], HIGH);
}

실행해 보면, 다음과 같이 좌, 우측 모터가 코딩한 대로 동작하는 것을 확인할 수 있다. 


이제, 캐터필러로 본체를 움직이도록 해 보자. 다음과 같이 잘 동작하는 것을 확인할 수 있다. 




3. 무선통신 칩
RF(Radio Frequency) 기반 무선 통신을 위해서는 nRF24송수신기 칩을 이용하면 된다. 가격은 대략 9,000~10,000원 정도 한다. 주파수는 2.4GHz를 사용하고, 데이터 전송 거리는 1000m (1km)이다. 이 때문에, RC 헬리콥터, UAV 등에서도 잘 사용된다. 


nRF24L01 + ant 와 RF2400P

다음은 nRF24L01을 사용해, 두개의 아두이노 송수신기를 만든 후, 데이터를 송수신하는 예제이다. 

다음은 RC에서 많이 사용하는 v202 프로토콜RF 송신기를 이용해, 아두이노에 전달하는 예이다. nRF24를 사용하고 있다.

다음은 라즈베리파이에 적용한 사례이다.



4. 제작 사례
이제, 부품들을 이용해, RF(Radio Frequency)기반, 무선 조정 로봇을 개발할 수 있다. 아두이이노를 이용한 사례는 다음 링크를 참고하라. 

다음은 아두이노 메가를 이용해, RF 신호를 받는 예이다.



라즈베리파이 WiFi 동글 사용기

라즈베리파이로 센서 데이터를 받은 후, 이 데이터를 특정 서버나 장치 등에 전송하고 싶을 때가 있다. 이때, 어렵게 CC3000같은 WiFi 칩을 사용해 프로그래밍할 필요가 없이, WiFi 동글을 사용하면 쉽게 해결된다.

WiFi 동글(Dongle)은 다음과 같이 생겼다. 가격은 보통 2~10달러정도 한다.


이 글에서 본인이 사용한 WiFi 동글은 WiFi n100mini이다.

WiFi 동글 설정은 간단하다. WiFi의 SSID와 PWD를 라즈베리안의 터미널 명령을 이용해 설정하면 된다.

1. 터미널에서 lsusb 입력
무선 랜아답터가 인식되는 지 확인한다.
예 - RTL8188CUS 802.11n WLAN Adapter)

pi@raspberrypi ~ $ lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter

2. sudo nano /etc/network/interfaces 입력해 다음과 같이 수정한다.
auto lo
iface lo inet loopback

iface eth0 inet dhcp

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

iface default inet dhcp

3. sudo iwlist wlan0 scan 명령어를 입력해, 검색된 무선네트워크 SSID 를 확인한다.

pi@raspberrypi ~ $ sudo iwlist wlan0 scan
wlan0 Scan completed :
 Cell 01 - Address: XX:XX:XX:XX:XX:XX
 ESSID:"SSID_NAME"
 Protocol:IEEE 802.11bgn
 ...

4. 이 중에서, 접속하고자 하는 SSID의 이름과 비밀번호를 암호화한다.
터미널에 다음과 같이 입력한다.
pi@raspberrypi ~ $ wpa_passphrase SSID_NAME SSID_PASSWORD
network={
 ssid="SSID_NAME"
 #psk="SSID_PASSWORD"
 psk=bea4ad3dc2e57e4f3db491da29231f1536151b221ee3ad76e5a4c25d739a267b
}

5. sudo nano /etc/wpa_supplicant/wpa_supplicant.conf 명령어를 입력하고, 앞에서 얻은 network=... 값으로 내용을 추가한다.

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
 ssid="SSID_NAME"
 proto=WPA2
 key_mgmt=WPA-PSK
 pairwise=CCMP
 group=CCMP
 psk=bea4ad3dc2e57e4f3db491da29231f1536151b221ee3ad76e5a4c25d739a267b
}

6. sudo reboot 명령을 입력한다.

7. 재부팅 후에 무선랜에서 파란 불이 깜빡거리면, 재대로 동작하는 것이다.

8. ifconfig 명령을 터미널창에서 실행해 보고, wlan0 부분에 inet addr부분의 IP주소가 제대로 설정되었는 지 확인해 본다.

9. ping www.google.com 명령을 입력해, 인터넷이 접속되는 지 확인해 본다.

관련 레퍼런스는 다음과 같다.

3차원 비전 기반 객체 인식

이 글은 3차원 기반 객체 인식 과정을 정리한 글이다. 포인트 클라우드를 획득한 상황을 가정한다. 이와 관련된 기본적인 알고리즘은 이미 논문과 관련 PCL과 같은 소스로 오픈되어 있다. 당연하지만, 특정 목적에 맞게 응용하기 위해서는 관련된 이론을 파악하고 있어야 한다.

보통 객체 인식과정은 다음과 같다.

1. 3차원 포인트 클라우드 획득
2. 필터링
포인트 클라우드는 데이터 양이 매우 많다. 그러므로, 불필요한 노이즈 등을 제거한다. 또한, 관심 영역만 필터링한다. 만약, 정밀도 높은 객체 인식이 필요하지 않은 경우, LOD (Level Of Detail)을 줄인다. 이는 Octree와 같은 공간인덱싱 기법을 이용해 빠른 속도로 처리 가능하다.
Octree 처리 모습 (nvidia)

3. 특징점 추출
특징점은 좌표 변환, 스케일 변환에 불변인 고유한 특징을 가진 점이다. 특징점을 획득하면, 여러 위치에서 스캔한 포인트 클라우드를 손쉽게 정합하거나, 포인트 클라우드를 세그먼테이션하거나 하는 등의 작업을 할 수 있다.

특징점을 얻기 위해서는, 반듯이 주어진 포인트 클라우드 PCD={P0...Pn} 의 모든 점 P에 대한 법선 벡터 Np를 계산해야 한다. 이를 위해서는 P 주변을 미소평면 PLN이라 가정하고, 미소평면상에 있는 포인트들 PLNp을 획득해야 한다. 이는 kNN 알고리즘을 통해 계산할 수 있다.

   PLNp = kNN(P)
kNN(Bandwidth Selection and Reconstruction Quality in Point-Based Surfaces. IEEE)

획득한 PLNp 을 다음 PCA 모델을 이용해, 미소평면 PLN을 획득하고, 여기서, 법선벡터 Np를 구한다. PCA는 주어진 포인트 들을 이용해, 공분산을 계산하여, 고유치를 획득한다. 고유치의 주성분이 평면을 구성하는 X, Y, Z축이 된다.

\mathbf{w}_{(1)} = {\operatorname{\arg\,max}}\, \left\{ \frac{\mathbf{w}^T\mathbf{X}^T \mathbf{X w}}{\mathbf{w}^T \mathbf{w}} \right\}

다음은 이렇게 계산된 법선벡터 Np이다.

법선벡터가 계산된 후에, 이 값을 이용해, 특징값들을 계산한다. 예를 들어, Point Feature Histograms (PFH) 와 같이, 두 이웃 포인트 Np1, Np2 간 법선벡터의 변화를 히스토그램화하여, 빈에 그 변화량을 누적하여, 특징으로 사용한다.

이 과정을 전체 포인트에 적용한다.

4. 세그먼테이션
앞서 계산된 법선벡터와 포인트들 간 거리를 이용해, 주어진 포인트 클라우드를 곡률 및 거리에 근거에 분할할 수 있다. 이외에, 다양한 포인트 속성값을 이용할 수 있는 데, 다음 그림은 색상을 이용해, 세그먼테이션한 것이다.

색상 기반 세그먼테이션 (PCL)

또한, 직선, 원, 호, 구, 평면, 실런더 등의 기본 모형을 정의하여, RANSAC알고리즘을 이용해 이 기본 모형에 가장 잘 부합하는 포인트 클라우드를 추출할 수 있다.

RANSAC

5. 객체 인식
객체를 인식한다는 것은, 객체의 형상, 위치, 크기, 치수 및 속성값 등을 추출한다는 것이다. 세그먼테이션을 하였다면, 각 세그먼트마다, 이 속성값들을 추출하기 위해, 다양한 전략을 적용한다.

1) Hough Transformation
허프변환을 통해, 기본 형상의 단면에 대해 가장 잘 부합하는 치수를 찾는다. 허프변환은 2차원 비전에도 활용된 방식으로, 정규분포를 가정하고, 모델 치수의 평균값을 계산한다.

2) PFH Matching
인식하고자 하는 모델의 특징점 히스토그램을 미리 저장해 놓고, 입력되는 PCD에 대해, 이 값과 비교한다. 이는 2차원 비전에서 히스토그램 매칭과 같은 개념이다.

3) RANSAC
모델을 수학적으로 미리 정의해 놓는다. 그리고, 주어진 PCD의 샘플점을 획득해, 수학적 모델을 만들고, 이 모델과 PCD가 얼마정도 부합하지지 inlier 포인트 갯수를 계산한다. 이를 통해, 모델과 유사도를 계산해, 유사도가 미리 정의한 Tolerance 값을 넘으면, 그 모델의 수치가 PCD와 일치한 것으로 가정한다.

4) Curve fitting
커브 피팅은 주어진 PCD에 가장 일치하는 수학 모델의 계수값을 계산하는 방식이다. 예를 들어, 다음과 같은 모델 수식이 있다고 하면,

P(t) = ax + by + c

여기서, 주어진 포인트 P={x, y, z} 의 군 PCD에 대해, 이 모델 수식과 가장 잘 부합하는 a, b, c값을 찾는다. 이는 복잡한 수치해석이 필요하다.

5) ICP (Interactive Iterative Closest Point)
두개의 포인트 클라우드 PCD1, PCD2가 있을 경우, 각 PCD의 특징점 집합을 구해, 서로 위치가 같도록 (서로간의 거리가 가깝도록), 좌표 변환 행렬을 계산해 각 PCD에 적용한다. 그리고, 이 과정을 계산된 거리 편차가 Tolerance이하 일때까지 반복적으로 실행한다.

만약, 두 포인트 클라우드가 같다면, 정확히 위치가 일치된다. 이런 방식이기 때문에, 정합과정에서 기본적으로 사용된다.

ICP (PCL)


6. 객체 생성
이제, 각 알고리즘에서 획득된 값을 이용해, 다음과 같이 객체를 정의할 수 있다.


2015년 7월 28일 화요일

2차원 비전 기반 객체 인식

2차원 비전 기반 객체 인식 방법에 대해 정리한다. 이 내용은 모두 OpenCV 에서 사용할 수 있는 것들로, 관련된 함수를 표시하였다.

일반적인 2차원 비전을 통한 객체 인식은 다음과 같은 순서를 가진다.

1. 2차원 이미지 획득
2. 모서리 추출
Canny edge detector 등을 이용해 모서리를 추출한다.

3. 외곽선 추출
모서리 추출 결과를 이용해, 벡터라이징을 하여, 외곽선을 추출한다. 추출된 외곽선은 시퀀스 트리 데이터 구조로 저장된다. 벡터라이징 방법은 프리만 체인을 이용해 8방향 탐색으로 추출하는 등의 기법을 사용한다.
   int cvFindContour(CvArr* image, CvMemStorage* storage, CvSeq** first_contour,
                          int header_size = sizeof(CvContour), int mode = CV_RETR_LIST,
                          int method = CV_CHAIN_APPROX_SIMPLE,
                          CvPoint offset = cvPoint(0,0))
4. 외곽선 후처리

  • 추출된 외곽선을 이용해, 외곽선을 다각형으로 근사화하거나, 길이 및 면적을 얻거나, 바운딩 박스를 얻을 수 있다. 
  • 미리 준비한 외곽선과 비교해, 유사도를 계산할 수 있다. 휴의 불변 모멘트를 이용하면, 유사도 비교를 효과적으로 실행할 수 있다. 
  • 컨벡스홀을 얻을 수 있다. 


기타 객체를 인식하는 다양한 방법은 다음과 같다. 이는 계산성능에 따라 선택할 수 있고, 이 중에 단순 마스크 필터나 패치(patch) 부분의 통계 처리 등과 관련된 알고리즘은 매우 빠른 속도로 계산할 수 있다. 다만, 조명, 그림자 등 환경에 따라 민감하게 결과가 달라질 수 있다.

1. 허프 변환 
영상에서 직선, 원 혹은 간단한 모양을 찾는 방법이다.
   cvHoughLines2(CvArr* image, void* line_storage, int method, double rho,
                       double theta, int threshold, double param1 = 0, double param2 = 0)

주어진 이미지를 구성하는 하나의 픽셀과 주변의 픽셀이 이루는 수많은 직선을 극좌표계에 누적한다. 이 중에 가장 많이 누적된 직선들을 리턴한다.


허프 변환은 근본적으로 직선 변환 방법이었으므로, 곡선일 경우, 수정된 방법을 사용한다.
   CvSeq* cvHoughCircle(CvArr* image, void* circle_storage, int method, double dp,
                                 double min_dist, double param1 = 100,
                                 double param2 = 100, int min_radius = 0, int max_radius = 0)

2. 히스토그램 매칭
주어진 이미지에서 관심 영역에 대한, 특정 방향의 히스토그램을 만들고, 미리 계산한 히스토그램 모델과 비교해, 유사도 여부를 계산하는 방법이다.

히스토그램은 정해진 갯수의 빈(bin)에 축적된 데이터 합산이다. 히스토그램은 그래디언트 크기와 방향, 색상 등으로 부터 추출된 특징이 나타난 횟수를 합산한 것이며, 데이터 분포를 보여주는 통계적인 값이다.

보통, 전체 데이터갯수로 각 빈을 다음 함수로 정규화하면, 특정 패턴을 매칭하는 것에 유리하다.
   void cvNormalizeHist(CvHistogram* hist, double factor)

또한, 잡으로 취급되어야 하는 빈을 0값으로 만들어주는 함수도 존재한다.
   void cvThreshHist(CvHistogram* hist, double threshold)

다음은 히스토그램의 최대/최소값을 알려준다.
   void cvGetMinMaxHistValue(const CvHistogram* hist, float* min_value,
                                 float* max_value, int* min_idx = NULL, int* max_idx = NULL)

다음은 이미지로부터 히스토그램을 계산하는 함수이다.
   void cvCalcHist(lplImage** image, CvHistogram* hist, int accumulate = 0,
                       const CvArr* mask = NULL)

다음은 두개의 히스토그램을 비교하는 함수이다.
   double cvCompareHist(const CvHistogram* hist1, const CvHistogram* hist2,
                                 int method)
비교할 때 method에 따라, 상관관계, 카이제곱, 교차, 바타챠야 거리에 따라 유사도를 비교할 수 있다.

다만, 이런 방법들은 조명에 변화에 따라, 색 공간의 이동을 초래하여, 히스토그램 매칭 결과가 부정확하게 나타날 수 있다. 이를 개선한 어스 무버 거리(EMD. Earth mover's distance)는 히스토그램 모양을 흙이 쌓여 있는 형태라 간주하여, 하나의 히스토그램을 다른 형태로 변경하기 위해 얼마나 많은 작업량이 필요한지를 계산한다. 최소 작업량이 두 히스토그램의 유사도이다.
   float cvCalcEMD2(const CvArr* sig1, const CvArr* sig2, int distance_type,
                          CvDistanceFunction distance_func = NULL,
                          const CvArr* const_matrix = NULL
                          CvArr* flow = NULL, float* lower_bound = NULL,
                          void* userdata = NULL)

만약, 주어진 이미지에서 특정 영역이 미리 만들어 놓은 히스토그램과 일치하는 지를 확인하고 싶다면, 히스토그램 역투영 기법(back projection)을 사용하면 된다. 이를 이용해, 매칭되는 이미지 특정 영역을 알 수 있다.
   void cvCalcBackProject(lplImage** image, CvArr* back_project,
                                 const CvHistogram* hist)

3. 템플릿 매칭
입력 이미지를 주어진 이미지 패치로 스캔하면서, 강한 유사도가 있는 부분을 찾는다.
   void cvMatchTemplate(const CvArr* image, const CvArr* templ, CvArr* results,
                                 int method)
매칭 방법은 제곱차 매칭, 상관관계 매칭, 상관계수 매칭, 정규화 방법을 이용할 수 있다.

4. 배경 삭제
움직이는 객체가 있을 때, 객체 전경은 두고, 배경만 삭제할 수 있다.

5. 특징 검출
객체 추적을 위해, 지역 특징을 추출할 수 있다.
코너 추출
옵티컬 플로우: 움직임 추정
움직임 추정: 칼만 필터

6. 이미지 캘리브레이션
카메라 렌즈 차이에 따라, 이미지의 왜곡이 발생한다. 왜곡된 이미지를 앞의 알고리즘으로 처리하면, 렌즈 차이에 따라, 처리 결과가 달라질 수 있다. 이를 보정하기 위해, 캘리브레이션을 처리할 수 있고, 캘리브레이션 된 결과는 왜곡지도(distortion map)을 생성한다. 이 지도를 이용해, 외곡된 이미지를 보정할 수 있다.
   void cvInitUndistortMap(const CvMat* intrinsic_matrix,
                                   const CvMat* distortion_coeffs,
                                   CvArr* mapx,
                                   CvArr* mapy)
7. 투영 및 3D 비전
캘리브레이션이 되었다면, 실좌표에서 픽셀좌표로 투영하거나, 다음 함수를 이용해 스테레오 이미지에서 깊이맵을 얻을 수 있다.
   void cvReprojectImageTo3D(CvArr* disparityImage, CvArr* results3DImage, CvArr* Q)

이외에, 영상 모폴로지 변환(morphological transformation)을 이용해 픽셀 밝기나 색상 속성등을 이용해, 유사한 속성이 뭉쳐져 있는 영역을 구할 수 있다. 피라미드 영상을 만들어 LOD (Level Of Detail)별로 영상을 생성할 수 있다.


2015년 7월 27일 월요일

Photogrammetry 기반 3D 포인트 클라우드(point cloud) 추출 방법

사진 측량술 (Photogrammetry) 을 이용한, 3차원 포인트 클라우드 추출 방법에 대해 글을 남긴다. 이 기술은 크게 두 가지 기술로 나눌 수 있는 데, 여러장의 사진 기반으로 3차원 모델을 추출하는 방법과 스테레오 이미지 기반으로 3차원 모델을 추출하는 방법이 있다.

첫번째 방법은 내부적으로 이미지의 특징점 추출 기능, 이미지 간 특징점 매칭 기술, 깊이맵 포인트 클라우드 추출 기능으로 구성된다.

두번째 방법은 사진 측량 기반 3차원 모델 추출 방법 중 또 다른 하나가 있다. 스테레오 스코픽 기반 깊이맵 계산 기법으로, 두개의 카메라를 하나의 대상에 대해 촬영하고, 삼각측량과 유사한 방식으로, 특징점의 깊이값을 계산한다. 특징점간 픽셀들의 깊이는 먼저 얻은 값들로 보정한다.

이와 관련된 알고리즘은 오픈되어 있으나, 개발하는 것이 쉽지는 않다. 그리고, 이미 오픈된 툴이 있어, 이를 적절히 사용하면, 좋은 결과를 얻을 수 있다.

본인이 작업해 본 결과, 사진 기반 이미지 스캔을 할 경우, 다음과 같이 촬영하는 것이 모델의 정밀도를 높일 수 있는 방법이다.

첫째, 촬영하는 모델을 중심으로 카메라가 360도 회전하면서 한장식 촬영하는 것이 좋다.
둘째, 카메라와 모델 간 거리가 일정한 것이 좋다.
셋째, 촬영된 사진들은 서로 1/3 정도 겹치도록 찍는 것이 좋다.
네째, 모델의 높이도 최소한 2등분하여, 하단부, 상단부를 360도 회전하면서 찍어야 한다.

앞의 경우를 만족하지 못하면, 추출된 3차원 모델은 좌우상하 비율이 안맞거나, 모델 일부가 유실될 경우가 많다. 본인이 실험한 결과로는 사진 측량 기반 3차원 모델 추출은 360도로 회전해 촬영할 수 있는 경우가 아니라면, 그 효과가 높지 않다.

1. Autodesk 123D 
Autdodesk 123D는 Autodesk에서 무료로 제공하고 있는 3D 모델 캡쳐 서비스이다. 아이폰, 안드로이드, 윈도우 버전이 제공된다.

Autodesk 123D

이 서비스의 장점은 스마트폰만 가지고 있으면, 3차원 모델을 손쉽게 얻을 수 있다는 것이다. PC버전도 있으나, 불편하다. 단점은 스마트폰에서 가이드된 대로만 촬영해야, 3차원 모델이 잘 나온다는 것이다. 일반 카메라로 찍었을 경우에는 반듯이 스마트폰에서 가이드된 방식대로 촬영해야지 된다. 참고로, PC버전은 불안정해 다운될 때도 많다. 촬영을 잘 했을 때 정밀도는 1~2센티미터 정도이다. 반사 재질일 경우, 특징점을 계산하지 못하므로, 해당 부분에 대한 3차원 포인트 클라우드는 추출하지 못한다.

2. VisualVSFM
사진 측량 기술 기반으로 한 툴로, 다양한 오픈소스를 이용해 개발된 것이다. 장점은 스마트폰에서 촬영된 것이 아니라도, 촬영한 이미지를 입력하면, 이들의 특징점, 특징점간 관계 등을 추출하여, 3차원 모델을 만들어 준다. 다만, 다른 도구보다 훨씬 많은 시간이 소요된다. 간단히 찍은 이미지들에서 모델을 추출하는 데, 3~4시간이상 걸리는 경우가 많다.




VisualVSFM

관련 레퍼런스는 다음과 같다. 
3. Pix4D
상용 소프트웨어이고, 일주일간 무료로 사용할 수 있다. 장점은 123D처럼 스마트폰으로만 이미지를 찍을 필요가 없으며, VisualVSFM처럼 3차원 모델을 추출하는 데 오랜 시간이 걸리지도 않는다. 단점은 일주일만 무료로 사용할 수 있으며, 상용은 가격이 꽤 비싸다는 것이다(천만원대). 역시, 이미지 기반 3차원 모델 추출 방식은 오차가 레이저 스캔에 비해 많다. Pix4D는 이를 개선하고자, GPS정보등을 사용한다. 이 경우, mm 수준으로 오차를 줄일 수 있다고 업체에서는 홍보하고 있다. 하지만, GPS신호가 없는 실내의 경우, cm 정도 오차를 가진다. 
다음은 실제 MEP 설비 장비를 고해상도 카메라로 촬영해, 이 이미지들에서 3차원 모델을 추출한 예이다. 



한국건설기술연구원 본관 지하 1층 MEP 설비 일부 
4. 3차원 모델 추출 RGB-D 카메라 
위 도구가 아니라, 직접 물체에 적외선을 주사해 반사된 값으로 3차원 좌표값들을 추출할 수 있는 RGB-D 카메라 장치를 사용하면, 앞서 언급된 방법보다 훨씬 정밀한 값을 얻을 수 있다. 이런 장치들은 보통 정밀도가 mm단위로 측정된다. 다만 정밀도에 따라 매우 비싸거나(최소 몇백만원 이상), 측정거리가 짧고 정밀도가 낮거나(키넥트 등), 적외선 파장이 간섭이 일어나는 야외에서 활용이 어려울 수 있다.

다음은 이런 장치를 소개한 글이다. 

5. 마무리
센서와 처리 소프트웨어는 역시 비싼만큼 정밀도가 높아지고, 처리속도도 빨라진다. 하지만, 응용 목적에 따른 정밀도나 처리 속도가 크게 문제되지 않는다면, 위의 무료 도구들을 이용해 볼 수 있다. 





2015년 7월 26일 일요일

2015 mini DRC 재난구조 로봇의 비전인식 알고리즘 정리 및 고려사항 도출

이 글은 mini DRC 참가를 위해, 8월초에 정리한 글입니다. 전략이었는데, 이번 챌린지에서는 사용할 기회가 없었네요^^;;; 다음 재난구조로봇에 참가할 분들을 위해 공유합니다. 



이 글은 모든 미션이 비전을 이용해, 자율주행할 수 있는 지를 검토해 보기 위해 알고리즘정리한 글이다 (참고로, 로봇제어는 모두 통신으로 처리해야 하며, 로봇의 모습이나 주변 상태는 눈으로 보이지 않는 거리에 있다). 로봇 기반으로 비전 처리를 해야하는 미션  알고리즘을 정리한다.


참고로, 경기장 재원 정보를 이용하면, 비전 처리 시 계산 속도를 높일 수 있다. SLAM을 처리하는 것은 좀 불안하다. 로봇이 경기장을 모두 스캔하고, 경기를 할 수는 없기 때문이다. 하지만, 만약, 경기장 규격이 경기 당일까지 전혀 바뀌지 않는다면, 현장 맵을 미리 프로그램에 넣을 수 있다. 이는 큰 속도 향상을 가져 올 수 있다 (*주: 자동 방식 보다는 반자동 방식이나 수동 방식으로 전략을 만들었다. 각 미션을 자동으로 진행한다는 것은 매우 어렵다).

1. 개요

1. 장애물 통과

장애물은 폭 20cm 통과 여유가 있다. 객체 인식은 3차원 포인트 클라우드를 획득했을 경우, PC 성능만 뒷받침해준다면, 곡률  유클리드 거리 기반 세그먼테이션 기법을 사용해, 객체를 구분하고, 위치를 얻어 낼 수 있다. 2차원 이미지로는 객체를 2차원적으로는 구분하고, 상대적인 크기를 획득할 수는 있지만, 거리/위치를 얻기는 매우 어렵다. 2차원 이미지 기반비전은 기본적으로 현재 이미지 특징점과 패턴을 인식하는 데는 용이하고, 빠른 처리가 가능하나, 객체 거리/위치를 얻는 것은 명확한 한계가 있다.

만약, 객체 위치와 거리를 얻을 수 있으면, 그 사이 위치를 확인해서, 로봇이 주행 중심으로 오게 하여, 장애물을 피해가게 할 수 있다. 다만, 진행 방향과 거리를 미리 지정해 주어야, 장애물을 피해서 갈 수 있다. 로봇에 명령하는 알고리즘은 다음과 같이 정리할 수 있다.


1) Vbeg = 진행 방향 시작점
2) Vend = 진행 방향 끝점
3) Vdir = 진행 방향 벡터  거리
4) 장애물 스캔  회피 진행
    1) 3차원 포인트 클라우드 획득
    2) 세그먼테이션
    3) 세그먼테이션된 객체 크기  거리 계산
    4) 장애물과 Vdir을 고려해서, 진행 경로 Path 계산.
       Path는 현재 로봇에서 다음 경로까지 상대 거리와 방향을 가지고 있음
    5) Path 정보를 이용해, 로봇 기구부 이동
    6) Vend 지점 주변부(허용오차거리 이내)까지 로봇이 도착하면, 이 단계 미션 성공!
    7) 1)번부터 반복 실행

이런 것이 가능하기 위해서는, 로봇 기구부 정면부 (20미터 크기 장애물을 스캔할 수 있는)를 스캔할 수 있는 이미지 센서가 있어야 한다. 아울러, 장애물과 로봇의 거리가 작을 경우, 이를 충분히 스캔할 수 있는 장비가 필요하다. 일반적인 RGBD센서는 50cm 거리 이상의 사물만 스캔할 수 있음을 명심하자. 그러므로, 이런 미션을 수행하기 위해서는 20cm 이하도 스캔할 수 있는 근거리용 스캔 센서가 필요하다. 

아울러, 모든 방향, 자세 및 이동 거리 제어는 PID방식으로 해야 한다. 로봇의 바퀴는 마찰력에 따라 진행 중 자세가 흐트러질 수 있음을 명심하자. 

2. 사다리 오르기

사다리는 20cm 간격으로 봉이 걸쳐져 있다.

이 미션은 간단히 IMU센서로 처리할 수 있을 듯하다 (*주: 현재 시점에서는 글을 쓸 8월 초 당시에 이 미션이 얼마나 어려운 것인지 몰랐었다. 일단, 이 미션이 가능하려면, 기구부에 로봇암이 두개 이상 있고 끝 부분이 마찰력이 있어, 사다리 상판부를 마찰력으로 몸체를 끌어 올라갈 수 있는 형태거나, 캐터필러에 갈고리가 달려, 갈고리가 사다리 봉을 걸치고, 끝까지 등판할 수 있는 형태가 되어야 한다. 아니면, 사다리를 올라갈 정도 정밀하게 자세제어가 되는 안드로이드형 로봇이 캐터필러형보다 더 낫다. 그렇지 않으면, 이 미션은 매우 수행하기 어렵다).

1) 로봇 자세 인식/교정
   자세가 사다리에 대해 바르지 않으면, 인식이 어려울 수 있음.
   이는 다른 장애물(문 등)도 마찬가지임. 자세 인식  정렬은 IMU센서를 이용할 수 있음
2) 진행 시작점 Vbeg, 끝점 Vend, 벡터 Vdir 설정
3) IMU센서 스캔
   1) 처음 사다리 미션 진행 시
      진행 후 40도 기울어진 시점에서 IMU센서 측정. 사다리 시작부임을 표시
   2) 사다리 시작부일 경우
      IMU센서 기울어짐이 10도 이내일 경우, 사다리 마지막부임을 표시.
     로봇을 40cm 더 주행함

이 또한, 앞의 글과 상황은 유사하다. 적절한 센서와 PID를 통한 자세 제어가 필요하다.

3. 출입문 통과

문을 인식하여, 통과해야 한다.

1) 이미지 스캔을 통해, 문 모서리 영역 인식
    2차원 비전은 모서리 인식 알고리즘을 사용.
    3차원 비전 경우 곡률 기반 세그먼테이션을 사용해, 평면을 획득 후 문 형상과 가장 가까운 평면을 문이라 인식해, 문 경계과 크기를 계산해야 함.
2) 문 중심점 인식
3) 문 중심보다 문을 밀고 닫기 좋은, 약간 우측 지점을 계산
4) 해당 지점 바로 앞으로 로봇을 이동
5) 로봇 자세 인식/정렬
6) 문을 60cm 밀며 진행

이 경우에서 조심해야 할 부분은 너무 지나가면, 바닥으로 떨어질 수 있다는 것이다. 이를 검출하기 위한 가장 간단한 방법은 로봇 바닥에 초음파 센서를 다는 것이다. 

4. 밸브 잠구기

밸브를 인식하여, 잠구어야 한다.

1) 로봇 자세 인식/교정해 로봇암이 밸브까지 뻗을 수 있는 위치로 이동/자세정렬
2) 이미지 스캔  밸브 인식
   1) 역시 세그먼테이션을 하고, 그 중에, 밸브 특징을 가진 객체를 추출한다.
      2차원 비전일 경우, 밸브가 있을 만한 영역 모서리들만 추출해 인식한다.
   2) 밸브 중심위치를 계산
3) 밸브 잠굼
   1) 중심위치와 로봇 현재위치를 계산해, 이동 벡터 계산
   2) 로봇암 엔드를 이동
   3) 로봇암 엔드를 밸브에 걸치고, 시계 반대 반향으로 로봇암 엔드를 회전

로봇암을 이용할 경우, 엔드가 뻗는 거리나 위치를 이용해, 역으로 로봇암을 구성하는 각 모터의 회전각을 결정해야 한다. 이는 역기구학을 참고하도록 한다.

5. 인명 구조

인명을 인식하여, 구조해야 한다.
이 단계는 2차원 비전으로는 어렵다.

1) 3차원 이미지 스캔
2) 세그먼테이션
3) 인형 객체 추출  외곽선 계산
4) 외곽선에서 인형 축 벡터 계산
5) 인형 축 벡터와 법선 벡터 상에 로봇이 위치할 수 있도록, 로봇 자세 제어
6) 인형 축 벡터까지 로봇 암이 뻗을 수 있는 거리까지 로봇 이동
7) 로봇 암을 뻗어, 인형 폭을 넘어가도록 로봇 엔드를 뻗는다.
8) 로봇 엔드를 바닥에 닫게 함.
9) 로봇 엔드를 로봇 안쪽으로 끌어 땅김
10) 로봇 안쪽까지 인형을 싣게 된 상황이 되면, 로봇 암으로 인형을 고정시킴

이 경우, 로봇 암이 2개라면, 안정적으로 인형을 끌어 땅기고, 인형을 로봇 위에 싣고, 고정하기 쉽다.

6. 계단 내려오기

계단 각 색상을 인식하여, 바닥까지 내려와야 한다.

1) 계단 상부 모서리 인식해, 로봇 자세인식/교정
2) 로봇 암 엔드에 달린 카메라를 계단 바닥 면을 보게 함
3) 2차원 이미지 스캔해 모서리와 영역 인식
4) 영역 평균 색상 비교
5) 색상이 계단 바닥색상이면, 로봇 주행 종료
6) 로봇을 앞으로 주행
7) 3)번 단계로 가서 반복 실행

계단 내려오기 부분은 2차원 비전으로도 충분하다. 이런 문제는 OpenCV를 이용해, 색상영역을 인식하면 매우 쉽게 처리할 수 있다.

2. 고려사항

  1. 로봇 자세에 따라 얻어지는 센서 이미지는 모두 틀리다. 그래서, 로봇 자세 교정 단계가 필요하다. 
  2. 고정된 이미지가 얻어지는 것이 아니다. 인식하고 조정해야 하는 객체 경우, 3, 6번 경우에는 로봇 기구를 바른 자세로 만들고 진행해야 한다.
  3. 만약, 로봇 암으로 조정해야 하는 경우, 4, 5은 로봇 엔드에 이미지(카메라 등) 센서가 있는 것이 객체 인식에 매우 유리하다.
  4. PC성능  네트워크 성능만 좋다면, 3차원 비전이 훨씬 유리해 보인다. 다만, 네트워크 환경이 나쁘다면, 카메라 이미지만 사용해서 미션을 수행해야 한다.
  5. 경기장 규격 맵을 미리 만들어 넣으면, IMU센서를 이용해, 각 미션 객체와 로봇을 마주보게 하는 등 자세 교정을 하기가 쉬워진다 (로봇이 SLAM맵을 한번 스캔하고, 대회를 진행하는 단계는 없기 때문에.). 
  6. 모든 부분을 자동화하는 방식으로 알고리즘을 고민해 보았을 때, 역시, 3차원 포인트 클라우드를 실시간(예를 들어 3초 내에 3차원 이미지 스캔 -> 객체 세그먼테이션 -> 객체 위치/치수 계산)이 가능한 정도라면, 로봇과 객체까지 위치/거리를 손쉽게 얻을 수 있으므로 쓸만하다. 
  7. 계단과 같이 색상이나 모서리를 빨리 파악해야 하는 경우는 2차원 비전이 유리하다. 다만, 위치나 거리가 상대적이므로, 계속 이 데이터를 피드백 받으면서, 로봇을 진행시켜야 한다. 
  8. 전체 미션 수행 시간이 10분이다. 6단계이므로, 한 단계당 100초 시간 내에 끝내야 하며, 자동으로 할지, 수동으로 조작할 지, 서로 견을 주고 받는 시간을 대략 20초로 잡으면, 80초 내에 각 단계를 수행해야 한다. 
  9. 자동일때 3초 이미지 스캔/비전 처리가 가능하다면, 주행 1초당 10cm 속도로 주행한다고 가정했을 때, 한단계 주행 거리가 200cm라면, 80초가 걸린다(주행시간 20초 + 이미지 스캔/비전처리 60초). 만약, 하나 스캔/비전처리 단위인 1 vision 당 20cm 주행이라면, 40초(10초+30초)가 소요될 것이다. 3초내에 스캔/통신/비전처리가 되는 정도 하드웨어 스펙이라면, 비전 처리가 가능하다 (*주: 이 시점에서 고려하지 못한 것 중 하나를 언급해 본다. ROS를 통한 자동 제어도, 그 상황을 관찰할 수 있는 UI를 별도 개발하는 편이 좋다. 그리고, 자동 제어 도중, 로봇의 자세 등이 잘못되었을 때, 이를 통신하여, 보정해 줄 수 있도록, 모니터링하고, 미세 조정하는 기능도 아울러 개발하는 편이 좋다).

3. 기술적 고려사항

 내용을 알고리즘으로 구성하기 전에 필요한 기술적 고려사항은 다음과 같다.

1. 3차원 포인트 클라우드, 2차원 비전  통신 기본 알고리즘까지 모두 개발할 시간은 없다.
PCL, OpenCV, ROS 를 최대한 활용해야 한다. 라즈베리파이2에 ROS를 설치해야 WiFi 동글을 통해, 통신을 할 수 있고, 마스터 PC에 노드로 등록할 수 있다. 이 전과정을 테스트해 봐야 한다.

2. 비전 인식 후 로봇 자세제어/구동을 위한 테스트를 해 보아야 한다.
일부는 이동/동작 지정 방식, 일부는 스캔->비전처리->동작제어->동작결과피드백->스캔 ... 으로 테스트하는 것이 필요하다.

3. 통신 테스트가 필요하다. 자동 동작하다가, 통신이 끈어진다던지, 트래픽이 나빠져, 전송속도가 급격히 떨어지는 등 문제가 발생할 수도 있다 (*주: 이 글을 8월 초에 정리했는 데, 지금 읽어보니 무슨 예언 같은 글이다. 많은 참가팀이 이 통신 문제 때문에, 원격으로 카메라 영상을 전혀 보지 못하였다. 우리가 사용하는 모든 통신 주파수는 채널을 분할해 사용한다는 것을 명심하자. 채널을 사용하는 사람이 많을 수록 그 채널은 급격히 속도가 느려진다. 코엑스나 킨텍스와 같은 장소는 이런 문제가 발생하는 전형적인 환경이다. 이 시점에서 간섭없는 완벽한 통신 방법은 없는 것인지 궁금하다).

그러므로, 아래 레퍼런스를 참고해, 관련 SW를 설치해 보고, 이런 부분들을 테스트할 필요가 있다.


참고로, 아래는 이미지 스캔을 통해 획득한 데이터를 이용해, 객체를 인식하는 방법을 기술한 레퍼런스들이다. 이와 유사한 레퍼런스들이 구글링을 하면 많이 나온다. 그에 비해, 네이버 검색을 하면 별로 안나온다 (예 - opencv or pcl door detection 등) 해외 어떤 사이트경우, 로봇+비전을 미리 개발해, 그 자료를 공개하고 있는 곳도 있었다.

비전 기반 객체 인식 레퍼런스

이미지 스캔을 통해 획득한 데이터를 이용해, 객체를 인식하는 방법을 기술한 레퍼런스를 정리한다.

2015년 7월 25일 토요일

아두이노/ROS/라즈베리파이 기반 RpLiDAR 활용

이 내용은 라즈베리파이 기반 RpLiDAR 센서 활용을 위해 정리한 글이다.
센싱한 정보를 ROS로 전달해 보는 것까지로 한다. 레퍼런스는 다음과 같다.
RpLiDAR는 ROS, 아두이노 및 라즈베리파이에서 사용이 가능하다. 참고로 아래 그림은 LiDAR동작 원리를 보여준다.

1. ROS

ROS에서는 다음 링크에서 관련 라이브러리를 다운받을 수 있다.

https://github.com/robopeak/rplidar_ros

2. 아두이노

아두이노에서는 앞의 링크에서 드라이버 라이브러리를 다운받아, 아두이노 라이브러리에 설치한다. 그리고, 다음과 같이 회로를 연결한다.


그리고, 예제의 simple_connect 샘플코드를 실행해 본다.
관련 소스코드는 아래 링크에서 찾을 수 있다.

https://github.com/robopeak/rplidar_arduino.

3. 라즈베리파이 기반 RpLiDAR 활용

본인은 다음과 같은 로봇 기반 SLAM 데이터를 획득하는 것이 목표이다.


라즈베리파이를 사용하면 이동에 적합한 SLAM 센서 테스트가 용이하다. 다음은 오픈소스 기반 SLAM을 이용해, RpLiDAR 및 RGBD 센서에서 획득한 데이터를 가시화한 화면이다.
한국건설기술연구원 본관 기계실

아래는 참고한 기타 레퍼런스이다.

센서 데이터 무선(WiFi, Bluetooth) 통신 방법

센서로부터 데이터를 받아, 노트북이나, 스마트폰으로 전달해야 하는 일이 생겼다.

이 경우, 블루투스 통신, WiFi 통신을 사용할 수 있다. 
블루투스 통신은 블루투스가 지원되는 장치 양방향 페어링을 하면, 서로 정보를 주고 받을 수 있다. WiFi의 경우, 네트워크 무선 AP가 있는 경우, 특정 포트로 정보를 전달할 수 있다. 이런 통신을 위해서는 다양한 통신 장치가 있으며, 당연히 돈을 많이 투자할수록, 이런 노가다 작업이 매우 쉬워진다. 

1. Adafruit CC3000
테스트해보기 위해, Adafruit CC3000을 이용해 작업해 보았다. 상세한 예제 따라하기는 아래 링크를 참고하길 바란다. 주의할 점은 CC3000라이브러리 내 사용핀이 상수로 고정되어 있어, 핀 번호를 마음대로 변경하면 안된다는 것이다. 이 과정을 무시하면, 한 두시간 그냥 노가다한다. 


만약, 잘 동작하지 않으면, 결선이 제대로 되었는 지, WiFi SSID와 암호를 확인해 보고, 그래도 문제가 있다면, CC3000칩을 다른 칩으로 사용해 본다.

작업 후기 - 실제로 이 작업을 하는 데, 3~4시간이 걸렸다. 매우 간단한 작업이었지만, 앞에 언급된 문제 뿐만 아니라, 얼마전 LG에서 업그레드 해준 공유기 문제까지 겹쳤다. 몇 시간 동안 동작이 안되니, 칩교체+단락테스트+핀교체+아두이노보드교체+재코딩+WiFi SSID/암호 변경을 무한 반복. 헐~ 그래도 안된다. 멘붕이다. 공유기를 교체한 후에도 해결이 안되었다. 마지막으로, 공유기 바로 앞으로 가져가서 테스트해보았다.


헐.. 잘 된다. 젠장. CC3300은 공유기가 보이는 곳에 있어야 인식된다. 다음 같은 메시지가 시리얼모니터로 출력되면 성공이다. 인식은 대략 25초 정도 걸렸다.

Hello, CC3000!

Free RAM: 1133

Initializing...

Attempting to connect to U+Net8080
Connected!
Request DHCP

IP Addr: 192.134.223.148
Netmask: 255.255.255.0
Gateway: 192.168.219.1
DHCPsrv: 192.168.219.1
DNSserv: 1.214.68.2
www.adafruit.com -> 207.58.139.247-------------------------------------
HTTP/1.1 200 OK
Date: Sun, 26 Jul 2015 06:15:13 GMT
Server: Apache
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Authorization, Referer, User-Agent
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
Accept-Ranges: bytes
X-Mod-Pagespeed: 1.9.32.3-4448
Vary: Accept-Encoding
Cache-Control: max-age=0, no-cache
Content-Length: 74
Content-Type: text/html

This is a test of the CC3000 module!
If you can read this, its working :)
-------------------------------------


Disconnecting

Adafruit CC3000 테스트 용으로 Adafruit 웹서버인 http://www.adafruit.com/testwifi/index.html 에 다음과 같은 TEXT 페이지를 넣어 놓았다.


건너방에서 스마트폰에서 와이파이 잘 터진다고, 그곳에서 테스트하면 안된다. 기본적으로 제공되는 WebClient, buildtest 모두 다 잘된다. 다음은 buildtest 결과이다.

Hello, CC3000!

RX Buffer : 131 bytes
TX Buffer : 131 bytes
Free RAM: 1215

Initialising the CC3000 ...
Firmware V. : 1.24
MAC Address : 0xFF 0x66 0x87 0x92 0x30 0x64
Networks found: 3
================================================
SSID Name    : U+zone
RSSI         : 36
Security Mode: 3

SSID Name    : U+Net372B
RSSI         : 36
Security Mode: 3

SSID Name    : U+Net8080
RSSI         : 36
Security Mode: 3

================================================

Deleting old connection profiles

Attempting to connect to U+Net8080
Connected!
Request DHCP

IP Addr: 192.234.453.123
Netmask: 255.255.255.0
Gateway: 192.168.219.1
DHCPsrv: 192.168.219.1
DNSserv: 1.214.68.2
www.adafruit.com -> 127.0.0.1

Pinging 127.0.0.1...0 replies


Closing the connection

HTTPServer 예제는 실행해 접속해 본 결과, 성능이 그리 좋지는 않았다.

Hello, CC3000!

Free RAM: 789

Initializing...

Attempting to connect to U+Net8080
Connected!
Request DHCP

IP Addr: 129.342.324.132
Netmask: 255.255.255.0
Gateway: 192.168.219.1
DHCPsrv: 192.168.219.1
DNSserv: 1.214.68.2

NOTE: This sketch may cause problems with other sketches
since the .disconnect() function is never called, so the
AP may refuse connection requests from the CC3000 until a
timeout period passes.  This is normal behaviour since
there isn't an obvious moment to disconnect with a server.

Listening for connections...

CC3000은 앞서 언급한 것처럼, 인식에 25초 정도 시간이 걸려, 다운된 것이 아닌가라는 생각을 하게 하는 함정이 있다.

참고로, 이 문제와 관련해, Adafruit forum website 에서 mike가 남긴 메시지이다.



2. Serial WiFi ESP8266
CC3000은 많은 양의 데이터를 전송할 때는 효과적일 수 있으나, 그렇지 않은 경우(영상 이외의 일반 센서 데이터 값처럼 그리 많지 않은 경우)에는 ESP8266과 같은 초소형 시리얼 WiFi 칩을 사용해도 충분하다. 참고로, CC3000의 경우 많은 라이브러리 코드로 인해, 코딩이 추가되면, 일반 아두이노 우노 보드에 코드가 업로드되지 않는 문제도 보고되고 있다.

ESP8266은 가격과 적당한 성능이 인상적이다. 처음 출시때 단돈 5달러인것이 요즘에는 3달러까지 내렸다.


회로 결선은 다음과 같이 하면 된다. 좀 더 상세한 예제는 이 링크를 참고한다.


ESP8266라이브러리를 설치하였다면, WiFiWebServer 예제를 실행해 본다. 참고로 오래된 아두이노 IDE 버전에 단순히 라이브러리만 설치하면, 에러가 나므로, 최신 버전을 설치한 후에 적용해 보자. 아래는 이 칩을 이용해, WiFi 웹서버 릴레이를 만든 사례이다. 
3. WiFi 동글
아울러, 아두이노보다 성능이 좋은 (다만 사용이 좀 더 복잡한) 라즈베리파이에서 주로 사용하는 WiFi 동글 ipTIME N100mini 을 사용할 수도 있다. 개인적으로 라즈베리파이에서는 제일 편한 방법이라 생각한다.
ipTIME N100mini

설치 방법은 아래 링크를 참고한다. 매우 간단하다. 사서 USB에 꼽기만 하면 된다 (물론 드라이버가 미리 설치되어 있는 운영체제에서는 자동으로 WiFi가 인식됨).
이외에 쉴드형 WiFi 장치가 있다. 다만, 가격이 비싸다.

4. Serial Bluetooth 
Bluetooth를 지원하는 간단한 시리얼 통신 형태 장치가 있다. 간단한 데이터 통신은 이 장비로도 충분하다.

HC-05, HC-06의 가격은 5~7달러 정도로 매우 싸다.

이 제품과 관련된 상세한 내용은 이 링크를 참고한다.
아두이노와 연동하는 예제여기를 참고한다.
블루투스는 AT명령을 지원해, 전송속도, 암호 등을 설정할 수 있다.

AT : Ceck the connection.
AT+NAME : See default name
AT+ADDR : see default address
AT+VERSION : See version
AT+UART : See baudrate
AT+ROLE: See role of bt module(1=master/0=slave)
AT+RESET : Reset and exit AT mode
AT+ORGL : Restore factory settings
AT+PSWD: see default password

HC-06은 AT명령이 아래와 같이 제한되어 있다. 
AT : check the connection
AT+NAME: Change name. No space between name and command.
AT+BAUD: change baud rate, x is baud rate code, no space between command and code.
AT+PIN: change pin, xxxx is the pin, again, no space.
AT+VERSION

DF Robot에서 나온 다음과 같은 블루투스는 모든 명령을 지원하고 있다. 다만, 가격이 비싸다.
DF의 Bluetooth V3 기본 설정값은 다음과 같다.
  • Default setting
    1. Device class: 0
    2. Inquiry code: 0x009e8b33
    3. Device mode: Slave mode
    4. Binding mode: SPP
    5. Serial port: 38400 bits/s; 1 stop bit, no parity (In datasheet, it said the default baud rate is 9600 which is wrong.)
    6. Pairing code: “1234”
    7. Device name: “HHW-SPP-1800-2

이외에, Adafruit에서 개발된 Adafruit Bluefruit LE UART Friend 등도 있다.



몇몇 보드는 약간 변경된 블루투스 방식을 사용하여, 전용 블루투스 장치가 필요하다. 다음은 다이나믹셀 제어용으로 개발한 OpenCM과 연결되는 BT-410, BT-210 블루투스 장치에 관한 링크이다. 
OpenCM에는 무선통신 용 RX, TX 단자가 있고, 코딩은 아두이노 변형 IDE 도구를 이용하기 때문에 손쉽게 일반적으로 사용되는 블루투스 장치와 호환될 것 같지만, 일반적인 블루투스 칩을 여기에 연결해도 통신이 이루어지지 않는다(쉽게 보고 삽질하다가 결국 잘 안되었다. 레퍼런스도 없다. 가격이 3이배 이상 비싸더라도 해당 제조사가 패키징한 블루투스 BT-410/210을 구매하자 -.-).