carla-simulator / ros-bridge

ROS bridge for CARLA Simulator
MIT License
523 stars 430 forks source link

CARLA crashes after closing the bridge node. #689

Closed Aleoli2 closed 4 months ago

Aleoli2 commented 1 year ago

When I shutdown the bridge ROS node with Ctrl+C, the CARLA simulation crashes. I am using CARLA version 0.9.14 and CARLA Ros bridge 0.9.12. The same problem happens when I run the manual controller of the PythonAPI of CARLA and I close it with Ctrl+C instead of using the ESC key.

I deduced that it was because some part of the connection was not closing correctly, and I solved it by saving the original settings of the CARLA world and applying them before the node is shutdown.

79        self.carla_settings = carla_world.get_settings()
80        self.original_settings = carla_world.get_settings()
81        if not self.parameters["passive"]:
356            self.synchronous_mode_update_thread.join()
357        self.carla_world.apply_settings(self.original_settings)
358        self.loginfo("Object update finished.")
pruthvik2112 commented 4 months ago

Hi Aleoli2, I am also working with ROS and Carla and facing the same issue, I am a little confused about how you implemented your solution. Could you please share it elaborately. I really appreciate any help you can provide. Thanks in advance.

Aleoli2 commented 4 months ago

After working more with CARLA, I would say that the problem is the following. When the bridge node is executed, Carla synchronous mode is set to True (this can be disabled with ROS parameters, but normally one wants synchronous mode), so when it is closed, the CARLA world waits for synchronous call (the function self.carla_world.tick()), but as it doesn't happen, it crashes. One solution is to apply the original settings when the node ends.
Therefore, I saved the original settings in the function initialize_bridge(self, carla_world, params):

79    self.carla_settings = carla_world.get_settings()
80    self.original_settings = carla_world.get_settings()

I added the last line, the other is already in the program and is used to apply the changes in the settings. Then, the original settings are applied when the node is destroyed, in the function destroy(self):

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

        :return:
        """
        self.loginfo("Shutting down...")
        self.shutdown.set()
        if not self.sync_mode:
            if self.on_tick_id:
                self.carla_world.remove_on_tick(self.on_tick_id)
            self.actor_factory.thread.join()
        else:
            self.synchronous_mode_update_thread.join()
        self.carla_world.apply_settings(self.original_settings) #This line is added
        self.loginfo("Object update finished.")
        self.debug_helper.destroy()
        self.status_publisher.destroy()
        self.destroy_service(self.spawn_object_service)
        self.destroy_service(self.destroy_object_service)
        self.destroy_subscription(self.carla_weather_subscriber)
        self.carla_control_queue.put(CarlaControl.STEP_ONCE)

        for uid in self._registered_actors:
            self.actor_factory.destroy_actor(uid)
        self.actor_factory.update_available_objects()
        self.actor_factory.clear()
        super(CarlaRosBridge, self).destroy()
pruthvik2112 commented 4 months ago

Hi Aleoli2, Thanks a lot for explaining. I understood now and it worked perfectly fine :)