A ROS 1 (Noetic) catkin workspace for simulating Adaptive Cruise Control (ACC) in a Dockerized environment. Developed for Vanderbilt University's CS 3892 Autonomous Vehicles & Traffic course.
Recorded driving data from a real vehicle is replayed as a lead car, and one or more simulated ego vehicles follow it using an ACC controller -- all running as ROS nodes inside a Docker container.
git clone https://github.com/jmscslgroup/rossim rossim
cd rossimThis gives you the workspace skeleton: launch files, setup scripts, and this README. The ROS packages themselves are cloned in Step 4.
- macOS / Windows: Install Docker Desktop
- Linux: Install Docker Engine
docker pull sprinkjm/rosemptyRun the image and confirm you get a shell prompt:
docker run --rm -it sprinkjm/rosempty /bin/bashYou should see a root prompt like root@<container_id>:/#. Inside it, verify ROS is available:
roscore &
sleep 2 && rostopic listYou should see /rosout and /rosout_agg listed. If so, ROS is working. Type exit to leave the container.
This step confirms that your host files are visible inside the container.
From the rossim/ directory on your host:
docker run --rm --mount type=bind,source=$(pwd),target=/ros/catkin_ws -it sprinkjm/rosempty:latest ls /ros/catkin_wsYou should see README.md, scripts/, src/, etc. -- the contents of your rossim/ directory. If you see an empty listing or an error, double-check the path and that Docker has permission to access the directory.
A setup script clones all the packages needed for the profacc ACC simulation:
./scripts/setup_profacc.shThis clones the following into src/:
| Package | Description |
|---|---|
| profacc | Time-headway ACC controller (Simulink-generated) |
| subtractor | Computes difference of two Float64 topics |
| odometer | Integrates velocity to produce position |
| carsimplesimulink | Simple point-mass vehicle model |
| carcomplexsimulink | Higher-fidelity vehicle model |
Download the example bag file from Brightspace (hwilexample.bag) and place it in the rossim/ root directory as mytest.bag:
cp /path/to/hwilexample.bag mytest.bagThis file contains a recorded velocity trace from a real vehicle and is replayed as the lead car in simulation.
Launch the Docker container with the workspace mounted:
docker run --mount type=bind,source=$(pwd),target=/ros/catkin_ws -it sprinkjm/rosempty:latestInside the container, build:
catkin_makeIf the build succeeds you will see a summary like:
[100%] Built target profacc
[100%] Built target carsimplesimulink
...
Then source the workspace:
source devel/setup.bashroslaunch profacc profaccDocker.launchYou will see ROS start up several nodes. The bag file replays the lead car velocity trace, the ACC controller computes acceleration commands, and the ego car model responds. All topics are recorded to a new bag file (profacc_*.bag) in the workspace root.
When the bag file finishes playing (or you want to stop early), press Ctrl+C.
The terminal will show log output from the various nodes. To see the simulation in action, open a second terminal and connect to the running container:
# Find the container name
docker ps
# Connect to it
docker exec -it <container_name> /bin/bash
source /ros/catkin_ws/devel/setup.bashThen try:
# List all active topics
rostopic list
# Watch the ego car velocity in real time
rostopic echo /egocar/car/state/vel_x
# Watch the ACC acceleration commands
rostopic echo /egocar/cmd_accelEach Docker launch file sets up this pipeline:
Recorded bag file Lead car Ego car
(real driving data) (odometer) (ACC + vehicle model)
| | |
/leadcar/car/state/vel_x odom_x profacc <-- subtractor (rel_vel)
\ | \--- subtractor (lead_dist)
\ v
carsimplesimulink --> vel_x, odom_x
rosbag playreplays the recorded velocity trace as the lead carodometerintegrates lead car velocity into positionsubtractornodes compute relative velocity and distance between lead and egoprofacccomputes an acceleration command using the ACC control lawcarsimplesimulinksimulates the ego car's response to that commandrosbag recordcaptures everything to a new bag file
The controller implements a time-headway ACC law:
cmd_accel = alpha * (lead_dist - tau * vel_x) + lambda * rel_vel
| Parameter | Default | Description |
|---|---|---|
alpha |
1.1 | Proportional gain |
tau |
2.0 | Time headway (seconds) |
lambda |
0.1 | Relative velocity gain |
Output is saturated to [-3.0, 1.5] m/s^2.
| Direction | Topic | Type | Description |
|---|---|---|---|
| Subscribes | car/state/vel_x |
std_msgs/Float64 |
Ego car velocity |
| Subscribes | lead_dist |
std_msgs/Float64 |
Distance to lead car |
| Subscribes | rel_vel |
std_msgs/Float64 |
Relative velocity (lead - ego) |
| Publishes | cmd_accel |
std_msgs/Float64 |
Acceleration command |
Parameters can be changed at runtime:
rosparam set /egocar/profacc_node/tau 3.0All Docker launch files are in src/profacc/launch/:
| Launch file | Ego cars | Vehicle model | Description |
|---|---|---|---|
profaccDocker.launch |
1 | simple | Basic scenario. Replays mytest.bag from t=100s. Lead starts at x=20m. |
profaccDocker_test1.launch |
1 | simple | Ego starts closer (x0=15m) and faster (v0=2.5 m/s). |
profaccDocker_test2.launch |
1 | complex | Adds 10m extra buffer to lead_dist. |
profaccDocker_complex.launch |
1 | complex | Same as basic but with the complex vehicle model. |
profaccDocker_homework3.launch |
1 | complex | Uses a different bag file, starts at t=310s. |
profaccDocker_homework3extra.launch |
4 | complex | Multi-car cascade (see below). |
profaccDocker_homework3extra.launch chains 4 ACC-controlled vehicles behind a lead car:
leadcar (x0=120m) --> egocar (x0=100m) --> egocar1 (x0=70m) --> egocar2 (x0=45m) --> egocar3 (x0=20m)
Each ego car runs its own profacc node and follows the car directly ahead. This is useful for studying string stability -- how disturbances propagate (or dampen) through a platoon.
roslaunch profacc profaccDocker_homework3extra.launchAfter a simulation, the recorded .bag file is written to the rossim/ directory. Open MATLAB, run the provided testResult script, and select the bag file when prompted.