.. Cover Letter

ㅇ 프로젝트/TEAM_Carla-Autoware-bridge

2. (CARLA Autoware Bridge) Autoware ROS상에서 Topic 구독, Carla ROS상에서 Topic 구독

BrainKimDu 2023. 4. 30. 05:14

 

GitHub의 코드 분석

GitHub - Robotics010/carla_autoware_bridge: Addition to carla_ros_bridge to convert carla messages to autoware messages

Carla

  1. 자동차의 Odometry 정보
    • ROS의 nav_msgs의 Odometry 메시지 타입
    • Callback → VelocityReportConverter → 를 통해서 Odometry를 변환하고 velocity_report_msg 형식 (VelocityReport)으 Publishing
    • publishing 하는 Topic의 이름은 '/carla/ego_vehicle/velocity_status'
    • Callback의 과정에서 Header를 붙인다.
  2. 자동차의 status 정보
    • Carla에서 제공하는 메시지 타입 CarlaEgoVehicleStatus
    • Callback → SteeringStatusConverter → 을 통해서 status 정보를 변환하여 steering_status_msg 형식(SteeringReport)으로 publishing
    • publishing 하는 topic의 이름은 '/carla/ego_vehicle/steering_status'

3. 자동차의 lidar 센서 정보

  • Carla/ego_vehicle/lidar에 있으며, ROS의 sensor_msgs.msg의 PointCloud2 라는 메시지 타입
  • Callback → LidarExtendedConverter->을 통해서 lidar 정보를 변환해서 lidar_ex_msg 라는 메시지 형식으로 publishing
  • Callback의 과정에서 Header를 붙인다.
  • publishing 하는 topic의 이름은 '/carla/ego_vehicle/lidar_ex'

 

Autoware

  1. autoware_auto_control_msgs.msg 의 AckermannControlCommand
    • '/control/command/control_cmd' 라는 토픽을 구독하는데, 메시지 타입은 Autoware에서 사용하는 msg임
    • Callback → ControlCommandConverter → 을 통해서 vehicle_control_command_msg 를 (CarlaEgoVehicleControl) publish 한다.
    • publishing 하는 topic의 이름은 '/carla/ego_vehicle/vehicle_control_cmd' 

 

Carla ROS Bridge를 활용하여 Topic 구독하기

ROS 패키지를 제작하고 CARLA에서 발행하는 토픽을 구독해보기

  • Workspace를 만들고, 이 안에 두 개의 패키지를 설치해야합니다. 하나는 ros-carla-bridge 그리고 하나는 우리가 만들 carla-autoware-ros-bridge입니다.
  • 같은 workspace 내부에 있어야 메시지타입을 알 수 있습니다.
cd
mkdir bridgews
cd bridgews
git clone --recurse-submodules https://github.com/carla-simulator/ros-bridge.git src/ros-bridge
cd src
ros2 pkg create --build-type ament_python autoware_carla_bridge
  • 우선 작성하고자 하는 코드는 Carla의 '/carla/ego_vehicle/odometry' 토픽을 구독하고 터미널상에 출력하는 코드를 작성할 것입니다.
  • Autoware_Carla_Bridge 폴더에 carla_subscribe.py 파일을 하나 만들겠습니다.
import rclpy as rp
from rclpy.node import Node
from carla_msgs.msg import CarlaEgoVehicleControl, CarlaEgoVehicleStatus
from autoware_auto_control_msgs.msg import AckermannControlCommand
from nav_msgs.msg import Odometry
from sensor_msgs.msg import PointCloud2
from std_msgs.msg import Header

class Subscriber(Node):
    def __init__(self) -> None:
        super().__init__('carla_autoware_bridge')
        self._odometry_subscriber = self.create_subscription(
            Odometry, '/carla/ego_vehicle/odometry',
            self._odometry_callback, 1)
        
    def _odometry_callback(self, odometry_msg):
        print("carla linking OK")

def main(args=None):
    rp.init(args=args)
    carla_autoware_bridge = Subscriber()

    rp.spin(carla_autoware_bridge)

    carla_autoware_bridge.destroy_node()
    rp.shutdown()


if __name__ == '__main__':
    main()

Setup.py 파일에 위의 코드의 entry point를 알려주어야합니다.

  • 다음의 위치에 다음과 같이 적어 넣습니다.
'carla_subscribe = autoware_carla_bridge.carla_subscribe:main',

저장을 한 후에 colcon build를 진행합니다.

cd bridgews
colcon build

이제 실행을 하면서 topic을 정상적으로 받아오는지 확인을 합니다.
터미널 A : Carla 실행

cd /opt/carla-simulator
./CarlaUE4.sh

터미널 B : ROS-Carla-Bridge 실행

car_ros_bridge
ros2 launch carla_autoware_bridge carla_ros_bridge.launch.py

터미널 C : ego vehicle 생성

car_ros_bridge
ros2 launch carla_spawn_objects carla_spawn_objects.launch.py

터미널 D : carla_manual_control 패키지로 ego vehicle 제어

car_ros_bridge
ros2 launch carla_manual_control carla_manual_control.launch.py

터미널 E : Foxy 환경만 불러와서 다음을 실행
 

foxy
ros2 run autoware_carla_bridge carla_subscribe

 

  • 그러면 다음처럼 구독을 할 수 있습니다.

 

Autoware의 Topic 구독하기

ROS 패키지를 제작하고 Autoware에서 발행하는 토픽을 구독해보기

  • 위의 코드에서 /control/command/control_cmd 을 구독하도록 코드를 작성합니다.
import rclpy as rp
from rclpy.node import Node
from carla_msgs.msg import CarlaEgoVehicleControl, CarlaEgoVehicleStatus
from autoware_auto_control_msgs.msg import AckermannControlCommand
from nav_msgs.msg import Odometry
from sensor_msgs.msg import PointCloud2
from std_msgs.msg import Header

class Subscriber(Node):
    def __init__(self) -> None:
        super().__init__('carla_autoware_bridge')
        self._odometry_subscriber = self.create_subscription(
            Odometry, '/carla/ego_vehicle/odometry',
            self._odometry_callback, 1)
        
        self._ackermann_control_command_subscriber = self.create_subscription(
            AckermannControlCommand, '/control/command/control_cmd',
            self._ackermann_control_command_callback, 1)
        
        
    def _odometry_callback(self, odometry_msg):
        #print(odometry_msg)

    def _ackermann_control_command_callback(self, ackermann_control_command_msg):
        print(ackermann_control_command_msg)
            

def main(args=None):
    rp.init(args=args)
    carla_autoware_bridge = Subscriber()

    rp.spin(carla_autoware_bridge)

    carla_autoware_bridge.destroy_node()
    rp.shutdown()


if __name__ == '__main__':
    main()

저장을 한 후에 colcon build를 진행합니다.

cd bridgews
colcon build

autoware docker 실행

sudo rocker --nvidia --x11 --user --volume $HOME/autoware --volume $HOME/autoware_map --  autoware_build:0.2

autoware 를 실행시킵니다.

ros2 launch autoware_launch planning_simulator.launch.xml map_path:=$HOME/autoware_map/carla-town01 vehicle_model:=sample_vehicle sensor_model:=sample_sensor_kit

 

  • 우선 2D Pose Estimate하여 자동차를 배치한 후에 2D GoalPose로 위치를 지정하면 Autoware 상에서 topic을 발행합니다. 이를 이제 확인해봅시다.
ros2 run autoware_carla_bridge carla_subscribe
  • 오류가 발생합니다. 원인은 AckermannControlCommand 형식의 메시지 타입을 모르기 때문입니다.

우선 우리의 브릿지의 src에 메시지 형식을 집어넣어주어야합니다. 다음을 git clone 하면 됩니다.

 cd bridgews/src
 git clone https://github.com/autowarefoundation/autoware_msgs
 colcon build
# 경우에 따라서는 rosdep 이 필요할 수도 있습니다.
# sudo rosdep init 오류가 발생한다면 무시하고 다음을 진행합니다.
# sudo rosdep update
# rosdep install --from-paths src --ignore-src -r -y
  • 이제 다시 진행합니다. 진행해봅시다. 성공적으로 파일을 받아오는 것을 확인합니다.

CARLA와 autoware를 동시에 실행하면서 topic을 받는지 확인해보자.

 

  • autoware에서 topic을 발행할때 이를 ros상에서 패키지를 제작하여 구독하여 확인합니다.
import rclpy as rp
from rclpy.node import Node
from carla_msgs.msg import CarlaEgoVehicleControl, CarlaEgoVehicleStatus
from autoware_auto_control_msgs.msg import AckermannControlCommand
from nav_msgs.msg import Odometry
from sensor_msgs.msg import PointCloud2
from std_msgs.msg import Header

class Subscriber(Node):
    def __init__(self) -> None:
        super().__init__('carla_autoware_bridge')
        self._odometry_subscriber = self.create_subscription(
            Odometry, '/carla/ego_vehicle/odometry',
            self._odometry_callback, 1)
        
        self._ackermann_control_command_subscriber = self.create_subscription(
            AckermannControlCommand, '/control/command/control_cmd',
            self._ackermann_control_command_callback, 1)
        
        
    def _odometry_callback(self, odometry_msg):
        print("carla linking OK")
        #print(odometry_msg)

    def _ackermann_control_command_callback(self, ackermann_control_command_msg):
        print("autoware linking OK")
            

def main(args=None):
    rp.init(args=args)
    carla_autoware_bridge = Subscriber()

    rp.spin(carla_autoware_bridge)

    carla_autoware_bridge.destroy_node()
    rp.shutdown()


if __name__ == '__main__':
    main()

두 값을 모두 정상적으로 구독할 수 있는 것이 증명되면서, Bridge는 결국 토픽과 토픽을 각자의 메시지 타입에 맞게 연결하는 과정임을 확인합니다.