diff --git a/.gitignore b/.gitignore index 2438a38..48bfa15 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,7 @@ srunner/osc2 srunner/osc2_dm srunner/osc2_stdlib metrics_manager.py - +docker-compose.yml jats paper logs diff --git a/README.md b/README.md index b0c94f8..f1a520c 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,11 @@ docker pull ghcr.io/intelligent-testing-lab/autoware-scenario-runner:latest docker pull ghcr.io/intelligent-testing-lab/autoware:latest ``` -Autoware and ROS use a custom messaging interface for communcation, known as DDS. They support various implementations, but they all rely on specific network settings to enable maximum data transfer. Save the following command in `setup.sh`, allow it to be executable `chmod +x setup.sh` and run. +Autoware and ROS use a custom messaging interface for communication, known as DDS. They support various implementations, but they all rely on specific network settings to enable maximum data transfer. Save the following command in `setup.sh`, allow it to be executable `chmod +x setup.sh` and run. ```bash -# Increase the maximum receive buffer size for network packets +# Increase the maximum receive and send buffer size for network packets, allowing our containers to communicate sudo sysctl -w net.core.rmem_max=2147483647 # 2 GiB, default is 208 KiB +sudo sysctl -w net.core.wmem_max=2147483647 # IP fragmentation settings sudo sysctl -w net.ipv4.ipfrag_time=3 # in seconds, default is 30 s @@ -42,7 +43,7 @@ xhost +local:docker Using CAWSR ------------------------ -After completiting the prerequisite steps, clone the CAWSR workspace repository. To launch CAWSR, navigate to the CAWSR workspace and run `docker compose up`. +After completiting the prerequisite steps, clone the [CAWSR workspace](https://github.com/Intelligent-Testing-Lab/cawsr_workspace) repository. To launch CAWSR, navigate to the CAWSR workspace and run `docker compose up`. The structure of the workspace is as follows. ``` @@ -78,14 +79,17 @@ is called. To implement a custom algorithm, create a class than inherits from `B The algorithm will execute **runs** times. - Scenario Definition ------------------- We use a custom implementation of a scenario definition in JSON. We have included a scenario domain model, as well as plenty of examples in the CAWSR Workspace repository `scenarios/examples/`. Domain Model: -![Domain Model](./docs/resources/scenario_domain.png) +![Domain Model](./docs/resources/scenario_domain.pdf) + +Notes +------------ +Currently, traffic light recognition is disabled due to an issue with the [CARLA map format](https://github.com/autowarefoundation/autoware_universe/tree/main/simulator/autoware_carla_interface#traffic-light-recognition). This is a time consuming process, as each new traffic light requires the creation of a new objects within the CARLA Lanelet2 file that match the position of the PCD exactly. Once finished, we'll publish an updated Autoware image accordingly. Contributing ------------ @@ -102,3 +106,4 @@ License ------- ScenarioRunner specific code is distributed under MIT License. +CAWSR specific code is distributed under MIT License. diff --git a/docker/cyclonedds.xml b/docker/cyclonedds.xml index bb87149..7584c0f 100644 --- a/docker/cyclonedds.xml +++ b/docker/cyclonedds.xml @@ -9,10 +9,14 @@ 65500B - + + - 500kB + 1MB + + warning + diff --git a/srunner/autoagents/autoware_agent.py b/srunner/autoagents/autoware_agent.py index c6979ee..5178c1e 100644 --- a/srunner/autoagents/autoware_agent.py +++ b/srunner/autoagents/autoware_agent.py @@ -44,10 +44,10 @@ def setup(self, config: EnvironmentConfig) -> None: """ rclpy.init(args=None) - + self.config = config - self._node = rclpy.create_node('cawsr_bridge') + self._node = rclpy.create_node("cawsr_bridge") self.autoware_state = autoware_state.AutowareState("ego_vehicle", None) @@ -171,7 +171,7 @@ def run_step(self) -> None: if self.initialised: logger.info("Set agent route!") - # check if the current route is set + # check if the current route is set and we can publish engage if self.autoware_state.route_set() and not self.autoware_state.sent_engage: self.autoware_node.publish_engage(True) diff --git a/srunner/autoagents/autoware_carla_interface/carla_ros.py b/srunner/autoagents/autoware_carla_interface/carla_ros.py index 85f6470..62d325f 100644 --- a/srunner/autoagents/autoware_carla_interface/carla_ros.py +++ b/srunner/autoagents/autoware_carla_interface/carla_ros.py @@ -27,7 +27,6 @@ from geometry_msgs.msg import Pose from geometry_msgs.msg import PoseWithCovarianceStamped import numpy -import rclpy import datetime import pathlib from rosgraph_msgs.msg import Clock @@ -56,7 +55,6 @@ SensorInterface, ) -from srunner.tools.CARLA_manager import CARLAManager class carla_ros2_interface(object): def __init__(self, node): @@ -86,27 +84,19 @@ def __init__(self, node): sensor: datetime.datetime.now() for sensor in self.sensor_frequencies } - self.game_time_offset = CARLAManager.FIXED_DELTA_SECONDS * 3 # offset to account for initilisation ticks - frac, whole = math.modf(self.game_time_offset) - self.ros2_node = node - # Publish clock self.clock_publisher = self.ros2_node.create_publisher(Clock, "/clock", 10) obj_clock = Clock() - obj_clock.clock = Time( - sec=int(whole), - nanosec=int(frac * 1e9) - ) + obj_clock.clock = Time(sec=int(0)) self.clock_publisher.publish(obj_clock) - # Sensor Config (Edit your sensor here) + # load sensor config and create publishers sensors_config = pathlib.Path( "srunner/autoagents/autoware_carla_interface/objects/sensors.json" ) self.sensors = json.load(open(sensors_config.absolute())) - # Subscribing Autoware Control messages and converting to CARLA control self.sub_control = self.ros2_node.create_subscription( ActuationCommandStamped, "/control/command/actuation_cmd", @@ -120,7 +110,6 @@ def __init__(self, node): self.current_control = carla.VehicleControl() - # Direct data publishing from CARLA for Autoware self.pub_pose_with_cov = self.ros2_node.create_publisher( PoseWithCovarianceStamped, "/sensing/gnss/pose_with_covariance", 1 ) @@ -140,7 +129,6 @@ def __init__(self, node): ActuationStatusStamped, "/vehicle/status/actuation_status", 1 ) - # Create Publisher for each Physical Sensors for sensor in self.sensors["sensors"]: self.id_to_sensor_type_map[sensor["id"]] = sensor["type"] if sensor["type"] == "sensor.camera.rgb": @@ -155,7 +143,7 @@ def __init__(self, node): self.pub_lidar[sensor["id"]] = self.ros2_node.create_publisher( PointCloud2, f"/sensing/lidar/{sensor['id']}/pointcloud_before_sync", - 10, + 5, # lower qos depth as using best_reliability ) else: self.ros2_node.get_logger().info( @@ -171,9 +159,6 @@ def __init__(self, node): ) pass - # add to multi threaded executor instead - # self.spin_thread = threading.Thread(target=rclpy.spin, args=(self.ros2_node,)) - def __call__(self): input_data = self.sensor_interface.get_data() timestamp = GameTime.get_time() @@ -504,18 +489,16 @@ def run_step(self, input_data, timestamp): else: self.ros2_node.get_logger().info("No Publisher for [{key}] Sensor") - # Publish ego vehicle status - self.ego_status() + time.sleep(0.05) # 50ms delay to ensure published messages are received - time.sleep(0.001) # small delay to ensure all data can be sent in time - - # publish clock last to ensure all sensor data is waiting for autoware seconds = int(self.timestamp) nanoseconds = int((self.timestamp - int(self.timestamp)) * 1000000000.0) obj_clock = Clock() obj_clock.clock = Time(sec=seconds, nanosec=nanoseconds) self.clock_publisher.publish(obj_clock) - + + self.ego_status() + return self.current_control def shutdown(self):