본문 바로가기

단순 기록

carla ros bridge

ros를 이용해서 시뮬레이션을 조작할 수 있다. ros는 용도가 다양하고 데이터를 주고 받는 어딘가에서 사용할 수 있도록 만들어져있다. 단순 pc간이나 pc에서 임베디드 단말 등 말이다. ros의 장점은 나열하면 너무 많아서 피곤할 정도로 다양한 곳에서 이용될 수 있다.

carla에서도 ros를 통해서 데이터 조작이 가능하다. 노드는 하나의 객체가 되고 객체들간 서로 다양한 방식으로 데이터를 전송한다. 노드는 결국 메세지라는 데이터를 주고 받는데 이러한 데이터를 어떻게 주고 받을지에 대해 토픽에 메세지를 모아두고 publish subscribe service 등으로 정의해두었다. node는 중계기같은 아니면 두 친구사이에서 말을 전달 해주는 친구같은 또는 우체부같은 느낌이다. 그래서 carla에서는 많은 전달자들을 만들어두고 오로지 그 것만 전달할 수 있도록 해두었다. 시간만 전달하거나 신호등의 신호상태만 전달하거나 자동차의 속도만 전달하거나 하는등 말이다. 물론 전달자이므로 상대방이 원하는 내용도 전달이 가능하지만 안듣는 사람도 있다. 자신의 말만 하는 사람 말이다.

그리고 이러한 것들을 묶어서 하나의 package나 launch 단위로 묶어서 실행하기도하고 package나 launch를 묶거나 node를 붙여서 또 새로운 package나 launch 를 만들기도 한다. 복잡하게 보이지만 결국 메세지를 보내는데 필요한 수단들이다. 굳이 비교하자면 launch가 node들이 모여있는 팀인셈이고 그 팀들이 모여서 하나의 큰 사업부가 된듯한 느낌이다. 군대로 말하.... 그렇다.

- node list -
/carla_ego_vehicle_ego_vehicle
/carla_manual_control_ego_vehicle
/carla_ros_bridge
/goal_relay
/initialpose_relay
/rosout

- topic list -
/carla/actor_list
/carla/debug_marker
/carla/ego_vehicle/camera/rgb/front/camera_info
/carla/ego_vehicle/camera/rgb/front/image_color
/carla/ego_vehicle/camera/rgb/view/camera_info
/carla/ego_vehicle/camera/rgb/view/image_color
/carla/ego_vehicle/collision
/carla/ego_vehicle/enable_autopilot
/carla/ego_vehicle/gnss/gnss1/fix
/carla/ego_vehicle/imu
/carla/ego_vehicle/initialpose
/carla/ego_vehicle/lane_invasion
/carla/ego_vehicle/lidar/lidar1/point_cloud
/carla/ego_vehicle/objects
/carla/ego_vehicle/odometry
/carla/ego_vehicle/radar/front/radar
/carla/ego_vehicle/twist_cmd
/carla/ego_vehicle/vehicle_control_cmd
/carla/ego_vehicle/vehicle_control_cmd_manual
/carla/ego_vehicle/vehicle_control_manual_override
/carla/ego_vehicle/vehicle_info
/carla/ego_vehicle/vehicle_status
/carla/marker
/carla/objects
/carla/status
/carla/traffic_lights
/carla/world_info
/clock
/initialpose
/move_base_simple/goal
/rosout
/rosout_agg
/tf
/tf_static

그리고 위 node 중에서 /carla_ros_bridge 조회해보면
------------
Publications:
* /carla/actor_list [carla_msgs/CarlaActorList]
* /carla/ego_vehicle/camera/rgb/front/camera_info [sensor_msgs/CameraInfo]
* /carla/ego_vehicle/camera/rgb/front/image_color [sensor_msgs/Image]
* /carla/ego_vehicle/camera/rgb/view/camera_info [sensor_msgs/CameraInfo]
* /carla/ego_vehicle/camera/rgb/view/image_color [sensor_msgs/Image]
* /carla/ego_vehicle/gnss/gnss1/fix [sensor_msgs/NavSatFix]
* /carla/ego_vehicle/imu [sensor_msgs/Imu]
* /carla/ego_vehicle/lidar/lidar1/point_cloud [sensor_msgs/PointCloud2]
* /carla/ego_vehicle/objects [derived_object_msgs/ObjectArray]
* /carla/ego_vehicle/odometry [nav_msgs/Odometry]
* /carla/ego_vehicle/radar/front/radar [ainstein_radar_msgs/RadarTargetArray]
* /carla/ego_vehicle/vehicle_info [carla_msgs/CarlaEgoVehicleInfo]
* /carla/ego_vehicle/vehicle_status[carla_msgs/CarlaEgoVehicleStatus]
* /carla/marker [visualization_msgs/Marker]
* /carla/objects [derived_object_msgs/ObjectArray]
* /carla/status [carla_msgs/CarlaStatus]
* /carla/traffic_lights [carla_msgs/CarlaTrafficLightStatusList]
* /carla/world_info [carla_msgs/CarlaWorldInfo]
* /clock [rosgraph_msgs/Clock]
* /rosout [rosgraph_msgs/Log]
* /tf [tf2_msgs/TFMessage]
Subscriptions:
* /carla/debug_marker [unknown type]
* /carla/ego_vehicle/enable_autopilot [std_msgs/Bool]
* /carla/ego_vehicle/twist_cmd [unknown type]
* /carla/ego_vehicle/vehicle_control_cmd [unknown type]
* /carla/ego_vehicle/vehicle_control_cmd_manual [carla_msgs/CarlaEgoVehicleControl]
* /carla/ego_vehicle/vehicle_control_manual_override [std_msgs/Bool]
* /clock [rosgraph_msgs/Clock]
Services:
* /carla_ros_bridge/get_loggers
* /carla_ros_bridge/set_logger_level

노드와 리스트 정보는 여기를 참조하면 된다.
https://docs-airlattice.readthedocs.io/en/latest/

/carla_manual_control_ego_vehicle을 실행했을때 노드와 토픽

도식으로 표현하면 이렇다. 이건 RQT를 실행해서 node와 topic을 보면된다.

<설명하자면 carla_ros_bridge 노드는 carla simulator에서 받은 데이터를 carla_manual_control_ego_vehicle 노드로 전달해주는 역할을 하고 있다. 이건 시뮬레이션에서 vehicle의 정보를 내보내주는 것이며 그걸 받은 ego_vehicle노드는 그 데이터를 보고 autopilot과 status 그리고 cmd_manual 토픽으로 시뮬레이션 안에 있는 vehicle을 제어하는 역할을 한다.>

하나의 노드는 위에 보듯이 한줄 한줄 전부 토픽과 그 메세지를 가지고 있으며, 각각의 토픽은 pub sub service 3가지방법으로 메세지를 주거나 받고 있다. 그래서 가만히 생각해보면 위에서 조회했던 토픽 리스트만 보고 있으면 이게 어떤 방식으로 이용되고 있는지 알 수가 없는 상황이다. 노드 리스트를 조회해서 찾고자 하는 노드 info를 조회하면 그때 어떤 토픽이 어떻게 사용되고 있는지 확인이 가능한 것이다.

이러한 구조적인 모습에 아래로 내려갈수록 담고 있는 데이터들의 구분이 너무 많아지고 세분화되는 것이 한눈에 직관적으로 보이지는 않아서 불편하며 규모가 커지면 커질수록 이해하기 더 어려울 수 있다. 그러나 ROS의 이러한 구조가 결국 ROS를 사용하게 만드는 이유 중에 하나라고 생각한다. 계층적인 구조 또는 피라미드 구조이기때문에 재사용성이 좋다는 점이다.

그 다음 계층으로 올라가면 launch가 나온다. 그리고 그 위 계층이 package이다. 여기서는 carla ros bridge가 패키지이다. 이 패키지 안에는 여러개의 launch가 존재한다. 그냥 package명과 launch명이 같게 정한거다. 둘이 같아야하는 규칙은 전혀 없다. 사용자 마음이다.

carla_ros_bridge
carla_ros_bridge_with_example_ego_vehicle
carla_ros_bridge_with_rviz

간단히 설명하면, 가장 기본이되는 launch인 ros bridge은 carla의 기본적인 정보를 주고 받으며 ego_vehicle은 앞에서 말한 ros bridge launch를 포함하고 있으며 추가적으로 이동체를 지도에 생성하고 카메라 라이다 gps 등의 센서를 장착하여 정보를 내보내고 엑셀 브레이크 스티어링휠을 조작할 수 있는 정보를 받는 기능을 더한 launch를 함께 실행한다.

ego_vehicle launch를 실행하면 이렇게 HUD를 포함한 화면이 나온다.

그리고 마지막으로 이렇게 내보낸 데이터를 rivz는 받아서 시각화 시켜주는 툴을 실행하여 보여준다.

RVIZ에서 ego_vehicle의 라이다센서 정보를 ROS 시각화하였다. ADD 눌러서 원하는 Topic을 찾아서 선택하면 나온다.
물론 RGB 카메라도 가능하다.


혹시라도 ROS1 또는 ROS2를 접하게 된다면 각각의 노드가 뭐하는 녀석인가 확인해야하고 각 노드가 가지고 있는 토픽을 통해서 무슨 정보를 얻을 수 있는지부터 확인하는 습관이 필요하다. package나 launch는 그룹화 시켜둔 형태이기때문에 실제 정보는 노드와 토픽을 통해서 확인이 가능하다.

https://www.researchgate.net/figure/A-graph-of-ROS-topics-and-nodes-when-applying-a-waypoint-following-control_fig4_328289438

예시 그림을 간략하게 설명하자면 일단 노드이름을 봐서는 세일링이 가능한 요트인것같다. 가운데 동그라미가 serial 노드인데 시리얼인터페이스를 뜻하는것같다. 보트에 MCU가 있고 각 센서등이 연결되어있어서 usart나 i2c spi 등으로 정보를 수집할 것이다. 그렇게 수집한 데이터 gps sail wind rudder imu imu_dv 등의 정보를 보트 외부에 있는 어딘가에 있을 (제어PC일지도) waypointFollower 노드로 흘려보내는 것 같다. follower 노드에서 데이터를 받으면 아마 어떠한 함수를 통해서 모터를 작동시키는 topic을 다시 보낼것이라고 예상된다. PID 제어등을 통해서 제어할 것같다. 결국 간략하게 정리하면 serial 노드가 데이터를 보내면 follower 노드가 데이터를 받는 구조이고, follower는 데이터를 가공하여 다시 msg나 cmd 토픽으로 serial 노드로 전송하여 자세제어와 속도제어를 통해서 설정 경로를 이동하게 하는 것이다. 암튼 그렇다.

serial 노드의 역할은 세일요트의 센서들의 데이터를 전송해주며 제어신호를 받아들이는 역할을 하며, follower는 센서 데이터를 받아들여 목표설정값과 비교하여 적정한 제어신호를 생성하고 다시 serial로 보내주는 역할을 하게 되는 것이다.

여튼 다시 ros bridge로 돌아와서.
launch를 실행할때는 설정값을 roslanch할때 넣어줄 수 있다.

roslaunch carla_ros_bridge carla_ros_bridge.launch passive:=True

setting값은
use_sim_time
host and port
timeout
passive
synchronous_mode
synchronous_mode_wait_for_vehicle_control_command
fixed_delta_seconds
ego_vehicle
town
register_all_sensors

하나의 launch에는 하나 또는 이상의 node가 있는데 어떠한 메세지를 주고 받을지 정해져있다. 여기서 노드가 메세지를 보낸다면 다른 노드에서 메세지를 받아들이는 노드가 있을것이다. 그리고 어떤 노드는 값은 보내지만 그걸 받는 노드가 없는 것도 있다. 내가 필요할때 subscribe하면 될 일이기때문이다.

예를 들어보면 자율주행 설정 토픽이 존재한다. ego_vehicle을 launch하는 경우, 토픽명이 /carla/ego_vehicle/enable_autopilot 인거같다. 이 토픽은 하나의 단일 메세지만 가지고 있는데 표준 메세지인 std_msgs/Bool 이다. true 아니면 false인데 true값을 전송하면 자율주행이 시작된다.

간단하게 cli로는
rostopic pub -1 /carla/ego_vehicle/enable_autopilot std_msgs/Bool true
딱한번의 메세지를 전송하고 끝난다.

아니면 cpp나 python으로 작성해서 catkin으로 새로운 패키지나 launch를 만들어서 사용 가능하다. 물론 ros1과 ros2는 완전 다른 프로그램이라서 차이를 이해할 필요는 있지만 결국 코드 작성해서 빌드하고 실행하는건 같은 이치다. 기본적으로 ros라이브러리를 include나 import로 불러와서 초기화 작업하고 ros핸들러를 만들어서 publish 또는 subscribe를 만들고, pub는 어떤 데이터를 보낼지 정의하고 sub는 데이터를 받아서 어떻게 처리할지 callback함수로 정의하면 된다. 보통 pub은 loop로 주기적으로 보내고 sub는 emitter처럼 작동시킨다. (정확한 내용은 아니니 그냥 흐름만 참고)

끝.

'단순 기록' 카테고리의 다른 글

run carla in Docker  (0) 2022.08.06
readthedocs  (0) 2021.09.01
carla 지도 생성 with roadrunner  (3) 2021.08.30
docker컨테이너에서 debug with webstorm IDE  (0) 2021.08.15
carla 0.9.12  (0) 2021.08.15