11 Jul 2018
|
리눅스 설정
Ubuntu
iBus 기반 한글 키보드 설치
Ubuntu 18.04 LTS 버전 기준으로 한글 키보드를 설치하는 방법입니다.
Ubuntu 18.04에서 한글어 입력기는 다시 ibus가 되었기 때문에 14.04나 16.04 때와는 다릅니다.
- 메뉴에서
Language Support 실행 → 필요한 파일들 자동으로 설치 됨
- 메뉴에서
Region & Language 실행
Input Sources 항목에서 기본으로 잡혀있던 English는 삭제하고, Korean(Hangul) 선택
- 아래에 있는 설정 버튼 클릭
Hangul Toggle Key의 Add 버튼을 누르고 한글 키 입력(ALT_R 로 표시될 것임)
UIM 기반 한글 설정
한글 설정
Ubuntu 18.04 LTS의 한글 입력기는 iBus로 되어 있습니다. 하지만, Sublime Text나 Visual Studio Code 등의 프로그램에서 한글 입력이 되지 않는 문제가 있어서 방법을 찾아보니 UIM을 이용하면 상당부분 해소가 되는 것 같았습니다. 물론 UIM도 완벽하지는 않은 것 같습니다. Visual Studio Code에서 간 등의 글자 입력이 잘 안되는 경우가 있네요. Sublime이나 IntelliJ 등에서는 문제없이 동작하네요.
설치는 다음과 같습니다.
sudo apt install uim
Settings > Region & Language에서 Manage Installed Language 버튼 클릭.
- 입력기를
UIM으로 변경
- 재부팅
재부팅 후, 프로그램 메뉴에서 Input Method 실행(UIM이라고 타이핑해도 실행됩니다.)
Global Settings에서 Specify default IM 체크
Global Settings > Default Input method를 Byeoru로 선택
Toolbar의 Display를 Never로 설정
Global key bindings 1의 상단의 [Global] on과 [Global] off 항목을 빈 칸으로 설정
BVyeoru key bindings 1의 [Byeoru] on과 [Byeoru] off 키 설정을 Multi_key로 설정
04 Jul 2018
|
C++
chrono 예제
#include
#include
using namespace std;
using namespace chrono;
const int MAX = 200000000;
long long a[MAX];
int main() {
cout << "init ... " << endl;
for (int i = 0; i < MAX; i++) {
a[i] = i;
}
cout << "running... " << endl;
system_clock::time_point start = system_clock::now();
for (int i = 0; i < MAX; i++) {
a[i] = a[i] * a[i];
}
system_clock::time_point end = system_clock::now();
duration sec = end - start;
cout << "Time: " << duration_cast<std::chrono::milliseconds>(sec).count() << endl;
return 0;
}
</pre>
02 Jun 2018
|
C++
클래스와 구조체 차이
C++에서는 클래스(class)도 구조체(struct)도 모두 상속이 가능합니다. 또한 구조체를 상속한 클래스도 구현을 할 수 있고, 그 반대도 가능합니다.
클래스와 구조체의 차이를 굳이 찾으면 다음과 같습니다.
- 클래스 멤버 변수는 기본적으로
private이지만, 구조체는 public 입니다.
template<class T>는 가능하지만, template<struct T>는 가능하지 않습니다. 다만, 키워드적으로 지원하지 않는 것이기 때문에 struct 대신 typename을 사용하면(ex. template<typename T>) 템플릿을 사용할 수 있습니다.
그 외에는 크게 차이가 없지만, 특정 목적에 따라 명시적으로 구분해서 사용하기도 합니다.
- 생성자와 소멸자가 없는 데이터 타입(POD, Plain Old Data)에는 구조체를 사용
- 메소드가 아닌 멤버 변수 위주로 사용할 때는 구조체 사용
POD
POD(Plain Old Data)는 C++11 부터는 표준 레이아웃(Standard layout) 또는 평범한 클래스(Trivial Class)라는 이름으로 대체되었습니다. 하지만 관행적으로 POD라는 용어가 쓰이고 있습니다.
POD는 C++98에서 정의된 용어로 C언어에서 사용되는 평범한 데이터 타입을 의미합니다.
05 May 2018
|
layout: post
title: ROS2 커스텀 Message 및 Service
category: ROS2
tag: [ROS, Python]
—
ROS2 커스텀 Message 및 Service
ROS2에서 사용자 정의 Message와 Service를 정의하는 방법입니다.
package.xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>tree_service</name>
<version>0.4.0</version>
<description>Message and Service of Tree-Service</description>
<maintainer email="snowdeer0314@gmail.com">snowdeer</maintainer>
<license>Apache License 2.0</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<build_depend>builtin_interfaces</build_depend>
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>builtin_interfaces</exec_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(tree_service)
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
endif()
find_package(ament_cmake REQUIRED)
find_package(builtin_interfaces REQUIRED)
find_package(rosidl_default_generators REQUIRED)
set(msg_files
"msg/TreeEvent.msg"
"msg/TreeData.msg"
"msg/TreeNode.msg"
)
set(srv_files
"srv/Tree.srv"
)
rosidl_generate_interfaces(${PROJECT_NAME}
${msg_files}
${srv_files}
DEPENDENCIES builtin_interfaces
)
ament_package()
Message는 ‘msg’라는 서브 디렉토리 밑에, Service는 ‘srv’라는 서브 디렉토리 밑에 위치시킵니다. (위 CMakeLists.txt 파일 참고)
각각의 예제 파일들은 다음과 같습니다. 상단에 상수값을 정의하면 나중에 C++이나 Python에서 해당 메시지나 서비스를 사용할 때 해당 상수값을 이용할 수 있습니다. TOPIC_NAME이라던지 이벤트 ID 등을 상수로 정의하면 편리합니다.
msg/TreeNode.msg
string NAME = "TreeNode"
string id
string parent_id
string type
string name
srv/TreeData
string NAME = "TreeData"
int64 REQUEST_TO_PUBLISH_TREE_DATA = 1
int64 request_id
---
int64 request_id
int64 response
04 May 2018
|
layout: post
title: ROS2 Simple Service Receiver on Python
category: ROS2
tag: [ROS, Python]
—
ROS2 Simple Service Receiver on Python
간단한 ROS2 Service를 수신하고, 커스텀 메시지 배열을 Publish 하는 예제입니다.
from simple_service.srv import SimpleService
from simple_service.msg import Position
from simple_service.msg import RoutingData
import rclpy
global g_publisher
def add_position(positions, x, y, theta):
pos = Position()
pos.x = x;
pos.y = y;
pos.theta = theta
positions.append(pos)
def callback(request, response):
request_id = request.request_id
print("Simple Service Request: {0} ".format(request_id))
if request_id == Navigation.Request.REQUEST_DEMO_MOVE_PATH_1:
msg = RoutingData()
msg.command = RoutingData.COMMAND_MOVE_ALONG_PATH
add_position(msg.positions, 100, 100, 10)
add_position(msg.positions, 500, 200, 10)
add_position(msg.positions, 1000, 1000, 1)
g_publisher.publish(msg)
elif request_id == Navigation.Request.REQUEST_DEMO_MOVE_PATH_2:
msg = RoutingData()
msg.command = RoutingData.COMMAND_MOVE_ALONG_PATH
add_position(msg.positions, -100, -100, 10)
add_position(msg.positions, -500, -200, 10)
add_position(msg.positions, -1000, -1000, 1)
g_publisher.publish(msg)
response.response = 200
return response
def main(args=None):
global g_publisher
rclpy.init(args=args)
node = rclpy.create_node('simple_service_receiver')
g_publisher = node.create_publisher(RoutingData, RoutingData.NAME)
srv = node.create_service(SimpleService, SimpleService.Request.NAME, callback)
rclpy.spin(node)
rclpy.shutdown()
if __name__ == '__main__':
main()