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()
03 May 2018
|
ROS
Python
ROS2 Simple Keyboard Publisher on Python
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="2">
<name>simple_publisher</name>
<version>0.4.0</version>
<description>Simple Publisher on Python</description>
<maintainer email="snowdeer0314@gmail.com">snowdeer</maintainer>
<license>Apache License 2.0</license>
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>simple_message</exec_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
setup.cfg
[develop]
script-dir=$base/bin/simple_publisher
[install]
install-scripts=$base/bin/simple_publisher
setup.py
from setuptools import setup
package_name = 'simple_publisher'
setup(
name=package_name,
version='0.4.0',
packages=[],
py_modules=[
'simple_publisher'],
install_requires=['setuptools'],
author='snowdeer ',
author_email='snowdeer0314@gmail.com',
maintainer='snowdeer',
maintainer_email='snowdeer0314@gmail.com',
keywords=['ROS'],
description='Simple Publisher on Python',
license='Apache License, Version 2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'simple_publisher = simple_publisher:main'
],
},
)
simple_publisher.py
import threading
import rclpy
import os
from simple_message.msg import SimpleMessage
NODE_NAME = "simple_publisher"
def handle_keyboard(publisher):
while True:
print('\n- Simple Publisher Menu -')
print(' 1. Command (Move along path 1)')
print(' 2. Command (Move along path 2)')
print(' 99. Exit')
menu = input('Input the menu: ')
if menu == '1':
msg = SimpleMessage()
msg.command_id = SimpleMessage.COMMAND_FOR_DEMO_1
publisher.publish(msg)
print(" \n>>> command is published : {0}".format(msg.command_id))
elif menu == '2':
msg = SimpleMessage()
msg.command_id = SimpleMessage.COMMAND_FOR_DEMO_2
publisher.publish(msg)
print(" \n>>> command is published : {0}".format(msg.command_id))
elif menu == '99':
rclpy.shutdown()
os._exit(1)
def main(args=None):
rclpy.init(args=args)
node = rclpy.create_node(NODE_NAME)
publisher = node.create_publisher(SimpleMessage, SimpleMessage.NAME)
th = threading.Thread(target=handle_keyboard, args=(publisher,))
th.start()
try:
rclpy.spin(node)
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()