for Robot Artificial Inteligence

Create File or Dir and ignore directory in C++

|

// create image save folder
            std::string image_save_folder_path = m_data_collect_folder_path + "/image";
            struct stat st = {0};
            if(stat(image_save_folder_path.c_str(), &st) == -1)
            {
                mkdir(image_save_folder_path.c_str(), 0777); // convert a C++ string to a C string
                std::cout << "directory does not exist, Create Directory" << std::endl;
            }
            /*  */

https://mymanual.tistory.com/1

Comment  Read more

Loosly Couple vs Tightly Couple Mean

|

Loose coupling means that the degree of dependency between two component is very low.

tight coupling means that the degree of dependancy between two components is very high.

Comment  Read more

Lib과 Share, include를 build안에 생성하고 시스템 안에 있는 library 특징 및 경로, 합치기 등을 해보기

|

특정 LIB에 생성이 안되는 문제

add_library를 이용하여서 특정 function에대한 라이브러리를 생성을 해야되고

install 함수를 이용하여서 해당 project 환경 library에 넣어줘야 한다.

보통 실행 파일은 bin에다 넣고, library 파일은 lib에다 넣는다.

install function중에 share folder에 해당 package folder 및 file들을 보존할 수 있다.

root library(system library)와 local library(user library), project library, ros library등 os에 여러 환경들이 존재한다.

하지만 공통적으로 존재한 폴더들이 있다.

  • bin(실행파일)
  • lib(library)
  • include(library header 파일 및 개발 환경(기능)을 구성하는 header 파일)
  • shared(library package folder)
  • etc

이들은 즉 각 환경에서 가지고 있는 library들이 다르고 header 환경이 다르다. 그렇기 때문에 개발환경에 맞춰서 설치경로도 확인해야되고, 만약 library나 header를 못찾는다고 한다면, 현재 환경에 library가 깔려있는지, 다른 개발환경이면서 library가 깔려있는줄 착각하고 계속 불러오려고 하는지 확인을 해야된다.

만약 환경이 다른 곳에서 개발을 하고 있었으면, export 커맨드나 sh 파일을 실행하여서 환경변수를 맞춰주고 이를

env를 통해 확인한다.

만약 library들을 다 링킹해서 사용하고 싶다면,

export  LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/home/hosting_users/test/module/okname
export  LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/opt/ros/noetic/lib/
export  LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/lib

및 bashrc 파일에

LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/home/hosting_users/test/module/okname
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/opt/ros/noetic/lib/
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/lib

를 추가하고 source, 환경을 먹여주면 된다. 즉 글로벌하게 링킹을 걸어준다면 library 문제 없이 어디 어디서든 사용할 수 있다.

개발 노트

cmake_minimum_required(VERSION 3.0.2)
project(vision_obstacle_pkg)
Compile as C++11, supported in ROS Kinetic and newer
add_compile_options(-std=c++14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
created by chan
set(LOG_SRC ${vision_obstacle_pkg_SOURCE_DIR}/include/vision_obstacle_pkg/log)
file(GLOB SRC_FILES ${LOG_SRC}/.h ${LOG_SRC}/.hpp ${LOG_SRC}/.cpp ${LOG_SRC}/.ipp)
if(MSVC OR MINGW)
list(REMOVE_ITEM SRC_FILES ${LOG_SRC}/crashhandler_unix.cpp)
else()
list(REMOVE_ITEM SRC_FILES ${LOG_SRC}/crashhandler_win.cpp)
endif(MSVC OR MINGW)
set(SRC_FILES ${SRC_FILES} ${SRC_PLATFORM_SPECIFIC})
create the g2log library
include_directories(${LOG_SRC})
MESSAGE(" g2logger files: [${SRC_FILES}]")
add_library(lib_g2logger ${LOG_SRC}/g2log.h ${LOG_SRC}/g2log.cpp ${LOG_SRC}/crashhandler_unix.cpp ${LOG_SRC}/crashhandler_win.cpp ${LOG_SRC}/crashhandler.h ${LOG_SRC}/g2future.h ${LOG_SRC}/g2logworker.h ${LOG_SRC}/g2moveoncopy.hpp ${LOG_SRC}/g2time.cpp ${LOG_SRC}/g2time.h ${LOG_SRC}/shared_queue.h )
add_library(lib_g2logger src/log/active.cpp src/log/crashhandler_unix.cpp src/log/crashhandler_win.cpp src/log/g2log.cpp src/log/g2logworker.cpp src/log/g2time.cpp)
add_library(plane_finder_module src/integral_image.cpp src/multi_plane_segmentation.cpp)
set_target_properties(lib_g2logger PROPERTIES LINKER_LANGUAGE CXX)
add_library(lib_g2logger_shared SHARED ${SRC_FILES})
add_library(lib_g2logger_shared SHARED ${SRC_FILES})
set_target_properties(lib_g2logger_shared PROPERTIES LINKER_LANGUAGE CXX)
created by chan done
created by chan`
find_package(nanoflann REQUIRED)

find_package(catkin REQUIRED COMPONENTS
geometry_msgs
image_transport
nodelet
pluginlib
roscpp
rospy
sensor_msgs
tf2
tf2_geometry_msgs
tf2_ros
message_generation
pcl_ros
message_filters
grid_map_core
grid_map_msgs
grid_map_ros
)
find_package(Boost REQUIRED COMPONENTS system)
find_package(RapidJSON REQUIRED)
################################################
Declare ROS messages, services and actions
################################################
Generate messages in the 'msg' folder
add_message_files(
FILES
DrivableArea.msg
DrivableAreaList.msg
)
add_service_files(
FILES
SaveImage.srv
)
Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
geometry_msgs#
std_msgs
sensor_msgs# tf2_geometry_msgs
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES vision_obstacle_pkg
CATKIN_DEPENDS geometry_msgs image_transport nodelet pluginlib roscpp rospy sensor_msgs tf2 tf2_geometry_msgs tf2_ros pcl_ros message_runtime message_filters
DEPENDS system_lib
)
###########
Build
###########
include_directories(
include
lib
${catkin_INCLUDE_DIRS}
${RapidJSON_INCLUDE_DIRS}
INCLUDE_DIRECTORIES
vision_obstacle_pkg
LOG_SRC # created by chan.
)
src/normal_estimator.cpp src/ndt_estimator.cpp
add_library(plane_finder_module src/integral_image.cpp src/multi_plane_segmentation.cpp)
target_link_libraries(plane_finder_module ${catkin_LIBRARIES})
add_library(ransac_lib src/ndt_plane_estimator.cpp)
add_library(lib_g2logger src/log/active.cpp src/log/crashhandler_unix.cpp src/log/g2log.cpp src/log/g2logworker.cpp src/log/g2time.cpp
src/log/crashhandler_win.cpp
)
add_executable(test_module src/test.cpp)
target_link_libraries(test_module ${catkin_LIBRARIES} ${boost_LIBRARIES})
add_executable(image_saver_module src/image_saver.cpp)
target_link_libraries(image_saver_module ${catkin_LIBRARIES} ${boost_LIBRARIES})
add_library(multicam_ground_extractor_nodelet src/multicam_ground_extractor.cpp)
add_dependencies(multicam_ground_extractor_nodelet ${catkin_EXPORTED_TARGETS})
target_link_libraries(multicam_ground_extractor_nodelet plane_finder_module ransac_lib ${catkin_LIBRARIES})
add_library(multicam_obstacle_extractor src/obstacle_extractor.cpp)
target_link_libraries(multicam_obstacle_extractor PUBLIC plane_finder_module ransac_lib ${catkin_LIBRARIES}
lib_g2logger
nanoflann::nanoflann
)
add_executable(multicam_obstacle_extractor_node src/obstacle_extractor_node.cpp)
target_link_libraries(multicam_obstacle_extractor_node multicam_obstacle_extractor
lib_g2logger ${PLATFORM_LINK_LIBRIES} # created by chan
nanoflann::nanoflann # created by chan
)
add_executable(test_imu_pose src/imu_test.cpp)
target_link_libraries(test_imu_pose ${catkin_LIBRARIES} )
if (UNIX)
target_link_libraries(multicam_obstacle_extractor_node bsd)
endif(UNIX)
install(TARGETS plane_finder_module DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION})
install(TARGETS ransac_lib DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION})
install(TARGETS multicam_obstacle_extractor DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION})
install(TARGETS multicam_obstacle_extractor_node DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
install(TARGETS lib_g2logger DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION})
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
PATTERN ".svn" EXCLUDE)
install(DIRECTORY include/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/include
PATTERN ".svn" EXCLUDE)
install(DIRECTORY cfg/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/cfg
PATTERN ".svn" EXCLUDE)
install(DIRECTORY scripts/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/scripts)

Comment  Read more

Docker 이해(경험으로 부터) 및 명령어들

|

Docker는 git하고 비슷한 성격을 가지고 있다.

Docker Image

Docker Image는 OS와 소프트웨어 환경(Library Dependency)들을 Container라는 형태로 저장이 되어서 가상공간 형태로 운영이 되도록 도와주는 형태입니다.

즉, 1) A…..Z라는 컴퓨터가 있다고 할때, 사용자에 따라 모든 OS환경과 Library Dependency가 다르다.

이에 linux OS 버전의 Docker Image를 통해서 로컬 컴퓨터안에 가상의 환경을 만들고 똑같은 OS버전으로 개발을 할 수 있다.

2) 또한 어떤 개발중인 Software가 있다고 가정을 할때, 다른 분들과 코업하기 위해서 테크리드가 개발중인 software OS버전과 Library Dependency를 공유를 해야할때, 개발환경을 Docker Image를 이용하여서 다른분들께 공유를 하여서, 도커 환경으로부터 동일한 개발환경에서 개발을 할 수 있다.

이것에 대한 이점은 개발환경에 맞게 모든 OS에 설치할 필요가 없고, 도커 이미지를 이용하여서 가상 개발환경에서 바로 시작할수 있다.

git처럼 docker에서 image를 공유하고 있기 때문에 docker서버에 사용하고자 하는 이미지가 존재 한다면

docker pull "image_name"

하면 된다.

또한 git repo처럼 누군가 만들어놓은 사용자의 image를 다운받아서 container로 바로 사용할 수 있다.(container는 docker image기반으로 생성된 가상환경 개발공간이다. 좀 있다 추가적인 설명을 할 것이다.)

Docker Image를 만드는 방법은 두가지가 있다. Docker Container로부터 이미지를 만드는 방법과 Dockerfile(shell script)으로 부터 도커 이미지를 만들수 있다.

Docker Container에서 추가적으로 개발이 되었던 애들을 image로 만들어 공유를 하는 방법과 shelll script type의 Dockerfile을 이용하여서 이미지를 만드는 방법이 있다.

첫번째 방법은 block box느낌의 image를 만드는 것이고, Dockerfile를 이용하여 이미지를 만드는 것은 일정 default 개발환경으로 만들어서 쓰는 것이다.

회사에서는 후자가 많이 쓰인다. 관리가 편하고 트래킹하기 쉽기 때문이다.

Image빌드하는 방법은 DockerFile일때

docker build

을 써주면 된다.

container에서 image를 만드는 방법은 구글링하면 많이 나오기 때문에 확인하여서 하면 될 것같다.

Docker Container

Docker Container는 VM과 같다. Docker Image로부터 Docker Container를 만들고, 로컬한 환경에서 개발을 하는 것이다.

로컬에서 개발된 container는 Docker Image를 만들거나 사용되었던 Dokcer Images간에 하나의 이미지로 Merge도 할 수 있고, 꾸준히 update할 수 있다.

Docker Container를 생성하고 실행하는 것은 쉽다.

생성

docker run -i -t --name test_env osrf/ros /bin/bash

실행

docker exec -t -i test_env /bin/bash

도커환경 설정은 생성할때도 –env를 이용하여서 컨터에너 configuration을 정할 수 있지만, 이후 container에 대한 configuration을 바꾸고 싶다면.

docker update "container id" --env

이런식으로 configuration을 바꿀수 있다.

기타

Docker Compose는 컨터에너 이름 및 속성을 설정할때 사용된다. dockerfile과 마찬가지로, 일정한 Container(개발환경)을 배포하기 위해서 사용이 된다.

그 외에 docker를 더 알아보고 싶다면 아래 링크를 보면 될 것이다.

Docker Tutorial

Docker Ros

심플 명령어

docker realsense ros

그외 잡다한 노트

Docker for Realsense
MAINTINER : CHANGYOLEE
CREATE DOCKERFILE SCRIPT FOR IMAGE OF REALSENSE SDK and (Optional REALSENSE ROS WRAPPER)
TAKE A LOOK AT DOCKERFILE SCRIPT AND LEVERAGE IT TO YOUR DOCKER IMAGE BUILD WORKSPACE
THANK YOU

HOW TO TEST
docker run --rm --net=host --privileged --volume=/dev:/dev -it osrf/ros:noetic-desktop-full /bin/bash -i -c 'roslaunch realsense2_camera rs_rgbd.launch enable_pointcloud:=true align_depth:=false depth_registered_processing:=true align_depth:=true'
If you would like to change ROS_MASTER_URI,
docker run --rm --net=host --privileged --volume=/dev:/dev -it osrf/ros:noetic-desktop-full /bin/bash -i -c 'rossetmaster TARGET_IP; roslaunch realsense2_camera rs_rgbd.launch enable_pointcloud:=true align_depth:=false depth_registered_processing:=true align_depth:=true'
run : execute
--rm : remove container id

# https://bluese05.tistory.com/38
-- net : host( 독립적인 네트워크 영역을 갖지 않고 host와 네트워크를 함께 사용하게 된다)

# Privilige mode
https://tttsss77.tistory.com/153

# Volume
https://www.daleseo.com/docker-volumes-bind-mounts/

# -it
container id

# bin/bash
A Dockerfile for a database engine may run the database command by default. In that case, if you needed an interactive shell, you'll need to do docker run ... /bin/bash . In general, you can't assume that docker run will give you an interactive shell. It's safer to specify /bin/bash if you need a shell.

The key here is the -i argument which instructs bash to act as it has been invoked as an interactive shell. This causes bash to read initialization file ( bashrc files etc)

-c <-https://stackoverflow.com/questions/27631916/what-does-c-mean-as-an-argument-to-bash


## Tutorial
https://jmook.tistory.com/7

# FROM COMMAND MEAN IN DOCKERFILE
https://stackoverflow.com/questions/54000157/purpose-of-from-command-docker-file

https://sseongju1.tistory.com/38

sudo docker run --rm -it --name=test 2c58d7c12e71
//  맨뒤에는 docker image id

DOCKERFILE

FROM osrf/ros:noetic-desktop-full

# LABEL maintainer="changyolee changyolee@hyundai.com"

ENV ROS_DISTRO noetic

# RUN apt -q -qq update && \
#     DEBIAN_FRONTEND=noninteractive apt install -y \
#     software-properties-common \
#     wget \
#     apt-transport-https

RUN apt-get update && apt-get install -y git

RUN git clone https://id:passwords@gitserver.com/realsense_sdk.git
RUN cd realsense_sdk/RealsenseSDK
RUN chmod +x ./usr
RUN yes | cp -r realsense_sdk/RealsenseSDK/usr /

# APT INSTALL
# RUN apt-key adv --keyserver keys.gnupg.net --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE || apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE
# RUN add-apt-repository -y "deb https://librealsense.intel.com/Debian/apt-repo xenial main"
# RUN apt-get update -qq
# RUN apt-get install librealsense2-dkms --allow-unauthenticated -y
# RUN apt-get install librealsense2-dev --allow-unauthenticated -y
#

######### TEST REALSENSE module[CAN SKIP IF ROS CAMERA DIRECTLY DEPLOY BY CI/CD]
######### WHICH MEANS ONLY INSTALL REALSENSE SDK ABOVE SCRIPT
######### SCRIPT THE BELOW IS TEST REALSENSCE ROS WRAPPER RUN OR FAIL BY OUR REALSENSE ROS WRAPPER
######### IF YOU WANT TO MAKE IMAGE OF BOTH OF REALSENSE SDK AND ROS-WAPPER THEN, USE BELOW SCRIPT
######### OTHERWISE SKIP

RUN apt-get -q -qq update && \
  DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-unauthenticated \
  python3-rosinstall \
  python3-catkin-tools \
  ros-${ROS_DISTRO}-jsk-tools \
  ros-${ROS_DISTRO}-rgbd-launch \
  ros-${ROS_DISTRO}-image-transport-plugins \
  ros-${ROS_DISTRO}-image-transport

RUN rosdep update

RUN mkdir -p /catkin_ws/src && cd /catkin_ws/src && \
  git clone --depth 1 https://id:passwords@gitserver.com/realsense_ros_wrapper.git && \
  git clone --depth 1 https://github.com/pal-robotics/ddynamic_reconfigure
RUN cd catkin_ws;
RUN mv /bin/sh /bin/sh_tmp && ln -s /bin/bash /bin/sh
RUN source /opt/ros/${ROS_DISTRO}/setup.bash; cd catkin_ws; catkin build -DCATKIN_ENABLE_TESTING=False -DCMAKE_BUILD_TYPE=Release
RUN rm /bin/sh && mv /bin/sh_tmp /bin/sh
RUN touch /root/.bashrc && \
  echo "source /catkin_ws/devel/setup.bash\n" >> /root/.bashrc && \
  echo "rossetip\n" >> /root/.bashrc && \
  echo "rossetmaster localhost"

RUN rm -rf /var/lib/apt/lists/*

COPY ./ros_entrypoint.sh /
ENTRYPOINT ["/ros_entrypoint.sh"]

CMD ["bash"]

Comment  Read more

understanding cmake by experience and error(0)

|

CMAKE 에서 역할

well written about CMAKE!

https://preshing.com/20170522/learn-cmakes-scripting-language-in-15-minutes/#:~:text=A CMake script defines targets,were defined in a subdirectory.

Sub_Directory: cmake inside of Cmakelist of third party library.

Bag of words library

add_subdirectory(third_party/DBoW2)

SIFT feature library

add_subdirectory(third_party/ezSIFT/platforms/desktop)

Set Role : To define a variable inside a script, use the [set](https://cmake.org/cmake/help/latest/command/set.html) command

set( DBoW2_INCLUDE_DIRS “${CMAKE_CURRENT_SOURCE_DIR}/third_party/DBoW2/include/”) # “/usr/local/include”)

set( DBoW2_LIBS DBoW2) # “/usr/local/lib/libDBoW2.so”)

set( EZSIFT_INCLUDE_DIRS “${CMAKE_CURRENT_SOURCE_DIR}/third_party/ezSIFT/include/” )

set( EZSIFT_LIBS ezsift) # “${CMAKE_CURRENT_SOURCE_DIR}/third_party/ezSIFT/platforms/desktop/build/lib/libezsift.so”)

라이브러리나, 인클루드를 사용자에 의해 지정을 해줄 수 있다.

Sub Directoy를 통해 Library의 lib을 읽는다.

beware, catkin_make read once all cmakelist inside of ws, and if read same library of add_subdirectory in many package, it will cause compile error. add_subdirectoy once is enough.

beware when add_subdirecoty written once on some pacakge, using “Set” to get include and lib of library that you need to specific package.

Catkin_Make, Beware

when you do catkin_make on some workspace, you might get some error about conflicting library name(duplicated when it read all the cmakelist in workspace.

  • please check packages that add_subidrectory has been written another package.
  • if that so, only remain one, please disable the add_subidrecoty line.

Comment  Read more