2020년 2월 15일 토요일

nodejs기반 Open data와 LAStools 활용한 포인트 클라우드 가시화

이 글은 nodejs기반 Open data와 LAStools 활용에 대한 간단한 예제를 소개한다.

결과


머리말
현재는 데이터가 석유보다 귀중한 자원이다. 이 글은 그래픽 분야에서 많은 관심을 가지는 점군(point cloud. 포인트 클라우드) 데이터를 지도 위에서 다루는 방법을 이야기할 것이다. 

이 데이터는 매우 크고(massive) 다루기가 쉽지 않다. 여기서는 LAStools, GDAL, QGIS를 사용해 이 데이터를 다룰 것이다. 

점군 전처리 과정
이 예시에서 사용한 점군 데이터는 원래 색상이 없었다. 이런 이유로, gdal_translate 를 이용해  지도를 GeoTIFF로 변환하고, 정사 영상을 이용해 각 점군을 색칠하여 lasmerge 로 병합하였다. 

이제 관심있는 영역만 lasclip도구로 잘라낸다. QGIS에서 적절한 경계 모양 파일을 만들어 사용했다. 

Pointscene 데이터 업로드
점군 데이터를 벡터와 함께 Pointscene에 업로드하였다. Pointscene nodejs 도구를 이용해 콘솔에서 직접 업로드한다. 방법은 이 링크를 참고한다.

다음 명령으로 pointscene-nodejs-cli 폴더로 이동해 설치한다. 사용법은 node pointscene --help로 확인한다.
cd pointscene-nodejs-cli 
npm install

이제 점군을 업로드한다.

pointscene 계정에 로긴하면 장면 설정에서 좌표 시스템 정보를 추가할 수 있다. 이후, 점군 범위가 기본맵에 표시된다. 

점군에 건물 면적과 도로 중심선 shp 파일을 추가한다. 

레퍼런스

cesium 기반 3차원 공간정보 데이터 그래픽 표시 방법

이 글은 3차원 cesium 기반 공간정보맵 그래픽 분석 방법을 개발하는 예제를 간략히 소개한다. 이 글은 cesium workshop 예제들을 참고하였다.
3차원 공간정보 데이터 그래픽 표시 결과

사용방법은 다음과 같다. 
cd cesium-workshop
npm install
npm start

그럼 다음과 같은 결과를 확인할 수 있다. 
실행 결과

레퍼런스

webpack기반 cesium.js 앱 개발

이 글은 webpack기반 cesium.js 앱 개발에 관한 간단한 예제를 다룬다.

cesium.js 로 만든 웹 앱

머리말
CesiumJS는 자바스크립트 라이브러리로 3D globe와 2D 맵을 웹 브라이저에서 가시화할 수 있다. 이 기술은 WebGL을 사용한다. CesiumJS 라이센스는 Apache 2.0이며, 상업용 및 비상업용으로 무료이다. 

CesiumJS는 지형, 이미지, 3D 타일을 상업용 Cesiumion플랫폼으로 스트리밍해 얻을 수 있다. Cesiumion은 CesiumJS 개발을 지원한다. 

예제 설치
다음과 같이 설치한다.
npm install cesium

데모 예제 코드는 다음 링크를 참고한다. 
세슘 기반 시뮬레이션 가시화 예시

레퍼런스

2020년 2월 2일 일요일

도커 기반 워드프레스로 홈페이지 구축하기

이 글은 도커 기반 워드프레스로 홈페이지 구축하는 방법을 간단히 알아본다. 워드프레스는 손쉽게 홈페이지 컨텐츠를 개발하고 관리할 수 있는 도구이다. 워드프레스는 가장 많이 사용되는 블로그 시스템이다. 이 글에서 도커는 다음 이미지를 사용한다.
도커 이미지를 다운로드 받고, 다음 명령을 입력한다. 
docker run --name some-wordpress -e WORDPRESS_DB_NAME=word -e WORDPRESS_DB_USER=word -e WORDPRESS_DB_PASSWORD=word123 -p 8080:80 -d wordpress

그리고, localhost:8080 을 접속하면 다음 화면을 볼 수 있다. 

레퍼런스

2020년 2월 1일 토요일

기상관측소 만들기 - MQTT, Node-RED, Google Chart

이 글은 기상관측소를 만들기 위해 어떻게 MQTT, Node-RED, Google Chart 를 서로 연동하는 지에 대한 내용을 간단히 다루어 본다.

개요
이 예제는 다음 도구를 사용한다.
Microcontroller
  Cactus Micro Rev2 – Arduino w/ ESP8266 WiFi built-in
Display
  LCD 16×2
Sensors
  DHT11- Humidity and Temperature
Photoresistor – Light
  Messaging
MQTT
  Mosca – MQTT broker
Data Storage
  MongoDB
Data Analysis
  Google Chart
Programming
  Arduino Sketch (C++)
  Node-RED
Gallery
  Pictures
Bonus: Real-time Graphs
  ThingSpeak

개발 순서
이 예제는 ESP8266을 사용한다. 다음과 같이 펌웨어를 준비한다.
git clone https://github.com/tuanpmt/espduino
cd espduino
./esptool.py -p /dev/tty.usbmodem1421 write_flash 0x00000 esp8266/release/0x00000.bin 0x40000 esp8266/release/0x40000.bin

다음과 같이 코딩한다.
// ESP8266 WiFi 
#include <espduino.h>
#define PIN_ENABLE_ESP 13
#define SSID "yourSSID"
#define PASS "yourPassword"

void wifiCb(void* response)
{
 uint32_t status;
 RESPONSE res(response);

 if(res.getArgc() == 1) {
 res.popArgs((uint8_t*)&status, 4);
 if(status == STATION_GOT_IP) {
 Serial.println("WIFI CONNECTED");
 wifiConnected = true;
 } else {
 Serial.println("WIFI OFFLINE");
 wifiConnected = false;
 } 
 }
}

void setup() {

 // Write to ESP8266
 Serial1.begin(19200);
 // Write to Console
 Serial.begin(19200);

 // Enable ESP8266
 esp.enable();
 delay(500);
 esp.reset();
 delay(500);
 while(!esp.ready());

 // Setup WiFi
 esp.wifiCb.attach(&wifiCb);
 esp.wifiConnect(SSID, PASS);

}

void loop() {
 esp.process();
 if(wifiConnected) {
 // Do Something 
 }
}

다음과 같이 회로를 개발한다.


다음과 같이 통신 시스템을 개발한다. IoT 사용 프로토콜은 MQTT, AMQP, øMQ 등이 있다. 또한, 웹 기반 REST, WebSocket 통신도 있다. 이는 PubNub, Pusher, HiveMQ, OctoBlu 등과 같은 도구에서 지원한다.

여기서는 MQTT를 사용한다. 브로커는 Mosca, Mosquito가 가장 유명하다. HiveMQ는 SLA과 확장성을 지원하는 엔터프라이즈 플랫폼이다. 여기서는 Mosca를 선택했으며 이는 NodeJS를 사용한다.

MQTT 클라이언트는 Arduino, RPi 등을 선택할 수 있다.

데이터 저장은 SQL, NoSQL DB를 사용한다. NoSQL은 MongoDB나 DynamoDB 등이 있다. 저장은 key:value 페어 형식이다. 이 형식은 보통 JSON 포맷으로 데이터 주고 받는다. 여기서는 MongoDB를 사용한다.

메시징 흐름은 다음과 같다.

데이터 분석은 Google Chart node를 Node-RED에 설치해 사용한다.


아두이노 코딩은 여기를 참고한다. 노드 레드는 다음과 같이 디자인한다.


실시간 그래프는 ThingSpeak를 사용한다.


마무리
이 글은 간단히 IoT 기반 weather station을 개발하는 예제를 설명하였다. 요즘 많은 도구가 오픈소스로 나와 있어, 저비용으로 손쉽게 개발이 가능하다. 

NDT 기반 SLAM 개념, 빌드 및 실행

이 글은 NDT(normal distribution transform) 기반 SLAM을 간략히 설명하고 개발방법을 소개한다.

NDT 기반 SLAM 예

개요
로봇 등 무인자율주행 장치가 주변 공간 위치를 파악할 때 실시간으로 생성되는 지도가 필요하다. 보통, 로봇에 마운트된 거리 센서 등을 스캔 센서에서 얻은 상대 거리 좌표(x, y, z) 정보가 포함된 점군(point cloud)에서 지도를 생성해야 하므로, 이는 정확히 말하면 각 장면별로 획득한 스캔 데이터를 정합하는 문제로 치환할 수 있다.

NDT SLAM 알고리즘 설명
각 장면에서 얻은 점군들이 {PCD1...PCDn} 이라면, 서로 중첩했을 때 오차가 제일 적은 정합 결과물이 제일 좋은 것이다. 이렇게 정합하는 방식 중 가장 유명한 것이 ICP(Iterative Closest Points)이다. ICP에서 모든 점들에 대해 정합 오차를 계산하면 시간이 너무 오래 걸리므로, 각 장면별 유일한 특징이 될만한 특징점을 먼저 추출한 후 ICP를 실행한다.

LiDAR를 이용한 실시간 정합은 보통 LiDAR SLAM으로 알려져 있는 데, 그 동작 메커니즘은 비슷하다. 다만, 빠른 계산 속도를 만족해야 한다는 조건이 더 붙는다.

NDT는 3D 공간에서 voxel 공간 인덱싱을 처리해, 각 복셀내 점군들 3D 가우시안 분포로 근사화시켜 빠른 계산 속도를 만족시킨다.

복셀은 스캔된 점군 밀도와 SLAM 계산성능 간의 tradeoff 함수이다. 이는 상황에 따라 다르다. 복셀에서 신뢰성 있는 특징들을 신속하게 얻는 것은 SLAM에서 매우 중요하다. 각 장면의 특징들을 얻은 후 이 특징들이 장면마다 일관성(consistency)을 유지하는 지 계산한다.

높은 일관성있는 특징들(평면과 모서리 부분. 색상이 밝은 점들은 일관성이 있다고 판정된 데이터임)(Stanford University, 2019)

결국 NDT SLAM 구조를 잘 설계하기 위해서는 특징 매칭 수준의 오류를 줄이는 것이 중요하다. 각 장면 연속된 점군 PCD1, PCD2의 NDT SLAM odmetry(주행괘적) 계산 및 매 키프레임(keyframe) 에 따른 지도 갱신 아키텍처는 다음과 같다.
NDT SLAM algorithm(Stanford University, 2019)

LiDAR odometry 부분은 다음과 같다. 처리 순서는 입력된 점군 PCD에서 얻은 특징들을 대략적으로 정합해 최적화한 후, 각 복셀에 포함된 점군을 좀 더 높은 정확도로 정합 계산하는 과정이 수행된다. 이를 미리 지정된 정확도까지 만족하도록 최적화해 Fine optimization 솔류션을 얻도록 반복 수행한다.
LiDAR odometry module(Stanford University, 2019)

Retain high consensus voxels는 맵핑 최적화를 위해 지역적으로 최적해를 만족하는 consensus metric를 계산하는 과정을 포함한다.
Map Update(Stanford University, 2019)

Consensus Metric은 각 점군이 후보 위치로 변환되었을 때를 테스트한다. 주어진 후보 위치에 대해 모든 복셀 컨센서스 매트릭스를 결합하고, 테스트하는 과정을 거친다.

이 알고리즘을 수행하면 다음과 같은 결과를 얻을 수 있다.

환경준비
개발을 위해 우분투, ROS, 벨로다인 VLP-16 센서 구동 환경을 미리 설정해야 한다. 이 내용은 아래 링크를 참고한다.
벨로다인 LiDAR 센서 개발 환경 구축 결과

빌드 및 실행
NDT를 사용한 Graph SLAM을 간단히 빌드하고 실행해 본다. 여기에서는 다음 패키지를 사용한다.
이 프로그램은 VLP-16 벨로다인 센서를 이용해 SLAM 테스트된 것이다. 이 프로그램은 NDT 알고리즘을 기반으로 정합을 수행한다. LOOP 검출, Back-end 최적화 및 전역 일관성을 처리하여 맵을 생성한다. 모듈 구성은 다음과 같다.
  • floor_filter: 바닥 점군을 필터링함. 주어진 높이, 점 법선 및 점군 밀도를 이용해 바닥 제거.
  • geo_transform: 좌표 변환. WGS84 to UTM변환 제공.
  • key_frame: 각 스캔 점군 프레임 관리. id, 위치(matrix4), 점군을 관리함
  • lidar_slam_3d_ros: ROS 기본 모듈. map, path, GPS, pose, filtered PCD, GPS, TF 등 ROS 메시지를 생성 및 구독함.
  • map_builder: 지도 생성. 
  • math_func: 기본 수학 계산 함수
모듈 내 알고리즘을 살펴보면, SLAM처리를 위해서는 평평한 바닥 등 일정한 특징이 있는 곳에만 사용할 수 있다는 것을 알 수 있다.

이 패키지는 ROS, g2o(general graph optimization. BSD license)를 사용한다. g2o는 Levenberg–Marquardt(L-M) 수치해석과 같은 비선형 커브피팅 최적화 알고리즘을 포함한다. L-M은 주어진 모델과 데이터간 오차가 최소제곱이 되도록 커브피팅하는 문제를 해결할 때 사용된다. 예를 들어, 데이터 셋 (Xi, Yi)가 있을 경우, 아래 수식에서커브 f의 파라메터 B를 찾는다. 이때 편차함수 S(B)는 최소가 된다.
다음과 같이 g2o 소스를 다운로드하고 개발 환경을 만든다.
git clone https://github.com/RainerKuemmerle/g2o
cd g2o
mkdir build
cmake ../
make

참고로, 우분투 16.04에서는 버전 문제로 make build 에러가 발생할 수 있다. 이 경우, 아래에서 2017년 g2o버전을 다운로드받아 빌드해보면 제대로 설치될 것이다.
빌드된 g2o의 라이브러리를 아래와 같이 복사한다.
sudo cp ~/g2o/lib/*.* /usr/local/lib

소스 빌드를 위해 다음과 같이 실행하고 빌드한다. 우분투 18.04에서는 라이브러리 버전 차이로 문법 에러가 발생할 수 있다. 적절히 소스 코드를 수정한다(github issue 참고).
cd catkin_ws/src
git clone https://github.com/ningwang1028/lidar_slam_3d
cd ..
catkin_make

빌드 후 다음과 같이 실행한다.
roscore
roslaunch lidar_slam_3d lidar_slam_3d.launch
ROS 실행화면

라이다를 이동 시키며 점군을 실시간으로 획득해 SLAM 처리하면 다음과 같은 결과를 얻을 수 있다.
SLAM 결과

NDT SLAM은 ICP와 같이 비선형 회귀분석 모델에 대한 커브피팅에 많은 계산 시간이 필요하다. SLAM은 엔비디아 TK2에서 실행해 보았고, 처리속도는 그리 빠르지 않은 것을 보아서는 최적화가 필요한 것으로 보인다. 아울러, 다른 SLAM과 같이 급격한 회전과 바닥 등 일정한 특징이 보이지 않은 복잡한 환경에서는 여전히 정합 결과가 튀는 문제가 발생한다. 

SLAM은 특정한 제약된 환경에서는 안정적일 수 있지만, 알고리즘에 의도하지 않은 곳에서는 이처럼 여러가지 문제가 발생할 수 있다. IMU등을 통해 이상치를 검색하고 개선할 수 있지만, SLAM만으로는 문제 해결에 한계가 있을 수 있다.

마무리
이 글에서 간단하게 NDT SLAM의 개념과 개발 방법을 다루어 보았다. SLAM은 각 장면별 점군 실시간 정합을 위한 다양한 방법이 있다. 이는 응용 목적에 따라 다를 수 있다.

레퍼런스
이 내용은 다음 링크를 참고하였다.

BIM기반 지식 서비스 구현을 위한 시멘틱 정보 질의 방법

이 글은 지식 서비스를 위한 BIM 시멘틱 정보 질의 방법을 간단히 알아본다.
이 내용은 시멘틱, 온톨로지, SPARQL, BIM(Building Information Modeling), 트리플(triple), 도커(docker) 등의 개념은 알고 있다는 가정하에 진행한다. 이와 관련된 사항은 아래 링크를 참고한다.
이 글에서는 온톨로지 모델로 트리플 구조를 사용한다. 트리플 설명, Turtle 파일 포맷, 예제는 다음 링크를 참고한다. 
Jena Fuseki 서버 동작
이 글은 Jena Fuseki 서버를 사용한다. 이미 만들어진 도커 이미지를 이용해 서버를 구동시킨다. 도커 이미지는 stain/jena-fuseki 를 사용한다. Jena Fuseki 서버에 관한 상세 내용은 다음 링크를 참고하라.
도커 명령 인터페이스(DCI. Docker Command Interface)에서 stain/jena-fuseki 도커를 다운로드 받는다. 도커 이미지를 run하기 전에, 도커 내 Jena Fuseki 작업 데이터를 보관(persist) 및 저장(save)하려면 다음 같이 도커 volume를 먼저 만들어야 한다. 이 경우 사용하기 편리한 busybox를 사용한다. volume 이름은 fuseki-data 이다.
docker run --name fuseki-data -v /fuseki busybox

이제 다음과 같이 생성된 도커 volume fuseki-data가 지정된 Jena Fuseki 이미지를 실행한다.
docker run -d --name fuseki -p 3030:3030 -e ADMIN_PASSWORD=pw123 --volumes-from fuseki-data stain/jena-fuseki


도커 이미지를 구동한 후 localhost:3030을 접속하면 다음과 같은 Apache Jena Fuseki 서버 데쉬보드 화면을 볼 수 있다. 참고로 아이디아와 암호는 admin, pw123이다.

BIM 온토롤지 파일 업로드
Apache Jena Fuseki 메뉴를 이용해 Spider란 이름의 Dataset을 만들고, 다음과 같이 spider.ttl 파일을 저장 후 Jena 에 upload한다.
@base <http://example.org/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rel: <http://www.perceive.net/schemas/relationship/> .

<#green-goblin>
    rel:enemyOf <#spiderman> ;
    a foaf:Person ;    # in the context of the Marvel universe
    foaf:name "Green Goblin" .

<#spiderman>
    rel:enemyOf <#green-goblin> ;
    a foaf:Person ;
    foaf:name "Spiderman", "Человек-паук"@ru .

dataset 생성 후 파일 업로드
등록된 그래프 데이터 리스트 결과

질의를 다음과 같이 해보자.
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rel: <http://www.perceive.net/schemas/relationship/>

SELECT ?subject
WHERE
{ ?subject foaf:name 'Green Goblin' }

그럼 다음과 같이 이름이 Green Goblin 인 subject가 검색된다 .
그래프 데이터 모델 검색 결과
SPARQL 질의
Dataset을 만들고, ifc2x3 ttl 파일을 다운로드하여 다음과 같이 Jena 에 upload한다.
dataset 생성
ttl upload files
업로드된 ifc2x3 ttl 일부 내용
query를 다음과 같이 실행한다. 질의 방법은 PREFIX로 용어를 정의한 네임 스페이스를 설정한 후, SPARQL 구문으로 IfcBuildingElement의 하위 클래스를 질의한다. 

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dce:   <http://purl.org/dc/elements/1.1/>
PREFIX owl:   <http://www.w3.org/2002/07/owl#>
PREFIX xsd:   <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX vann:  <http://purl.org/vocab/vann/>
PREFIX list:  <https://w3id.org/list#> 
PREFIX expr:  <https://w3id.org/express#> 
PREFIX ifc:   <http://ifcowl.openbimstandards.org/IFC2X3_Final#> 
PREFIX cc:    <http://creativecommons.org/ns#> 

SELECT ?subject
WHERE
{ ?subject rdfs:subClassOf ifc:IfcBuildingElement }  

결과는 다음과 같다. 
질의 모습
질의 결과

fuseki 도커 서버의 로그를 확인하려면 다음 명령을 입력한다.

서버 종료를 위해 다음과 같이 도커 stop명령을 입력한다.
docker stop fuseki

도커 fuseki 서버를 재시작하려면 다음 명령을 입력한다. 참고로 fuseki 서버 run 시 옵션이 저장되므로, 모두 입력할 필요는 없다.
docker restart fuseki

다음처럼, 앞서 생성한 dataset 등이 모두 잘 보관되어 실행되는 것을 확인할 수 있다.
데이터 복원된 도커 Jena Fuseki 서버 실행 모습

마무리
SPARQL을 이용하면 좀 더 복잡하고, 추론적인 질의가 가능하다. 이를 이용해 BIM기반의 다양한 지식 서비스를 좀 더 손쉽게 구현할 수 있다. 다만, BIM과 연계된 지식 서비스 구축을 위해서는 대상 소스의 데이터를 <주어-술어-목적어> 트리플 형식으로 구조화해 데이터베이스를 구축해야 한다. 만약, 텍스트 파일에서 트리플 데이터를 생성하기 위해서는 텍스트 마이닝 기법을 사용해야 한다. 이와 관련된 상세 내용은 레퍼런스를 참고하길 바란다.

레퍼런스