def __init__(self, carla_actor, parent, communication, synchronous_mode, prefix=None):  # pylint: disable=too-many-arguments
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        :param prefix: the topic prefix to be used for this actor
        :type prefix: string
        """
        if not prefix:
            prefix = 'camera'
        super(Camera, self).__init__(carla_actor=carla_actor,
                                     parent=parent,
                                     communication=communication,
                                     synchronous_mode=synchronous_mode,
                                     prefix=prefix)

        #if self.__class__.__name__ == "Camera":
        #    rospy.logwarn("Created Unsupported Camera Actor"
        #                  "(id={}, parent_id={}, type={}, attributes={})".format(
        #                      self.get_id(), self.get_parent_id(),
        #                      self.carla_actor.type_id, self.carla_actor.attributes))
        #else:
        self.pub1=Publisher(self.get_topic_prefix() + '/camera_info')
        self.pub2=Publisher(self.get_topic_prefix() + '/' + self.get_image_topic_name())
    
        self.cv_bridge = CvBridge()

        self._build_camera_info()
示例#2
0
    def __init__(self, carla_world, setstart, setgoal):
        self.world = carla_world

        #only for circles
        self.map = carla_world.get_map()
        self.ego_vehicle = None
        self.role_name = 'ego_vehicle'
        self.waypoint_publisher = Publisher(
            'carla_ego_vehicle_waypoints'.format(self.role_name))

        # set initial goal

        self.start = setstart
        self.goal = setgoal

        self.current_route = None
        self.goal_subscriber = Subscriber("/carla/{}/goal".format(
            self.role_name))
        self._pose_subscriber = Subscriber(
            "ego_pose_localization"
        )  #, RigidBodyStateStamped, self.pose_callback
        self._pose = RigidBodyStateStamped()
        self.pose_ = PoseStamped()

        self._update_lock = threading.Lock()
        self.update_loop_thread = Thread(target=self.loop)
        self.update_loop_thread.start()
        # use callback to wait for ego vehicle
        self.world.on_tick(self.find_ego_vehicle_actor)
class ObjectSensor(PseudoActor):
    """
    Pseudo object sensor
    """
    def __init__(self, parent, communication, actor_list, filtered_id):
        """
        Constructor
        :param carla_world: carla world object
        :type carla_world: carla.World
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        :param actor_list: current list of actors
        :type actor_list: map(carla-actor-id -> python-actor-object)
        :param filtered_id: id to filter from actor_list
        :type filtered_id: int
        """

        super(ObjectSensor, self).__init__(parent=parent,
                                           communication=communication,
                                           prefix='objects')
        self.actor_list = actor_list
        self.filtered_id = filtered_id
        self.pub1 = Publisher(self.get_topic_prefix())

    def destroy(self):
        """
        Function to destroy this object.
        :return:
        """
        self.actor_list = None
        super(ObjectSensor, self).destroy()

    def update(self, frame, timestamp):
        """
        Function (override) to update this object.
        On update map sends:
        - tf global frame
        :return:
        """
        icv_objects = ObjectArray(header=self.get_msg_header("map"))
        for actor_id in self.actor_list.keys():
            # currently only Vehicles and Walkers are added to the object array
            if self.filtered_id != actor_id:
                actor = self.actor_list[actor_id]
                if isinstance(actor, Vehicle):
                    icv_objects.objects.append(actor.get_object_info())
                elif isinstance(actor, Walker):
                    icv_objects.objects.append(actor.get_object_info())
        self.pub1.publish(icv_objects)
示例#4
0
    def __init__(self):
        """
        Constructor
        """
        self.tf_to_publish = []
        self.msgs_to_publish = []

        self.timestamp = Time()

        #icvTF=TFMessage()

        # needed?
        self.pubtf = Publisher("tf")
        self.pubmarker = Publisher("/carla/marker")
        self.pubclock = Publisher("clock")
        self.publist = Publisher("/carla/actor_list")
    def __init__(self, carla_actor, parent, communication, synchronous_mode):
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        """
        super(Lidar, self).__init__(carla_actor=carla_actor,
                                    parent=parent,
                                    communication=communication,
                                    synchronous_mode=synchronous_mode,
                                    prefix='lidar/' + carla_actor.attributes.get('role_name'))
        self.pub1=Publisher(self.get_topic_prefix()+  "/point_cloud")
    def __init__(self, carla_actor, parent, communication,
                 vehicle_control_applied_callback):
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        """
        super(EgoVehicle,
              self).__init__(carla_actor=carla_actor,
                             parent=parent,
                             communication=communication,
                             prefix=carla_actor.attributes.get('role_name'))

        self.vehicle_info_published = False
        self.vehicle_control_override = False
        self._vehicle_control_applied_callback = vehicle_control_applied_callback
        self.sub1 = Subscriber(self.get_topic_prefix() +
                               "/vehicle_control_cmd")
        self.sub2 = Subscriber(self.get_topic_prefix() +
                               "/vehicle_control_cmd_manual")
        self.sub3 = Subscriber(self.get_topic_prefix() +
                               "/vehicle_control_manual_override")
        self.sub4 = Subscriber(self.get_topic_prefix() + "/enable_autopilot")
        self.sub5 = Subscriber(self.get_topic_prefix() + "/twist_cmd")
        self.Sec_loop = 0.02

        self.control_subscriber = CarlaEgoVehicleControl()
        self.manual_control_subscriber = CarlaEgoVehicleControl()
        self.control_override_subscriber = Bool()
        self.enable_autopilot_subscriber = Bool()
        self.twist_control_subscriber = Twist()

        self.pub1 = Publisher(self.get_topic_prefix() + "/vehicle_info")
        self.pub2 = Publisher(self.get_topic_prefix() + "/vehicle_status")

        self.update_command_thread = Thread(
            target=self._update_commands_thread)
        self.update_command_thread.start()
示例#7
0
class CollisionSensor(Sensor):
    """
    Actor implementation details for a collision sensor
    """
    def __init__(self, carla_actor, parent, communication, synchronous_mode):
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        :param synchronous_mode: use in synchronous mode?
        :type synchronous_mode: bool
        """
        super(CollisionSensor,
              self).__init__(carla_actor=carla_actor,
                             parent=parent,
                             communication=communication,
                             synchronous_mode=synchronous_mode,
                             is_event_sensor=True,
                             prefix="collision")
        self.pub1 = Publisher(self.get_topic_prefix())

    # pylint: disable=arguments-differ
    def sensor_data_updated(self, collision_event):
        """
        Function to wrap the collision event into a icv messsage

        :param collision_event: carla collision event object
        :type collision_event: carla.CollisionEvent
        """
        collision_msg = CarlaCollisionEvent()
        collision_msg.header = self.get_msg_header()
        collision_msg.other_actor_id = collision_event.other_actor.id
        collision_msg.normal_impulse.x = collision_event.normal_impulse.x
        collision_msg.normal_impulse.y = collision_event.normal_impulse.y
        collision_msg.normal_impulse.z = collision_event.normal_impulse.z

        self.pub1.publish(collision_msg)
示例#8
0
class Communication(object):
    """
    Handle communication of icv topics
    """
    def __init__(self):
        """
        Constructor
        """
        self.tf_to_publish = []
        self.msgs_to_publish = []

        self.timestamp = Time()

        #icvTF=TFMessage()

        # needed?
        self.pubtf = Publisher("tf")
        self.pubmarker = Publisher("/carla/marker")
        self.pubclock = Publisher("clock")
        self.publist = Publisher("/carla/actor_list")

    def update_clock(self, carla_timestamp):
        """
        perform the update of the clock

        :param carla_timestamp: the current carla time
        :type carla_timestamp: carla.Timestamp
        :return:
        """
        time = icvTime()
        self.timestamp = time.from_sec(carla_timestamp.elapsed_seconds)

        self.pubclock.publish(self.timestamp)

    def get_current_time(self):
        """
        get the current icv time

        :return: the current icv time
        :rtype icv.Time
        """
        return self.timestamp
    def __init__(self, carla_actor, parent, communication, synchronous_mode):
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        :param synchronous_mode: use in synchronous mode?
        :type synchronous_mode: bool
        """
        super(Gnss, self).__init__(carla_actor=carla_actor,
                                   parent=parent,
                                   communication=communication,
                                   synchronous_mode=synchronous_mode,
                                   prefix="gnss/" +
                                   carla_actor.attributes.get('role_name'))
        self.pub1 = Publisher(self.get_topic_prefix() + "/fix")
示例#10
0
    def __init__(self, carla_world, communication):
        """
        Constructor

        :param carla_world: carla world object
        :type carla_world: carla.World
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        """

        super(WorldInfo, self).__init__(parent=None,
                                        communication=communication,
                                        prefix="world_info")

        self.carla_map = carla_world.get_map()

        self.map_published = False
        self.pub1=Publisher(self.get_topic_prefix() )
        self.update_loop_thread = Thread(target=self.loop)
        self.update_loop_thread.start() 
    def __init__(self, carla_actor, parent, communication, synchronous_mode):
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        :param synchronous_mode: use in synchronous mode?
        :type synchronous_mode: bool
        """
        super(LaneInvasionSensor,
              self).__init__(carla_actor=carla_actor,
                             parent=parent,
                             communication=communication,
                             synchronous_mode=synchronous_mode,
                             is_event_sensor=True,
                             prefix="lane_invasion")
        self.pub1 = Publisher(self.get_topic_prefix())
    def __init__(self, parent, communication, actor_list, filtered_id):
        """
        Constructor
        :param carla_world: carla world object
        :type carla_world: carla.World
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        :param actor_list: current list of actors
        :type actor_list: map(carla-actor-id -> python-actor-object)
        :param filtered_id: id to filter from actor_list
        :type filtered_id: int
        """

        super(ObjectSensor, self).__init__(parent=parent,
                                           communication=communication,
                                           prefix='objects')
        self.actor_list = actor_list
        self.filtered_id = filtered_id
        self.pub1 = Publisher(self.get_topic_prefix())
class Gnss(Sensor):
    """
    Actor implementation details for gnss sensor
    """
    def __init__(self, carla_actor, parent, communication, synchronous_mode):
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        :param synchronous_mode: use in synchronous mode?
        :type synchronous_mode: bool
        """
        super(Gnss, self).__init__(carla_actor=carla_actor,
                                   parent=parent,
                                   communication=communication,
                                   synchronous_mode=synchronous_mode,
                                   prefix="gnss/" +
                                   carla_actor.attributes.get('role_name'))
        self.pub1 = Publisher(self.get_topic_prefix() + "/fix")

    # pylint: disable=arguments-differ
    def sensor_data_updated(self, carla_gnss_event):
        """
        Function to transform a received gnss event into a icv NavSatFix message

        :param carla_gnss_event: carla gnss event object
        :type carla_gnss_event: carla.GnssEvent
        """
        navsatfix_msg = NavSatFix()
        navsatfix_msg.header = self.get_msg_header(
            timestamp=carla_gnss_event.timestamp)
        navsatfix_msg.latitude = carla_gnss_event.latitude
        navsatfix_msg.longitude = carla_gnss_event.longitude
        navsatfix_msg.altitude = carla_gnss_event.altitude
        self.pub1.publish(navsatfix_msg)
class LaneInvasionSensor(Sensor):
    """
    Actor implementation details for a lane invasion sensor
    """
    def __init__(self, carla_actor, parent, communication, synchronous_mode):
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        :param synchronous_mode: use in synchronous mode?
        :type synchronous_mode: bool
        """
        super(LaneInvasionSensor,
              self).__init__(carla_actor=carla_actor,
                             parent=parent,
                             communication=communication,
                             synchronous_mode=synchronous_mode,
                             is_event_sensor=True,
                             prefix="lane_invasion")
        self.pub1 = Publisher(self.get_topic_prefix())

    # pylint: disable=arguments-differ
    def sensor_data_updated(self, lane_invasion_event):
        """
        Function to wrap the lane invasion event into a icv messsage

        :param lane_invasion_event: carla lane invasion event object
        :type lane_invasion_event: carla.LaneInvasionEvent
        """
        lane_invasion_msg = CarlaLaneInvasionEvent()
        lane_invasion_msg.header = self.get_msg_header()
        for marking in lane_invasion_event.cicvsed_lane_markings:
            lane_invasion_msg.cicvsed_lane_markings.append(marking.type)
        self.pub1.publish(lane_invasion_msg)
class EgoVehicle(Vehicle):
    """
    Vehicle implementation details for the ego vehicle
    """
    def __init__(self, carla_actor, parent, communication,
                 vehicle_control_applied_callback):
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        """
        super(EgoVehicle,
              self).__init__(carla_actor=carla_actor,
                             parent=parent,
                             communication=communication,
                             prefix=carla_actor.attributes.get('role_name'))

        self.vehicle_info_published = False
        self.vehicle_control_override = False
        self._vehicle_control_applied_callback = vehicle_control_applied_callback
        self.sub1 = Subscriber(self.get_topic_prefix() +
                               "/vehicle_control_cmd")
        self.sub2 = Subscriber(self.get_topic_prefix() +
                               "/vehicle_control_cmd_manual")
        self.sub3 = Subscriber(self.get_topic_prefix() +
                               "/vehicle_control_manual_override")
        self.sub4 = Subscriber(self.get_topic_prefix() + "/enable_autopilot")
        self.sub5 = Subscriber(self.get_topic_prefix() + "/twist_cmd")
        self.Sec_loop = 0.02

        self.control_subscriber = CarlaEgoVehicleControl()
        self.manual_control_subscriber = CarlaEgoVehicleControl()
        self.control_override_subscriber = Bool()
        self.enable_autopilot_subscriber = Bool()
        self.twist_control_subscriber = Twist()

        self.pub1 = Publisher(self.get_topic_prefix() + "/vehicle_info")
        self.pub2 = Publisher(self.get_topic_prefix() + "/vehicle_status")

        self.update_command_thread = Thread(
            target=self._update_commands_thread)
        self.update_command_thread.start()

    def get_marker_color(self):
        """
        Function (override) to return the color for marker messages.

        The ego vehicle uses a different marker color than other vehicles.

        :return: the color used by a ego vehicle marker
        :rtpye : std_msgs.ColorRGBA
        """
        color = ColorRGBA()
        color.r = 0
        color.g = 255
        color.b = 0
        return color

    def send_vehicle_msgs(self):
        """
        send messages related to vehicle status

        :return:
        """

        vehicle_status = CarlaEgoVehicleStatus(
            header=self.get_msg_header("map"))
        vehicle_status.velocity = self.get_vehicle_speed_abs(self.carla_actor)
        vehicle_status.acceleration.linear = transforms.carla_vector_to_icv_vector_rotated(
            self.carla_actor.get_acceleration(),
            self.carla_actor.get_transform().rotation)
        vehicle_status.orientation = self.get_current_icv_pose().orientation
        vehicle_status.control.throttle = self.carla_actor.get_control(
        ).throttle
        vehicle_status.control.steer = self.carla_actor.get_control().steer
        vehicle_status.control.brake = self.carla_actor.get_control().brake
        vehicle_status.control.hand_brake = self.carla_actor.get_control(
        ).hand_brake
        vehicle_status.control.reverse = self.carla_actor.get_control().reverse
        vehicle_status.control.gear = self.carla_actor.get_control().gear
        vehicle_status.control.manual_gear_shift = self.carla_actor.get_control(
        ).manual_gear_shift
        self.pub2.publish(vehicle_status)
        # only send vehicle once (in latched-mode)
        if not self.vehicle_info_published:
            self.vehicle_info_published = True
            vehicle_info = CarlaEgoVehicleInfo()
            vehicle_info.id = self.carla_actor.id
            vehicle_info.type = self.carla_actor.type_id
            vehicle_info.rolename = self.carla_actor.attributes.get(
                'role_name')
            vehicle_physics = self.carla_actor.get_physics_control()

            for wheel in vehicle_physics.wheels:
                wheel_info = CarlaEgoVehicleInfoWheel()
                wheel_info.tire_friction = wheel.tire_friction
                wheel_info.damping_rate = wheel.damping_rate
                wheel_info.max_steer_angle = math.radians(
                    wheel.max_steer_angle)
                vehicle_info.wheels.append(wheel_info)

            vehicle_info.max_rpm = vehicle_physics.max_rpm
            vehicle_info.max_rpm = vehicle_physics.max_rpm
            vehicle_info.moi = vehicle_physics.moi
            vehicle_info.damping_rate_full_throttle = vehicle_physics.damping_rate_full_throttle
            vehicle_info.damping_rate_zero_throttle_clutch_engaged = \
                vehicle_physics.damping_rate_zero_throttle_clutch_engaged
            vehicle_info.damping_rate_zero_throttle_clutch_disengaged = \
                vehicle_physics.damping_rate_zero_throttle_clutch_disengaged
            vehicle_info.use_gear_autobox = vehicle_physics.use_gear_autobox
            vehicle_info.gear_switch_time = vehicle_physics.gear_switch_time
            vehicle_info.clutch_strength = vehicle_physics.clutch_strength
            vehicle_info.mass = vehicle_physics.mass
            vehicle_info.drag_coefficient = vehicle_physics.drag_coefficient
            vehicle_info.center_of_mass.x = vehicle_physics.center_of_mass.x
            vehicle_info.center_of_mass.y = vehicle_physics.center_of_mass.y
            vehicle_info.center_of_mass.z = vehicle_physics.center_of_mass.z

            self.pub1.publish(vehicle_info)

    def update(self, frame, timestamp):
        """
        Function (override) to update this object.

        On update ego vehicle calculates and sends the new values for VehicleControl()

        :return:
        """
        self.send_vehicle_msgs()
        super(EgoVehicle, self).update(frame, timestamp)

    def _update_commands_thread(self):
        time.sleep(self.Sec_loop)

        if self.sub4.getstate():
            self.sub4.reset()
            self.enable_autopilot_updated()

        if self.sub3.getstate():
            self.sub3.reset()
            self.control_command_override()

        if self.sub1.getstate() or self.sub2.getstate():
            self.sub1.reset()
            self.sub2.reset()
            self.control_command_updated()

        if self.sub5.getstate():
            self.sub3.reset()
            self.twist_command_updated()

    def destroy(self):
        """
        Function (override) to destroy this object.

        Terminate icv subscriptions
        Finally forward call to super class.

        :return:
        """
        #rospy.logdebug("Destroy Vehicle(id={})".format(self.get_id()))
        #self.control_subscriber.unregister()
        self.control_subscriber = None
        #self.enable_autopilot_subscriber.unregister()
        self.enable_autopilot_subscriber = None
        #self.twist_control_subscriber.unregister()
        self.twist_control_subscriber = None
        #self.control_override_subscriber.unregister()
        self.control_override_subscriber = None
        #self.manual_control_subscriber.unregister()
        self.manual_control_subscriber = None
        super(EgoVehicle, self).destroy()

    def twist_command_updated(self):
        """
        Set angular/linear velocity (this does not respect vehicle dynamics)
        """
        if not self.vehicle_control_override:
            sub5.subscribe(self.twist_control_subscriber)
            twist = self.twist_control_subscriber
            angular_velocity = Vector3D()
            angular_velocity.z = math.degrees(twist.angular.z)

            rotation_matrix = transforms.carla_rotation_to_numpy_rotation_matrix(
                self.carla_actor.get_transform().rotation)
            linear_vector = numpy.array(
                [twist.linear.x, twist.linear.y, twist.linear.z])
            rotated_linear_vector = rotation_matrix.dot(linear_vector)
            linear_velocity = Vector3D()
            linear_velocity.x = rotated_linear_vector[0]
            linear_velocity.y = -rotated_linear_vector[1]
            linear_velocity.z = rotated_linear_vector[2]

            #    rospy.logdebug("Set velocity linear: {}, angular: {}".format(
            #        linear_velocity, angular_velocity))
            self.carla_actor.set_velocity(linear_velocity)
            self.carla_actor.set_angular_velocity(angular_velocity)

    def control_command_override(self):
        """
        Set the vehicle control mode according to icv topic
        """
        self.sub3.subscribe(self.control_override_subscriber)
        self.vehicle_control_override

    def control_command_updated(self):
        """
        Receive a CarlaEgoVehicleControl msg and send to CARLA

        This function gets called whenever a icv CarlaEgoVehicleControl is received.
        If the mode is valid (either normal or manual), the received icv message is
        converted into carla.VehicleControl command and sent to CARLA.
        This bridge is not responsible for any restrictions on velocity or steering.
        It's just forwarding the icv input to CARLA

        :param manual_override: manually override the vehicle control command
        :param icv_vehicle_control: current vehicle control input received via icv
        :type icv_vehicle_control: carla_msgs.msg.CarlaEgoVehicleControl
        :return:
        """
        if self.vehicle_control_override:
            sub2.subscribe(self.manual_control_subscriber)
            icv_vehicle_control = self.manual_control_subscriber
        else:
            sub1.subscribe(self.control_subscriber)
            icv_vehicle_control = self.control_subscriber

        vehicle_control = VehicleControl()
        vehicle_control.hand_brake = icv_vehicle_control.hand_brake
        vehicle_control.brake = icv_vehicle_control.brake
        vehicle_control.steer = icv_vehicle_control.steer
        vehicle_control.throttle = icv_vehicle_control.throttle
        vehicle_control.reverse = icv_vehicle_control.reverse
        self.carla_actor.apply_control(vehicle_control)
        self._vehicle_control_applied_callback(self.get_id())

    def enable_autopilot_updated(self):
        """
        Enable/disable auto pilot

        :param enable_auto_pilot: should the autopilot be enabled?
        :type enable_auto_pilot: std_msgs.Bool
        :return:
        """
        #rospy.logdebug("Ego vehicle: Set autopilot to {}".format(enable_auto_pilot.data))
        self.sub4.subscribe(self.enable_autopilot_subscriber)
        self.carla_actor.set_autopilot(self.enable_autopilot_subscriber.data)

    @staticmethod
    def get_vector_length_squared(carla_vector):
        """
        Calculate the squared length of a carla_vector
        :param carla_vector: the carla vector
        :type carla_vector: carla.Vector3D
        :return: squared vector length
        :rtype: float64
        """
        return carla_vector.x * carla_vector.x + \
            carla_vector.y * carla_vector.y + \
            carla_vector.z * carla_vector.z

    @staticmethod
    def get_vehicle_speed_squared(carla_vehicle):
        """
        Get the squared speed of a carla vehicle
        :param carla_vehicle: the carla vehicle
        :type carla_vehicle: carla.Vehicle
        :return: squared speed of a carla vehicle [(m/s)^2]
        :rtype: float64
        """
        return EgoVehicle.get_vector_length_squared(
            carla_vehicle.get_velocity())

    @staticmethod
    def get_vehicle_speed_abs(carla_vehicle):
        """
        Get the absolute speed of a carla vehicle
        :param carla_vehicle: the carla vehicle
        :type carla_vehicle: carla.Vehicle
        :return: speed of a carla vehicle [m/s >= 0]
        :rtype: float64
        """
        speed = math.sqrt(EgoVehicle.get_vehicle_speed_squared(carla_vehicle))
        return speed
示例#16
0
class WorldInfo(PseudoActor):

    """
    Publish the map
    """

    def __init__(self, carla_world, communication):
        """
        Constructor

        :param carla_world: carla world object
        :type carla_world: carla.World
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        """

        super(WorldInfo, self).__init__(parent=None,
                                        communication=communication,
                                        prefix="world_info")

        self.carla_map = carla_world.get_map()

        self.map_published = False
        self.pub1=Publisher(self.get_topic_prefix() )
        self.update_loop_thread = Thread(target=self.loop)
        self.update_loop_thread.start() 

    def loop(self):
        while True:
            time.sleep(10)
            self.map_published = False
         





    def destroy(self):
        """
        Function (override) to destroy this object.

        Remove reference to carla.Map object.
        Finally forward call to super class.

        :return:
        """
        #rospy.logdebug("Destroying WorldInfo()")
        self.carla_map = None
        super(WorldInfo, self).destroy()

    def update(self, frame, timestamp):
        """
        Function (override) to update this object.

        :return:
        """
        if not self.map_published:
            #print("send map")
            open_drive_msg = CarlaWorldInfo()
            open_drive_msg.map_name = self.carla_map.name
            open_drive_msg.opendrive = self.carla_map.to_opendrive()
            self.pub1.publish( open_drive_msg)
            self.map_published = True
class Lidar(Sensor):

    """
    Actor implementation details for lidars
    """

    def __init__(self, carla_actor, parent, communication, synchronous_mode):
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        """
        super(Lidar, self).__init__(carla_actor=carla_actor,
                                    parent=parent,
                                    communication=communication,
                                    synchronous_mode=synchronous_mode,
                                    prefix='lidar/' + carla_actor.attributes.get('role_name'))
        self.pub1=Publisher(self.get_topic_prefix()+  "/point_cloud")

    def get_icv_sensor_transform(self, transform):
        """
        Function (override) to modify the tf messages sent by this lidar.

        The lidar transformation has to be altered:
        for some reasons lidar sends already a rotated cloud,
        so herein, we need to ignore pitch and roll

        :return: the filled tf message
        :rtype: geometry_msgs.msg.TransformStamped
        """
        tf_msg = super(Lidar, self).get_icv_sensor_transform(transform)

        rotation = tf_msg.transform.rotation
        quat = [rotation.x, rotation.y, rotation.z, rotation.w]
        dummy_roll, dummy_pitch, yaw = transformations.euler_from_quaternion(
            quat)
        # set roll and pitch to zero
        quat = transformations.quaternion_from_euler(0, 0, yaw)
        tf_msg.transform.rotation = trans.numpy_quaternion_to_icv_quaternion(
            quat)
        return tf_msg

    # pylint: disable=arguments-differ
    def sensor_data_updated(self, carla_lidar_measurement):
        """
        Function to transform the a received lidar measurement into a icv point cloud message

        :param carla_lidar_measurement: carla lidar measurement object
        :type carla_lidar_measurement: carla.LidarMeasurement
        """
        header = self.get_msg_header()

        lidar_data = numpy.frombuffer(
            carla_lidar_measurement.raw_data, dtype=numpy.float32)
        lidar_data = numpy.reshape(
            lidar_data, (int(lidar_data.shape[0] / 3), 3))
        # we take the oposite of y axis
        # (as lidar point are express in left handed coordinate system, and icv need right handed)
        # we need a copy here, because the data are read only in carla numpy
        # array
        lidar_data = -lidar_data
        # we also need to permute x and y
        lidar_data = lidar_data[..., [1, 0, 2]]
        point_cloud_msg = create_cloud_xyz32(header, lidar_data)
        self.pub1.publish(point_cloud_msg)
class Camera(Sensor):

    """
    Sensor implementation details for cameras
    """

    # global cv bridge to convert image between opencv and icv

    def __init__(self, carla_actor, parent, communication, synchronous_mode, prefix=None):  # pylint: disable=too-many-arguments
        """
        Constructor

        :param carla_actor: carla actor object
        :type carla_actor: carla.Actor
        :param parent: the parent of this
        :type parent: carla_icv_bridge.Parent
        :param communication: communication-handle
        :type communication: carla_icv_bridge.communication
        :param prefix: the topic prefix to be used for this actor
        :type prefix: string
        """
        if not prefix:
            prefix = 'camera'
        super(Camera, self).__init__(carla_actor=carla_actor,
                                     parent=parent,
                                     communication=communication,
                                     synchronous_mode=synchronous_mode,
                                     prefix=prefix)

        #if self.__class__.__name__ == "Camera":
        #    rospy.logwarn("Created Unsupported Camera Actor"
        #                  "(id={}, parent_id={}, type={}, attributes={})".format(
        #                      self.get_id(), self.get_parent_id(),
        #                      self.carla_actor.type_id, self.carla_actor.attributes))
        #else:
        self.pub1=Publisher(self.get_topic_prefix() + '/camera_info')
        self.pub2=Publisher(self.get_topic_prefix() + '/' + self.get_image_topic_name())
    
        self.cv_bridge = CvBridge()

        self._build_camera_info()

    def _build_camera_info(self):
        """
        Private function to compute camera info

        camera info doesn't change over time
        """
        camera_info = CameraInfo()
        # store info without header
        camera_info.header = None
        camera_info.width = int(self.carla_actor.attributes['image_size_x'])
        camera_info.height = int(self.carla_actor.attributes['image_size_y'])
        camera_info.distortion_model = 'plumb_bob'
        cx = camera_info.width / 2.0
        cy = camera_info.height / 2.0
        fx = camera_info.width / (
            2.0 * math.tan(float(self.carla_actor.attributes['fov']) * math.pi / 360.0))
        fy = fx
        camera_info.K = [fx, 0, cx, 0, fy, cy, 0, 0, 1]
        camera_info.D = [0, 0, 0, 0, 0]
        camera_info.R = [1.0, 0, 0, 0, 1.0, 0, 0, 0, 1.0]
        camera_info.P = [fx, 0, cx, 0, 0, fy, cy, 0, 0, 0, 1.0, 0]
        self._camera_info = camera_info

    # pylint: disable=arguments-differ
    def sensor_data_updated(self, carla_image):
        """
        Function (override) to transform the received carla image data
        into a icv image message

        :param carla_image: carla image object
        :type carla_image: carla.Image
        """
        #if ((carla_image.height != self._camera_info.height) or
        #        (carla_image.width != self._camera_info.width)):
        #    rospy.logerr(
        #        "Camera{} received image not matching configuration".format(self.get_prefix()))
        image_data_array, encoding = self.get_carla_image_data_array(
            carla_image=carla_image)
        img_msg = self.cv_bridge.cv2_to_imgmsg(image_data_array, encoding=encoding)
        # the camera data is in respect to the camera's own frame
        img_msg.header = self.get_msg_header()

        cam_info = self._camera_info
        cam_info.header = img_msg.header

        self.pub1.publish(cam_info)
        self.pub2.publish(img_msg)

    def get_icv_sensor_transform(self, transform):
        """
        Function (override) to modify the tf messages sent by this camera.

        The camera transformation has to be altered to look at the same axis
        as the opencv projection in order to get easy depth cloud for RGBD camera

        :return: the filled tf message
        :rtype: geometry_msgs.msg.TransformStamped
        """
        tf_msg = super(Camera, self).get_icv_sensor_transform(transform)
        rotation = tf_msg.transform.rotation
        quat = [rotation.x, rotation.y, rotation.z, rotation.w]
        quat_swap = transformations.quaternion_from_matrix(
            [[0, 0, 1, 0],
             [-1, 0, 0, 0],
             [0, -1, 0, 0],
             [0, 0, 0, 1]])
        quat = transformations.quaternion_multiply(quat, quat_swap)

        tf_msg.transform.rotation = trans.numpy_quaternion_to_icv_quaternion(
            quat)
        return tf_msg

    @abstractmethod
    def get_carla_image_data_array(self, carla_image):
        """
        Virtual function to convert the carla image to a numpy data array
        as input for the cv_bridge.cv2_to_imgmsg() function

        :param carla_image: carla image object
        :type carla_image: carla.Image
        :return tuple (numpy data array containing the image information, encoding)
        :rtype tuple(numpy.ndarray, string)
        """
        raise NotImplementedError(
            "This function has to be re-implemented by derived classes")

    @abstractmethod
    def get_image_topic_name(self):
        """
        Virtual function to provide the actual image topic name

        :return image topic name
        :rtype string
        """
        raise NotImplementedError(
            "This function has to be re-implemented by derived classes")
示例#19
0
class CarlaToRosWaypointConverter(object):
    """
    This class generates a plan of waypoints to follow.

    The calculation is done whenever:
    - the hero vehicle appears
    - a new goal is set
    """
    WAYPOINT_DISTANCE = 2.0

    def __init__(self, carla_world, setstart, setgoal):
        self.world = carla_world

        #only for circles
        self.map = carla_world.get_map()
        self.ego_vehicle = None
        self.role_name = 'ego_vehicle'
        self.waypoint_publisher = Publisher(
            'carla_ego_vehicle_waypoints'.format(self.role_name))

        # set initial goal

        self.start = setstart
        self.goal = setgoal

        self.current_route = None
        self.goal_subscriber = Subscriber("/carla/{}/goal".format(
            self.role_name))
        self._pose_subscriber = Subscriber(
            "ego_pose_localization"
        )  #, RigidBodyStateStamped, self.pose_callback
        self._pose = RigidBodyStateStamped()
        self.pose_ = PoseStamped()

        self._update_lock = threading.Lock()
        self.update_loop_thread = Thread(target=self.loop)
        self.update_loop_thread.start()
        # use callback to wait for ego vehicle
        self.world.on_tick(self.find_ego_vehicle_actor)

    def loop(self):
        while True:
            time.sleep(0.25)
            self.publish_waypoints()
            '''
            if self.goal_subscriber.getstate():
                self.goal_subscriber.reset()
                print "goal?"
                self.goal_subscriber.subscribe(self.pose_)
                self.on_goal(self.pose_)'''
            '''
            if self._pose_subscriber.getstate():
                self._pose_subscriber.reset()
                self._pose_subscriber.subscribe(self._pose)
                self.pose_callback(self._pose)'''

    def pose_callback(self, msg):
        # Note: Here we actually assume that pose is updating at highest frequency
        print("We received pose in carla waypoint publisher")
        #self.publish_waypoints()

    def on_goal(self, goal):
        """
        Callback for /move_base_simple/goal

        Receiving a goal (e.g. from RVIZ '2D Nav Goal') triggers a new route calculation.

        :return:
        """
        carla_goal = carla.Transform()
        carla_goal.location.x = goal.pose.position.x
        carla_goal.location.y = -goal.pose.position.y
        carla_goal.location.z = goal.pose.position.z + 2  # 2m above ground
        quaternion = (goal.pose.orientation.x, goal.pose.orientation.y,
                      goal.pose.orientation.z, goal.pose.orientation.w)
        _, _, yaw = euler_from_quaternion(quaternion)
        carla_goal.rotation.yaw = -math.degrees(yaw)

        self.goal = carla_goal
        print("start to reroute")
        self.reroute()

    def reroute(self):
        """
        Triggers a rerouting
        """
        if self.ego_vehicle is None or self.goal is None:
            # no ego vehicle, remove route if published
            self.current_route = None
            self.publish_waypoints()
        else:
            self.current_route = self.calculate_route(self.start, self.goal)
        self.publish_waypoints()

    def find_ego_vehicle_actor(self, _):
        """
        Look for an carla actor with name 'ego_vehicle'
        """
        with self._update_lock:
            hero = None
            for actor in self.world.get_actors():
                if actor.attributes.get('role_name') == self.role_name:
                    hero = actor
                    break

            ego_vehicle_changed = False
            if hero is None and self.ego_vehicle is not None:
                ego_vehicle_changed = True

            if not ego_vehicle_changed and hero is not None and self.ego_vehicle is None:
                ego_vehicle_changed = True

            if not ego_vehicle_changed and hero is not None and \
                    self.ego_vehicle is not None and hero.id != self.ego_vehicle.id:
                ego_vehicle_changed = True

            if ego_vehicle_changed:
                #rospy.loginfo("Ego vehicle changed.")
                self.ego_vehicle = hero
                self.reroute()

    def calculate_route(self, start, goal):
        """
        Calculate a route from the current location to 'goal'
        """
        # rospy.loginfo("Calculating route to x={}, y={}, z={}".format(
        #     goal.location.x,
        #     goal.location.y,
        #     goal.location.z))

        dao = GlobalRoutePlannerDAO(self.world.get_map(), 1)
        grp = GlobalRoutePlanner(dao)
        grp.setup()
        route = grp.trace_route(
            carla.Location(start.location.x, start.location.y,
                           start.location.z),
            carla.Location(goal.location.x, goal.location.y, goal.location.z))

        return route

    def publish_waypoints(self):
        """
        Publish the ROS message containing the waypoints
        """
        msg = Path()
        msg.header.frame_id = "map"
        msg.header.stamp = icvTime().time_now_o()
        if self.current_route is not None:
            for wp in self.current_route:
                pose = PoseStamped()
                pose.pose.position.x = wp[0].transform.location.x
                pose.pose.position.y = -wp[0].transform.location.y
                pose.pose.position.z = wp[0].transform.location.z

                quaternion = transformations.quaternion_from_euler(
                    0, 0, -math.radians(wp[0].transform.rotation.yaw))
                pose.pose.orientation.x = quaternion[0]
                pose.pose.orientation.y = quaternion[1]
                pose.pose.orientation.z = quaternion[2]
                pose.pose.orientation.w = quaternion[3]
                msg.poses.append(pose)

        self.waypoint_publisher.publish(msg)
        print("Published {} waypoints.".format(len(msg.poses)))