검색결과 리스트
글
리눅스(우분투)에서 USB가 동작하지 않을 때 수동으로 연결하기(Failed to open the USB device!)
PrimeSense사에서 제작한 RD 1.09 RGB-D 카메라를 USB 3.0에 꽃아서 openni2 환경에서 실행을 해보려 하던 도중 다음과 같은 문제가 발생하였습니다.
No matching device found.... waiting for devices. Reason: openni2_wrapper::OpenNI2Device::OpenNI2Device(const string&) @ /tmp/buildd/ros-indigo-openni2-camera-0.2.2-0trusty-20141015-0837/src/openni2_device.cpp @ 74 : Initialize failed
Could not open "1d27/0609@1/12": Failed to open the USB device!
보아하니 RD 1.09 버전에서는 USB 2.0 버전만 지원이 되서 발생하는 문제로 추측됩니다. 즉, 디바이스 노드를 생성하지 못하는 상황으로 추측할 수 있습니다. 이 경우 USB 기기를 수동으로 설정하기 위해서는 다음과 같이 진행해줍니다.
1. 먼저 현재 리눅스(우분투)에 연결된 USB 드라이버의 리스트를 출력합니다.
$ lsusb
위의 명령어를 입력하시면 다음과 같이 현재 컴퓨터에 연결된 USB 기기들의 리스트가 나타납니다.
위 목록을 보았을 때 자신의 기기가 어떤 것인지를 파악합니다. 저의 경우 1d27:0609로 써있는 부분으로 추정됩니다.
2. udev를 사용하여 USB 드라이버를 수동으로 연결하는 규칙을 만들어줍니다. 여기서 .rules의 이름은 자신이 파악하기 쉬운 이름으로 붙여줍니다. (ex: 40-libopenni2-0.rules)
$ sudo vi /etc/udev/rule.d/my_rule.rules
3. 다음과 같이 입력해 주시고 ':wq'를 입력하여 저장해줍니다. ATTR의 'idProduct'와 'idVendor'는 위에서 lsusb를 입력하였을 때 나왔던 ID를 각각 입력해주시고 GROUP의 경우 자신에 맞는 그룹을 설정해줍니다. 저의 경우 카메라를 사용하므로 'video'로 설정하였습니다.
SUBSYSTEM=="usb", ATTR{idProduct}=="0609", ATTR{idVendor}=="1d27", MODE:="0666", OWNER:="root", GROUP:="video"
4. 여기까지 진행하신 후 다시 기기를 사용해보신다면 정상적으로 연결되는 것을 확인하실 수 있습니다.
혹시 udev에 대해 자세히 알고 싶으신 분은 아래의 블로그 글을 읽어보시기를 추천드립니다!
'공대생의 팁' 카테고리의 다른 글
| Windows 10 Internet Explorer 11 에서 Adobe flash가 실행되지 않을때 해결방법 (1) | 2019.08.26 |
|---|---|
| C++에서 Boost ASIO를 사용하여 TCP 동기화(Blocked) 통신 프로그래밍 (0) | 2019.07.21 |
| C++에서 Graphviz로 그래프 이미지 그리기 (0) | 2019.07.04 |
| Extreme Learning Machine(극학습기계) (0) | 2019.05.15 |
| LSD-SLAM에서 Semi-Dense의 의미 (1) | 2019.03.19 |
설정
트랙백
댓글
글
C++에서 Graphviz로 그래프 이미지 그리기
자료구조를 공부하거나 특정한 환경을 그림으로 표현하고자 하는 경우가 있습니다. 특히 위상수학 같이 이산수학이 사용되는 분야에서는 각 객체들의 상호관계를 나타내야 하는 것이 중요하지요. 이러한 특성을 이미지로 나타낸 것을 흔히 그래프(Graph)라고 부릅니다.
위의 그림은 같은 Depth를 유지하는 것을 목적으로 설계된 B+ 트리를 나타냅니다. 각 노드(혹은 Vertex)가 화살표(혹은 Edge)로 연결되어 있습니다. 특정한 프로그램의 알고리즘을 위와 같이 그림으로 표현한 것을 그래프라고 합니다.
그렇다면 과연 우리들이 직접 설계한 프로그램을 바로 그림으로 나타낼 수 있는 방법이 있을까요? C++의 Boost library에서는 그래프를 생성할 수 있는 Graphviz를 지원합니다. 이산수학의 그래프 이론을 잘 알고 계시다면 Graphviz를 사용 하는 것이 상당히 쉬워질 것입니다.
Graphviz를 사용하기에 앞서서 간단한 그래프 이론에 대해 설명을 드리겠습니다. 예를들어 다음과 같은 그래프가 있다고 가정합니다.
위 그래프는 Graphviz로 생성한 4개의 Vertex와 4개의 Edge를 가지고 있는 그래프입니다. 한 눈으로 봐도 각 vertex인 A, B, C와 D가 각각 edge로 어떻게 연결되었는지 한 번에 알 수 있습니다. 이를 인접 행렬(Adjacency matrix)로 나타내면 다음과 같습니다.
각 행과 열의 첫 번째 부터 A, B, C, D로 보았을 때 나타낸 인접 행렬의 모습입니다. 첫째 열의 경우 [0 1 0 1] 로 나타내어졌는데 각각 A는 두 번째인 B와 4 번째인 D와 연결된 부분을 1로 나타낸 것입니다. 나머지 열의 경우는 직접 위의 그림과 비교해 보신다면 쉽게 아실 수 있으실 겁니다!
지금까지 우리는 무방향 그래프(Undirectional graph)를 설명하였습니다. 다음으로는 Edge에 방향성이 포함되어 있는 방향 그래프(Directional graph)를 보도록 하겠습니다.
위에서 보았던 그래프에 화살표로 방향이 추가된 그래프입니다. 이 그래프 또한 인접 행렬로 다음과 같이 나타낼 수 있습니다.
위에서 보았던 인접 행렬과 다른 점은 각 열은 출발 vertex, 각 행은 도착 vertex를 나타낸 것입니다. 즉 A의 경우 B와 D의 방향으로 향하고 있기 때문에 첫 번째 열의 경우 [0 1 0 1] 순서로 나타나는 것입니다. 반면, C의 경우 무방향 그래프의 경우 A와 같은 [0 1 0 1]이었으나 B로는 연결 방향이 존재하지 않기 때문에 [0 0 0 1]로 나타내는 것입니다. 또한 방향 그래프는 인접 리스트(Adjacency list)로 아래와 같이 나타낼 수 있습니다.
위에서 보았던 방향 그래프를 생각하시면 이해하기 쉬우실 겁니다. 각각의 Vertex인 A와 B, C, D를 생성한 후 각 Vertex가 향하는 방향의 Vertex를 연결 리스트(Linked list)로 이어주는 것이지요. 연결되는 순서는 상관 없습니다. 즉 [A → B → C] 로 표기하거나 [A → C → B]로 표기하여도 모두 같은 값을 나타낸다고 보시면 되겠습니다. 여기서 D로부터 시작하는 방향은 존재하지 않으므로 D는 그 어떤 Vertex와 연결되있지 않음을 위에서 보실 수 있습니다.
그러면 이번에는 위에서 설명한 그래프들을 직접 소스코드로 구현해봅시다. 먼저 Boost library를 컴퓨터에 설치해 줍니다.
$ sudo apt install libboost-all-deb graphviz
다음으로 아래와 같은 소스코드를 입력합니다.
graphviz.cc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include <boost/graph/adjacency_list.hpp> #include <boost/graph/graphviz.hpp> #include <cstdio> using namespace std; struct VertexP { string tag; }; struct EdgeP { string symbol; }; struct GraphP { string orientation; }; typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, VertexP, EdgeP, GraphP, boost::listS> ListGraph; int main() { ListGraph g(GraphP{"Example"}); boost::dynamic_properties dp; dp.property("node_id", get(&VertexP::tag,g)); ofstream dot_file("graph.dot"); string dcmd = "dot -Tpng graph.dot -o graph.png"; // Create the vertexes ListGraph::vertex_descriptor a = add_vertex(VertexP{"A"},g); ListGraph::vertex_descriptor b = add_vertex(VertexP{"B"},g); ListGraph::vertex_descriptor c = add_vertex(VertexP{"C"},g); ListGraph::vertex_descriptor d = add_vertex(VertexP{"D"},g); // Create the edges // A → B add_edge(a, b, g); // B → D add_edge(a, d, g); // B → C add_edge(b, c, g); // C → D add_edge(c, d, g); // Print graph write_graphviz_dp(dot_file, g, dp); std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(dcmd.c_str(), "r"), pclose); if (!pipe) { throw runtime_error("popen() failed!"); } return 0; } | cs |
여기서 소스코드의 중요한 부분을 하나씩 설명해 드리겠습니다.
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, VertexP, EdgeP, GraphP, boost::listS> ListGraph;
위에서 설명드렸던 인접 리스트(Adjacency list)를 만들수 있도록 해주는 Boost library입니다. Graphviz로 그래프를 만들어주기 위해 사용됩니다.
14 15 16 | ListGraph g(GraphP{"Example"}); boost::dynamic_properties dp; dp.property("node_id", get(&VertexP::tag,g)); | cs |
하나의 인접 리스트 변수 g를 선언합니다. 인접 리스트의 이름은 "Example" 입니다. dynamic_properties는 Graphviz에서 Adjacency list의 내용을 설정해 주기 위해 사용되는 변수입니다. 각 vertex의 이름은 VertexP 구조에 저장되므로 16번 줄을 작성하여 Adjacency list 변수 g에 선언해줍니다.
18 19 | ofstream dot_file("graph.dot"); string dcmd = "dot -Tpng graph.dot -o graph.png"; | cs |
Graphviz를 생성해 주기 위해 파일을 생성합니다. 파일의 이름은 "graph.dot"입니다. Graphviz를 이미지로 생성시켜주는 과정은 Terminal의 명령어로 이루어지므로 명령어를 설정해 줍니다. 명령어는 다음과 같습니다.
$ dot -Tpng graph.dot -o graph.png
위 명령어는 생성되는 이미지의 확장명은 png로 설정하며 파일명은 graph.png로 저장하겠다는 의미입니다.
21 22 23 24 25 | // Create the vertexes ListGraph::vertex_descriptor a = add_vertex(VertexP{"A"},g); ListGraph::vertex_descriptor b = add_vertex(VertexP{"B"},g); ListGraph::vertex_descriptor c = add_vertex(VertexP{"C"},g); ListGraph::vertex_descriptor d = add_vertex(VertexP{"D"},g); | cs |
Vertex들을 생성해줍니다. vertex_descriptor에 해당 vertex를 저장해 줍니다.
27 28 29 30 31 32 33 34 35 | // Create the edges // A → B add_edge(a, b, g); // B → D add_edge(a, d, g); // B → C add_edge(b, c, g); // C → D add_edge(c, d, g); | cs |
바로 이 부분이 제가 위에서 말씀드렸던 인접 리스트의 방식을 나타낸 것입니다. 각 vertex와 연결하고자 하는 vertex를 위의 순서대로 입력하시면 우리가 원하는 방식대로 edge가 연결됩니다.
37 38 | // Print graph write_graphviz_dp(dot_file, g, dp); | cs |
지금까지 우리들이 만들었던 그래프를 Graphviz로 만듭니다. 이를 실행하면 dot 파일이 생성됩니다.
1 2 3 4 | std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(dcmd.c_str(), "r"), pclose); if (!pipe) { throw runtime_error("popen() failed!"); } | cs |
dot 파일로 생성된 Graphviz를 이미지로 만들기 위해 실행되는 부분입니다. 이 과정은 Graphviz 프로그램에서 직접 실행되기 때문에 위와 같이 설정해 주시면 직접 사용자가 dot 명령어를 입력하지 않고도 이미지가 생성됩니다.
여기까지 완성되었다면 이제 컴파일을 해줍니다. 다음과 같은 파일을 만들어줍니다.
Makefile
1 2 3 4 5 | CC = g++ CFLAGS = -g -Wall -std=c++11 output:graphviz.cc $(CC) $(CFLAGS) -o output graphviz.cc | cs |
make로 컴파일을 해줍니다.
$ make
이제 컴파일이 실행된 폴더를 확인해보시면 'output' 이라는 이름의 실행파일이 생성됩니다. 이제 실행해봅니다.
$ ./output
그러면 다음과 같은 이미지 파일이 생성되 있는 것을 확인하실 수 있습니다.
다음으로 이번에는 방향 그래프를 만들어 보겠습니다. 위 코드에서 다음 부분만 바꿔주시면 되겠습니다.
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexP, EdgeP, GraphP, boost::listS> ListGraph;
그러면 다음과 같은 방향 그래프가 생성됩니다.
이번에는 생성된 그래프를 회전 시켜보겠습니다. 다음과 같은 코드를 추가시켜주세요.
14 15 16 17 | ListGraph g(GraphP{"Example"}); boost::dynamic_properties dp; dp.property("node_id", get(&VertexP::tag,g)); dp.property("rankdir", boost::make_constant_property<ListGraph*>(string("LR"))); | cs |
그러면 다음과 같이 그래프가 90도 회전합니다.
만약 위의 vertex의 순서를 반대로 하고자 하시는 분이라면 소스코드를 다음과 같이 고쳐주세요.
14 15 16 17 | ListGraph g(GraphP{"Example"}); boost::dynamic_properties dp; dp.property("node_id", get(&VertexP::tag,g)); dp.property("rankdir", boost::make_constant_property<ListGraph*>(string("RL"))); | cs |
그러면 vertex의 순서가 좌우 반전으로 다음과 같이 출력됩니다.
'공대생의 팁' 카테고리의 다른 글
| C++에서 Boost ASIO를 사용하여 TCP 동기화(Blocked) 통신 프로그래밍 (0) | 2019.07.21 |
|---|---|
| 리눅스(우분투)에서 USB가 동작하지 않을 때 수동으로 연결하기(Failed to open the USB device!) (0) | 2019.07.05 |
| Extreme Learning Machine(극학습기계) (0) | 2019.05.15 |
| LSD-SLAM에서 Semi-Dense의 의미 (1) | 2019.03.19 |
| C++ 클래스 객체를 stream으로 통신 및 전달방법 - Boost Serialization(2) [Class를 TCP 소켓 통신으로 전송] (0) | 2019.03.08 |
설정
트랙백
댓글
글
철길도 이사를 간다? 덕하역 이설 전날 풍경(2) [2019.06,16]
2019년도 벌써 절반이 지나가고 또다시 무더운 여름이 다가오고 있습니다. 올해는 부디 좋은 날씨에서 여행을 많이 돌아다니고 싶네요.
이번 포스팅에서는 지난번에 이어서 덕하역 인근 철길 이설 전날의 모습들을 사진으로 남겨보았습니다.
철길도 이사를 간다? 덕하역 이설 전날 풍경(2) [2019.06,16]
건널목 너머에는 셀프빨래방과 카페가 있습니다.
카페의 이름이 '기차길옆에서'라고 되어있군요.
덕하역 방면의 모습입니다.
여기서 좀만 더 나아가면 덕하역이 나타납니다.
남창역 방향을 바라본 모습입니다. 저 멀리 끊어진 교각이 보입니다.
건널목 바로 인근에는 아파트가 들어서 있습니다.
소음이 상당했을 것으로 보입니다.
새로 지어지는 덕하역 방향에서 바라본 모습입니다.
내일부터 모든 열차는 이 곳으로 운행됩니다.
내일부터 운행될 교각임에도 옛 철길과 교차하는 이 부분만 다리가 없습니다.
가까이 와서 보아도 절묘하게 이 부분만 다리로 연결되어 있지 않습니다.
내일부터 연결할 예정인지 인부들이 상당히 바쁘게 개통을 준비하고 있습니다.
보통 이설될 때 기존선에서 다소 떨어진 위치에서 새로운 철길을 만드는데
이 구간은 희안하게 기존부터 사용되어온 철길과 가깝게 교차하는 구간입니다.
그와중에 열차는 그 사이를 통과합니다.
자세히 보니 기존 철교와 높이가 너무 가까워서 미리 만들어서 연결할 수는 없는 상황인것 같습니다.
연결될 부분의 레일이 삐죽 나와있습니다.
교차하는 다리 사이에는 임시로 기둥이 올라와 있습니다.
이 기둥은 지난번에 영주 이설준비중인 구간에서 본 적이 있습니다.
아직 만들어지지 않은 구간을 뺀다면 다리는 거의 다 만들어져 있습니다.
한편 그 아래에서는 인부들의 작업이 한창입니다.
자세히 보니 임시로 올린 기둥에 임시로 철길을 이으려는 모양입니다.
그 때 덕하역 방향에서 열차가 들어옵니다.
이제 이 임시철교가 올라가게 된다면.
이제 이 광경은 내일부터 볼 수 없게 됩니다.
과연 새로 이설될 부분으로 다니는 열차의 모습은 어떠한 모습일까요?
임시철교는 생각보다 꽤 정교하게 만들어져 있습니다.
그래도 이 위로 열차가 다닐것이라는게 조금은 신기해 보입니다.
아마도 오늘 밤 열차가 운행되지 않는 시간에 곧바로 이 다리를 올려서 설치할 모양입니다.
이제 이 건널목도 내일부터는 울리지 않겠지요.
건널목 인근 벤치에 앉아 쉴 수 있는 그늘이 있습니다.
잠시 쉬고 계신 할아버지께서 건널목을 바라보고 계십니다.
이 건널목은 이설 이후 2차선의 도로로 확장될 예정입니다.
이제 이 길은 앞으로 어떤 모습으로 바뀌게 될까요?
꼬불꼬불 철길을 달리던 열차도 이제 내일부터는 쭉 뻗은 교량 위로 달려나갈 것입니다.
철길 너머에는 새로운 덕하역이 건설되고 있습니다.
현재의 덕하역 앞길은 흔한 시골에서 볼 수 있는 풍경입니다.
잠시 읍내를 돌아다니고 오는 사이 안내문이 새로 만들어졌습니다.
아담한 느낌의 이 역사도 이제는 시한부 인생이 되었습니다.
그래도 새로운 역사가 건설이 완료될 때 까지는 계속 사용될 것으로 보입니다.
지금 당장은 임시승강장을 가는 길이 보이지는 않습니다만
내일이면 완성되어 있겠지요?
그 사이에 동대구행 열차가 들어옵니다.
내일부터는 이 모습도 볼 수 없게 됩니다.
열차 마주편에서 부전방면 열차가 들어옵니다.
이제 열차를 타고 동대구역으로 향합니다.
세월이 지날수록 주변에는 항상 있을거라 생각해왔던 것들이 하나둘씩 추억속으로 사라집니다. 앞으로도 이렇게 추억들을 사진으로 하나둘 담아두는 여행을 계속 이어가고자 합니다!
'좌충우돌 여행기 > 국내여행' 카테고리의 다른 글
| 무더운 여름날 김유정역 강촌레일파크 [2019.07.17] (0) | 2019.07.20 |
|---|---|
| 바다가 보이는 간이역 월내역에서 기차가 서던 마지막날 [2019.07.14] (0) | 2019.07.16 |
| 철길도 이사를 간다? 덕하역 이설 전날 풍경(1) [2019.06.16] (0) | 2019.06.19 |
| 도심속 작은 간이역 사상역의 흔적들 [2019.06.16] (2) | 2019.06.18 |
| 싱싱한 해산물들을 맛볼 수 있는 곳 - 해운대 전통시장 [2019.06.15] (0) | 2019.06.17 |