Skip to content

ROS 2#

Connect the game or ACRES Core to ROS 2 Humble. The bridge publishes the topics, the services and the action of the simulated Polaris.

Warning

Start each ROS 2 node of this workspace in a shell with the DDS loopback fence (source ROS/Env/setup_env.sh). The command topics have the names of the real Polaris. Outside the fence, a command can go to a real vehicle on the same network.

The ROS 2 graph of one Polaris session: the three local sockets of the simulator, the node sim_bridge, the topic groups with their rates, the command topics, the services and the action, and the ROS 2 nodes that use them. LOCAL SOCKETS, 127.0.0.1 ROS 2 BRIDGE TOPICS, SERVICES, ACTION ROS 2 NODES Game or ACRES Core Sensor stream -SensorStream=5601 binary frames, TCP clock, INS, LiDAR, camera, barriers Vehicle bridge -RlPort=5556 JSON lines, TCP Simulator control channel -SimControl=5600 JSON lines, TCP Node sim_bridge Sensor reader The reader thread publishes the clock and the INS data. A second thread publishes the clouds and the images. Vehicle client publishes the reports sends each command immediately Control client A step reply waits for the barriers of all channels. frames reports commands requests Clock, 120 Hz /clock rosgraph_msgs/Clock Pose and INS, 100 Hz /vehicle/odom /tf /oxts/fix /oxts/imu /oxts/velocity /sim/ground_truth/odom Odometry, Imu, NavSatFix, TwistStamped LiDAR and camera /lidar/points PointCloud2, 10 Hz /camera/image_raw Image, 10 Hz /camera/camera_info CameraInfo Drive-by-wire reports, 50 Hz /vehicle/*/report ds_dbw_msgs /vehicle/vehicle_velocity /vehicle/dbw_enabled std_msgs/Bool Commands /vehicle/*/cmd ds_dbw_msgs /vehicle/enable /vehicle/disable /sim/reset PoseStamped Simulator control /sim/episode Episode, latched /step_simulation /simulate_steps /get_simulation_state /get_... /acres/record /acres/farm_state simulation_interfaces, acres_interfaces Subscribers RViz 2 ros2 bag record perception nodes Controller dbw_demo_driver or your node Client lockstep loop, task scoring
The bridge connects the three sockets of the simulator to the topics, the services and the action. Open the diagram

The DDS Loopback Fence#

ROS 2 nodes find each other on the network automatically. The DDS loopback fence is a set of environment settings that keeps all ROS 2 traffic on the address 127.0.0.1.

The DDS loopback fence: the simulator, the ROS 2 bridge and the ROS 2 nodes of the workstation exchange data on 127.0.0.1 only. The settings of the fence stop all DDS traffic to the LAN and to the Tailscale network, where the real Polaris is. Workstation DDS loopback fence interface lo, address 127.0.0.1, ROS domain 77 Game or ACRES Core local TCP sockets ROS 2 bridge sim_bridge TCP ROS 2 nodes controller, RViz 2, CLI ROS 2 bag record and play DDS between the nodes: UDP unicast Ethernet, Wi-Fi LAN tailscale0 Tailscale network 1, 2 1, 2 Real Polaris vehicle computer ROS 2 Humble Cyclone DDS ROS domain 0 drive-by-wire commands move the vehicle network network 3: other ports Settings of the Fence ROS/Env/dds_safety.sh sets them in each shell of the conda environment ros2 1 ROS_LOCALHOST_ONLY=1 The middleware selects only the interface lo. 2 CYCLONEDDS_URI=cyclonedds_localhost.xml No multicast. The only discovery peer is 127.0.0.1. 3 ROS_DOMAIN_ID=77 UDP ports 26660 to 26789. Domain 0 starts at 7400. RMW_IMPLEMENTATION=rmw_cyclonedds_cpp The middleware that reads the configuration file. ROS_AUTOMATIC_DISCOVERY_RANGE=LOCALHOST The same limit for ROS 2 Iron and later versions. unset ROS_STATIC_PEERS ROS_DISCOVERY_SERVER No peer or discovery server from the parent shell.
The settings of the fence keep the ROS 2 traffic inside the computer. Open the diagram

The file ROS/Env/dds_safety.sh has the settings. Two paths apply it:

  • The script ROS/Env/setup_env.sh applies it when you source the script.
  • The conda hook applies it each time you activate the environment ros2.

Build the Workspace#

Before you start

  • Linux with bash, and Miniconda in ~/miniconda3. For a different folder, set CONDA_ROOT.
  • Access to the conda channels robostack-humble and conda-forge.

The build does not use the game. The package acres_core_sim compiles the sources of ACRES Core.

  1. Make the conda environment ros2 with ROS 2 Humble from RoboStack.

    conda env create -f ROS/Env/environment.yml --override-channels -c robostack-humble -c conda-forge
    
  2. Install the conda hooks of the fence. Run the script again after you change a file in ROS/Env.

    ROS/Env/install_conda_hooks.sh
    
  3. Open a shell with the environment and the fence.

    source ROS/Env/setup_env.sh
    

    Expected result

    acres_ros: workspace not built yet (see ROS/README.md)
    acres_ros: ROS 2 humble | rmw_cyclonedds_cpp | ROS_DOMAIN_ID=77 | ROS_LOCALHOST_ONLY=1
    
  4. Make sure that the fence operates. The check starts a talker and a listener and records each UDP packet.

    ROS/Env/check_dds_isolation.sh
    

    Expected result

    The last line is PASS: DDS traffic stays on loopback.

    Warning

    Do not start a node if the last line is FAIL. Install the conda hooks again, open a new shell and do the check again.

  5. Build all packages.

    cd ROS && colcon build && cd ..
    

    Expected result

    Summary: 6 packages finished [1min 20s]
    

    Two packages write one CMake warning about Python_FIND_VIRTUALENV on stderr. The warning has no effect.

  6. Source the script again to load the workspace.

    source ROS/Env/setup_env.sh
    
  7. Run the tests. They use a substitute for the game and do not start it.

    cd ROS
    colcon test --packages-select acres_sim acres_description acres_core_sim
    colcon test-result --verbose
    cd ..
    

    Expected result

    Summary: 60 tests, 0 errors, 0 failures, 5 skipped
    

The Polaris Description#

The package purdue_ranger has the URDF file of the real Polaris. It has a proprietary license and is not in the repository. The bridge does not need it. Without it, the static frames of the URDF and the model in RViz are not available.

Launch File Without purdue_ranger
acres_sim sim_bridge.launch.py Use vehicle:=auto or vehicle:=maxxum. The default vehicle:=polaris stops.
acres_core_sim core_sim.launch.py Stops. Start core_sim and sim_bridge with ros2 run and ros2 launch.
acres_description launch files Stop.

Connect the Game#

The procedure uses three shells: shell 1 for the simulator, shell 2 for the bridge and shell 3 for the commands. Source ROS/Env/setup_env.sh in shells 2 and 3.

Socket Option of the Game Port Argument of the Launch File
Sensor stream -SensorStream= 5601 sensor_port
Vehicle bridge -RlPort= 5556 rl_port
Simulator control channel -SimControl= 5600 control_port
  1. In shell 1, start the game with the Polaris and the three sockets.

    Packaged/Linux/Acres.sh -VehicleDemo -Vehicle=polaris -SensorStream=5601 -RlPort=5556 -SimControl=5600
    

    Expected result

    ACRES_SENSOR_STREAM_LISTENING agent=polaris port=5601
    ACRES_RL_LISTENING port=5556
    ACRES_SIM_CONTROL_READY port=5600 lockstep=0 replay=0 log=
    
  2. In shell 2, start the bridge.

    ros2 launch acres_sim sim_bridge.launch.py vehicle:=auto
    

    Expected result

    [sim_bridge]: connected to polaris (polaris): LiDAR 1800 x 32 at 10 Hz, camera 896 x 512 at 10 Hz, INS 100 Hz
    

    Add rviz:=true to see the LiDAR cloud and the camera image in RViz 2.

    RViz 2 with the LiDAR cloud and the camera image of the game

  3. In shell 3, list the topics.

    ros2 topic list -t
    

    Expected result

    The list has the sensor topics, the drive-by-wire topics and the simulator topics:

    /camera/image_raw [sensor_msgs/msg/Image]
    /clock [rosgraph_msgs/msg/Clock]
    /lidar/points [sensor_msgs/msg/PointCloud2]
    /oxts/fix [sensor_msgs/msg/NavSatFix]
    /oxts/imu [sensor_msgs/msg/Imu]
    /sim/episode [acres_interfaces/msg/Episode]
    /sim/ground_truth/odom [nav_msgs/msg/Odometry]
    /vehicle/enable [std_msgs/msg/Empty]
    /vehicle/odom [nav_msgs/msg/Odometry]
    /vehicle/ulc/cmd [ds_dbw_msgs/msg/UlcCmd]
    /vehicle/ulc/report [ds_dbw_msgs/msg/UlcReport]
    ...
    

Topics gives each topic with its type, rate, QoS and frame.

Drive with the Drive-by-Wire#

The Polaris starts in the gear L with the drive-by-wire off. A command has an effect only after you enable the drive-by-wire. The simulator stops a subsystem 0.1 s after its last command, as the real vehicle does. Send the commands continuously.

  1. Enable the drive-by-wire.

    ros2 topic pub --once /vehicle/enable std_msgs/msg/Empty "{}"
    
  2. Send a speed command of 1.5 m/s at 50 Hz for 10 s.

    ros2 topic pub -r 50 -t 500 /vehicle/ulc/cmd ds_dbw_msgs/msg/UlcCmd "{cmd: 1.5, cmd_type: 1, enable: true}"
    

    Expected result

    The Polaris moves to the north at 1.5 m/s. In a different shell, ros2 topic echo --once /vehicle/ulc/report shows the speed:

    cmd_type: 1
    vel_ref: 1.5
    vel_meas: 1.5082000494003296
    enabled: true
    

    After the last command, the vehicle stops and enabled becomes false.

  3. Disable the drive-by-wire.

    ros2 topic pub --once /vehicle/disable std_msgs/msg/Empty "{}"
    

Control the Simulation#

The bridge offers the services of simulation_interfaces.

Command Result
ros2 service call /get_simulation_state simulation_interfaces/srv/GetSimulationState The state: 1 for play, 2 for pause.
ros2 service call /set_simulation_state simulation_interfaces/srv/SetSimulationState "{state: {state: 2}}" Pause the world. The game continues to render.
ros2 service call /step_simulation simulation_interfaces/srv/StepSimulation "{steps: 120}" Advance 120 physics steps, which is 1 s. The response arrives after the bridge published the sensor data of the steps.
ros2 service call /set_simulation_state simulation_interfaces/srv/SetSimulationState "{state: {state: 1}}" Play again.
ros2 service call /acres/farm_state acres_interfaces/srv/FarmState "{edge_band_m: 4.0, fields: [48]}" The ground truth of field F48: crop, crushed area, harvested area, soil water.
ros2 service call /set_simulation_state simulation_interfaces/srv/SetSimulationState "{state: {state: 3}}" Stop the game.

Services and Actions gives each service with its fields and result codes.

Use ACRES Core in Place of the Game#

The executable core_sim runs the Polaris of ACRES Core behind the same three sockets. It needs no game and no GPU. The bridge and all commands are the same.

  1. In shell 1, start ACRES Core.

    ros2 run acres_core_sim core_sim
    

    Expected result

    ACRES_CORE_SIM_READY agents=1 control=5600 lockstep=0 rate=1 ...
    ACRES_CORE_SIM_AGENT name=polaris sensor_stream=5601 rl_port=5556 x=-38.710 y=-140.513 yaw_deg=90.00
    
  2. In shell 2, start the bridge with the same command as for the game.

    Expected result

    ACRES Core has no camera:

    [sim_bridge]: connected to polaris (polaris): LiDAR 1800 x 32 at 10 Hz, camera None x None at 0 Hz, INS 100.0 Hz
    
  3. Run ACRES Core faster than real time with the option --rate.

    ros2 run acres_core_sim core_sim --rate 10
    

    Expected result

    ros2 topic hz /clock shows approximately 1200 Hz, and ros2 topic hz /lidar/points shows approximately 100 Hz.

RViz 2 with the Polaris of ACRES Core and its LiDAR cloud

Next Steps#

  • Topics


    Each topic with its type, rate, QoS and frame.

  • Lockstep Stepping


    A control loop that steps the simulation.

  • Vehicles


    The Polaris, the Maxxum and sessions with several vehicles.