How can I correct my m-file traffic simulation so that each of the eight traffic lights only becomes green or red based on the density count of cars at the two junctions?
3 views (last 30 days)
Show older comments
clc;
clear;
% Parameters
laneWidth = 7;
roadWidth = 2 * laneWidth;
mainLength = 200;
junctionLength = 100;
leftOffset = 50;
rightOffset = -50;
roadColor = [0.2 0.2 0.2];
lineColor = [1 1 1];
carLength = 4;
carWidth = 2;
numCars = 6;
v_max = 0.2; % Max speed
safeDistance = 6; % Minimum distance between cars
acceleration = 0.01; % Speed change per step
spawnInterval = 200;
stopDistance = 10; % Distance at which cars check traffic light
% Lane-specific traffic light colors for each junction
leftTopLaneColor = [1 0 0]; % Red (initial for left junction, top lane)
leftBottomLaneColor = [0 1 0]; % Green (initial for left junction, bottom lane)
rightTopLaneColor = [1 0 0]; % Red (initial for right junction, top lane)
rightBottomLaneColor = [0 1 0];% Green (initial for right junction, bottom lane)
leftTopDiagLaneColor = [1 0 0]; % Red (initial for left junction, top lane)
leftBottomDiagLaneColor = [0 1 0]; % Green (initial for left junction, bottom lane)
rightTopDiagLaneColor = [1 0 0]; % Red (initial for right junction, top lane)
rightBottomDiagLaneColor = [0 1 0];% Green (initial for right junction, bottom lane)
% Frame counter for light updates
frameCount = 0;
updateInterval = 500; % Update lights every 500 frames (~5 seconds)
yellowDuration = 100; % frames for yellow light (~1 second)
lightPhase = 'normal'; % states: 'normal', 'yellowToRed', 'yellowToGreen'
yellowCounter = 0; % counter for yellow phase
% Create figure
figure;
set(gcf, 'Color', [1 1 1]);
hold on;
axis equal;
axis off;
xlim([-mainLength/2-50 mainLength/2+50]);
ylim([-mainLength/2-50 mainLength/2+50]);
%% Plot static roads
x_main = [-mainLength/2, mainLength/2, mainLength/2, -mainLength/2];
y_main = [-roadWidth/2 -roadWidth/2 roadWidth/2 roadWidth/2];
fill(x_main, y_main, roadColor, 'EdgeColor', 'none');
x_leftVert = [-roadWidth/2 + leftOffset, roadWidth/2 + leftOffset, ...
roadWidth/2 + leftOffset, -roadWidth/2 + leftOffset];
y_leftVert = [-junctionLength/2, -junctionLength/2, junctionLength/2, junctionLength/2];
fill(x_leftVert, y_leftVert, roadColor, 'EdgeColor', 'none');
x_rightVert = [-roadWidth/2 + rightOffset, roadWidth/2 + rightOffset, ...
roadWidth/2 + rightOffset, -roadWidth/2 + rightOffset];
y_rightVert = [-junctionLength/2, -junctionLength/2, junctionLength/2, junctionLength/2];
fill(x_rightVert, y_rightVert, roadColor, 'EdgeColor', 'none');
x_dashes = linspace(-mainLength/2, mainLength/2, 50);
for i = 1:2:length(x_dashes)-1
plot(x_dashes(i:i+1), [0 0], '--', 'Color', lineColor, 'LineWidth', 1.5);
end
y_dashes = linspace(-junctionLength/2, junctionLength/2, 10);
for i = 1:2:length(y_dashes)-1
plot([leftOffset leftOffset], y_dashes(i:i+1), '--', 'Color', lineColor, 'LineWidth', 1.5);
plot([rightOffset rightOffset], y_dashes(i:i+1), '--', 'Color', lineColor, 'LineWidth', 1.5);
end
%% Plot circles at junctions
circleRadius = 2;
junctionCircleLeft1 = rectangle('Position', [leftOffset-12 - circleRadius, -circleRadius-12, 2*circleRadius, 2*circleRadius], ...
'Curvature', [1 1], 'FaceColor', leftBottomLaneColor, 'EdgeColor', 'none'); % Bottom lane
junctionCircleLeft2 = rectangle('Position', [leftOffset+12 - circleRadius, -circleRadius+12, 2*circleRadius, 2*circleRadius], ...
'Curvature', [1 1], 'FaceColor', leftTopLaneColor, 'EdgeColor', 'none'); % Top lane
junctionCircleRight1 = rectangle('Position', [rightOffset-12 - circleRadius, -circleRadius-12, 2*circleRadius, 2*circleRadius], ...
'Curvature', [1 1], 'FaceColor', rightBottomLaneColor, 'EdgeColor', 'none'); % Bottom lane
junctionCircleRight2 = rectangle('Position', [rightOffset+12 - circleRadius, -circleRadius+12, 2*circleRadius, 2*circleRadius], ...
'Curvature', [1 1], 'FaceColor', rightTopLaneColor, 'EdgeColor', 'none'); % Top lane
%% Additional Traffic Lights (Diagonally Opposite, 0.5 unit outward)
offset = 0.5; % Distance away from the road
% Left Junction Additional Lights
junctionCircleLeft3 = rectangle('Position', [leftOffset+12 - circleRadius, -circleRadius-12-offset, 2*circleRadius, 2*circleRadius], ...
'Curvature', [1 1], 'FaceColor', leftBottomLaneColor, 'EdgeColor', 'none'); % Diagonal bottom opposite
junctionCircleLeft4 = rectangle('Position', [leftOffset-12 - circleRadius, -circleRadius+12+offset, 2*circleRadius, 2*circleRadius], ...
'Curvature', [1 1], 'FaceColor', leftTopLaneColor, 'EdgeColor', 'none'); % Diagonal top opposite
% Right Junction Additional Lights
junctionCircleRight3 = rectangle('Position', [rightOffset+12 - circleRadius, -circleRadius-12-offset, 2*circleRadius, 2*circleRadius], ...
'Curvature', [1 1], 'FaceColor', rightBottomLaneColor, 'EdgeColor', 'none'); % Diagonal bottom opposite
junctionCircleRight4 = rectangle('Position', [rightOffset-12 - circleRadius, -circleRadius+12+offset, 2*circleRadius, 2*circleRadius], ...
'Curvature', [1 1], 'FaceColor', rightTopLaneColor, 'EdgeColor', 'none'); % Diagonal top opposite
%% Vehicle Count Texts
textLeftTop = text(leftOffset+22, 14, 'Vs: 0', 'FontSize', 6, 'Color', 'black', 'FontWeight', 'bold');
textLeftBottom = text(leftOffset-36, -14, 'Vs: 0', 'FontSize', 6, 'Color', 'black', 'FontWeight', 'bold');
textRightTop = text(rightOffset+22, 14, 'Vs: 0', 'FontSize', 6, 'Color', 'black', 'FontWeight', 'bold');
textRightBottom = text(rightOffset-36, -14, 'Vs: 0', 'FontSize', 6, 'Color', 'black', 'FontWeight', 'bold');
% Additional Vehicle Count Texts for Diagonal Lights
textLeftTopDiag = text(leftOffset-36, 14, 'Vs: 0', 'FontSize', 6, 'Color', 'black', 'FontWeight', 'bold');
textLeftBottomDiag = text(leftOffset+22, -14, 'Vs: 0', 'FontSize', 6, 'Color', 'black', 'FontWeight', 'bold');
textRightTopDiag = text(rightOffset-36, 14, 'Vs: 0', 'FontSize', 6, 'Color', 'black', 'FontWeight', 'bold');
textRightBottomDiag = text(rightOffset+22, -14, 'Vs: 0', 'FontSize', 6, 'Color', 'black', 'FontWeight', 'bold');
%% Initialize cars
carColors = lines(6);
cars = struct([]);
carRects = gobjects(0);
% Initial car spawning in all directions
dirs = {'right', 'left', 'up', 'down'};
for d = 1:length(dirs)
for i = 1:numCars
switch dirs{d}
case 'right'
x = -mainLength/2 - (i-1)*spawnInterval;
y = -laneWidth/2;
case 'left'
x = mainLength/2 + (i-1)*spawnInterval;
y = laneWidth/2;
case 'up'
x = rightOffset + laneWidth/2; % Move to right lane
y = mainLength/2 - (i-1)*spawnInterval;
case 'down'
x = leftOffset - laneWidth/2; % Move to left lane
y = mainLength/2 + (i-1)*spawnInterval;
end
cars(end+1).x = x;
cars(end).y = y;
cars(end).dir = dirs{d};
cars(end).v_current = v_max;
cars(end).turn = randi([0 2]);
cars(end).turned = false;
cars(end).color = carColors(mod(i+10*d, size(carColors,1))+1,:);
if strcmp(dirs{d}, 'up') || strcmp(dirs{d}, 'down')
carRects(end+1,1) = rectangle('Position', [x - carWidth/2 y carWidth carLength], ...
'FaceColor', cars(end).color, 'EdgeColor', 'none');
else
carRects(end+1,1) = rectangle('Position', [x y-carWidth/2 carLength carWidth], ...
'FaceColor', cars(end).color, 'EdgeColor', 'none');
end
end
end
%% Animation loop
% Initialize (before the animation loop if not already declared)
leftJunctionLocked = false;
rightJunctionLocked = false;
while true
% Update frame counter
frameCount = frameCount + 1;
% Count cars near each junction for top and bottom lanes
leftTopCarCount = 0;
leftBottomCarCount = 0;
rightTopCarCount = 0;
rightBottomCarCount = 0;
leftTopDiagCarCount = 0;
leftBottomDiagCarCount = 0;
rightTopDiagCarCount = 0;
rightBottomDiagCarCount = 0;
densityRange = 30; % Increased from 20 to 30 to capture more cars
for i = 1:length(cars)
if ~cars(i).turned && cars(i).v_current < 0.01 % Count stopped cars only
% Left junction (x=35)
% Right-moving (bottom lane, y=-1.75): count cars in x=5 to 35
% Left-moving (top lane, y=1.75): count cars in x=35 to 65
if strcmp(cars(i).dir, 'right') && cars(i).x >= leftOffset-30 && cars(i).x <= leftOffset
if cars(i).y == -laneWidth/2 % Bottom lane (y=-1.75)
leftBottomCarCount = leftBottomCarCount + 1;
end
elseif strcmp(cars(i).dir, 'left') && cars(i).x >= leftOffset && cars(i).x <= leftOffset+30
if cars(i).y == laneWidth/2 % Top lane (y=1.75)
leftTopCarCount = leftTopCarCount + 1;
end
end
% Right junction (x=-35)
% Right-moving (bottom lane, y=-1.75): count cars in x=-65 to -35
% Left-moving (top lane, y=1.75): count cars in x=-35 to -5
if strcmp(cars(i).dir, 'right') && cars(i).x >= rightOffset-30 && cars(i).x <= rightOffset
if cars(i).y == -laneWidth/2 % Bottom lane (y=-1.75)
rightBottomCarCount = rightBottomCarCount + 1;
end
elseif strcmp(cars(i).dir, 'left') && cars(i).x >= rightOffset && cars(i).x <= rightOffset+30
if cars(i).y == laneWidth/2 % Top lane (y=1.75)
rightTopCarCount = rightTopCarCount + 1;
end
end
end
end
% Update traffic lights based on density every updateInterval frames
if strcmp(lightPhase, 'normal') && mod(frameCount, updateInterval) == 0
% Switch to yellow phase before changing lights
lightPhase = 'yellowToRed';
yellowCounter = 0;
% Save current states to know what’s transitioning
prevLeftTop = leftTopLaneColor;
prevLeftBottom = leftBottomLaneColor;
prevRightTop = rightTopLaneColor;
prevRightBottom = rightBottomLaneColor;
prevLeftTopDiag = leftTopDiagLaneColor;
prevLeftBottomDiag = leftBottomDiagLaneColor;
prevRightTopDiag = rightTopDiagLaneColor;
prevRightBottomDiag = rightBottomDiagLaneColor;
% Set yellow wherever green exists
if all(prevLeftTop == [0 1 0]), leftTopLaneColor = [1 1 0]; end
if all(prevLeftBottom == [0 1 0]), leftBottomLaneColor = [1 1 0]; end
if all(prevRightTop == [0 1 0]), rightTopLaneColor = [1 1 0]; end
if all(prevRightBottom == [0 1 0]), rightBottomLaneColor = [1 1 0]; end
if all(prevLeftTopDiag == [0 1 0]), leftTopDiagLaneColor = [1 1 0]; end
if all(prevLeftBottomDiag == [0 1 0]), leftBottomDiagLaneColor = [1 1 0]; end
if all(prevRightTopDiag == [0 1 0]), rightTopDiagLaneColor = [1 1 0]; end
if all(prevRightBottomDiag == [0 1 0]), rightBottomDiagLaneColor = [1 1 0]; end
% Update visuals
junctionCircleLeft1.FaceColor = leftBottomLaneColor;
junctionCircleLeft2.FaceColor = leftTopLaneColor;
junctionCircleLeft3.FaceColor = leftBottomLaneColor;
junctionCircleLeft4.FaceColor = leftTopLaneColor;
junctionCircleRight1.FaceColor = rightBottomLaneColor;
junctionCircleRight2.FaceColor = rightTopLaneColor;
junctionCircleRight3.FaceColor = rightBottomLaneColor;
junctionCircleRight4.FaceColor = rightTopLaneColor;
elseif strcmp(lightPhase, 'yellowToRed')
yellowCounter = yellowCounter + 1;
if yellowCounter >= yellowDuration
% After yellow, determine which lane gets green based on car count
lightPhase = 'normal';
% Example logic: Give green to the most congested lane at each junction
% LEFT junction
if leftTopCarCount > leftBottomCarCount
leftTopLaneColor = [0 1 0]; % Green
leftBottomLaneColor = [1 0 0]; % Red
else
leftTopLaneColor = [1 0 0];
leftBottomLaneColor = [0 1 0];
end
% RIGHT junction
if rightTopCarCount > rightBottomCarCount
rightTopLaneColor = [0 1 0]; % Green
rightBottomLaneColor = [1 0 0]; % Red
else
rightTopLaneColor = [1 0 0];
rightBottomLaneColor = [0 1 0];
end
% Update visuals
junctionCircleLeft1.FaceColor = leftBottomLaneColor;
junctionCircleLeft2.FaceColor = leftTopLaneColor;
junctionCircleLeft3.FaceColor = leftBottomLaneColor;
junctionCircleLeft4.FaceColor = leftTopLaneColor;
junctionCircleRight1.FaceColor = rightBottomLaneColor;
junctionCircleRight2.FaceColor = rightTopLaneColor;
junctionCircleRight3.FaceColor = rightBottomLaneColor;
junctionCircleRight4.FaceColor = rightTopLaneColor;
end
end
% Update vehicle count text
set(textLeftTop, 'String', ['Vs: ' num2str(leftTopCarCount)]);
set(textLeftBottom, 'String', ['Vs: ' num2str(leftBottomCarCount)]);
set(textRightTop, 'String', ['Vs: ' num2str(rightTopCarCount)]);
set(textRightBottom, 'String', ['Vs: ' num2str(rightBottomCarCount)]);
% Update additional vehicle count text (same values, opposite side)
set(textLeftTopDiag, 'String', ['Vs: ' num2str(leftTopCarCount)]);
set(textLeftBottomDiag, 'String', ['Vs: ' num2str(leftBottomCarCount)]);
set(textRightTopDiag, 'String', ['Vs: ' num2str(rightTopCarCount)]);
set(textRightBottomDiag, 'String', ['Vs: ' num2str(rightBottomCarCount)]);
for i = 1:length(cars)
% Check for car ahead
minDist = inf;
for j = 1:length(cars)
if i == j
continue;
end
if strcmp(cars(i).dir, cars(j).dir)
if strcmp(cars(i).dir, 'right')
if cars(j).x > cars(i).x
dist = cars(j).x - cars(i).x;
if dist < minDist
minDist = dist;
end
end
elseif strcmp(cars(i).dir, 'left')
if cars(j).x < cars(i).x
dist = cars(i).x - cars(j).x;
if dist < minDist
minDist = dist;
end
end
end
end
end
% Check traffic light for cars approaching junctions
stopAtJunction = false;
if ~cars(i).turned
if cars(i).turn == 1 && strcmp(cars(i).dir, 'right') && abs(cars(i).x - leftOffset) <= stopDistance
if all(leftBottomLaneColor == [1 0 0]) % Red light for bottom lane at left junction
stopAtJunction = true;
end
elseif cars(i).turn == 1 && strcmp(cars(i).dir, 'left') && abs(cars(i).x - leftOffset) <= stopDistance
if all(leftTopLaneColor == [1 0 0]) % Red light for top lane at left junction
stopAtJunction = true;
end
elseif cars(i).turn == 2 && strcmp(cars(i).dir, 'right') && abs(cars(i).x - rightOffset) <= stopDistance
if all(rightBottomLaneColor == [1 0 0]) % Red light for bottom lane at right junction
stopAtJunction = true;
end
elseif cars(i).turn == 2 && strcmp(cars(i).dir, 'left') && abs(cars(i).x - rightOffset) <= stopDistance
if all(rightTopLaneColor == [1 0 0]) % Red light for top lane at right junction
stopAtJunction = true;
end
end
end
% Gradual braking or acceleration
if stopAtJunction
cars(i).v_current = 0; % Stop at red light
elseif minDist < safeDistance
cars(i).v_current = max(0, cars(i).v_current - acceleration);
elseif cars(i).v_current < v_max
cars(i).v_current = min(v_max, cars(i).v_current + acceleration);
end
% Move car
if strcmp(cars(i).dir, 'right')
cars(i).x = cars(i).x + cars(i).v_current;
elseif strcmp(cars(i).dir, 'left')
cars(i).x = cars(i).x - cars(i).v_current;
elseif strcmp(cars(i).dir, 'up')
cars(i).y = cars(i).y + cars(i).v_current;
elseif strcmp(cars(i).dir, 'down')
cars(i).y = cars(i).y - cars(i).v_current;
end
% Release junction lock when car exits intersection area
if leftJunctionLocked
anyInLeft = false;
for j = 1:length(cars)
if abs(cars(j).x - leftOffset) < 2 && abs(cars(j).y) < 2
anyInLeft = true;
break;
end
end
if ~anyInLeft
leftJunctionLocked = false;
end
end
if rightJunctionLocked
anyInRight = false;
for j = 1:length(cars)
if abs(cars(j).x - rightOffset) < 2 && abs(cars(j).y) < 2
anyInRight = true;
break;
end
end
if ~anyInRight
rightJunctionLocked = false;
end
end
% Turn if needed and adjust lane
if ~cars(i).turned
switch cars(i).dir
case 'right'
% Turn left at LEFT junction
if cars(i).turn == 1 && abs(cars(i).x - leftOffset) < 1 && ~leftJunctionLocked
cars(i).dir = 'up';
cars(i).x = leftOffset + laneWidth/2; % Stay aligned in upward right lane
cars(i).y = -laneWidth/2; % Bottom lane y-position
cars(i).turned = true;
leftJunctionLocked = true; % Lock junction
% Turn right at RIGHT junction
elseif cars(i).turn == 2 && abs(cars(i).x - rightOffset) < 1 && ~rightJunctionLocked
cars(i).dir = 'down';
cars(i).x = rightOffset - laneWidth/2;
cars(i).y = -laneWidth/2;
cars(i).turned = true;
rightJunctionLocked = true;
end
case 'left'
% Turn left at RIGHT junction
if cars(i).turn == 1 && abs(cars(i).x - rightOffset) < 1 && ~rightJunctionLocked
cars(i).dir = 'up';
cars(i).x = rightOffset + laneWidth/2;
cars(i).y = laneWidth/2;
cars(i).turned = true;
rightJunctionLocked = true;
% Turn right at LEFT junction
elseif cars(i).turn == 2 && abs(cars(i).x - leftOffset) < 1 && ~leftJunctionLocked
cars(i).dir = 'down';
cars(i).x = leftOffset - laneWidth/2;
cars(i).y = laneWidth/2;
cars(i).turned = true;
leftJunctionLocked = true;
end
end
end
% Update rectangle
if strcmp(cars(i).dir, 'up') || strcmp(cars(i).dir, 'down')
set(carRects(i), 'Position', [cars(i).x - carWidth/2 cars(i).y carWidth carLength]);
else
set(carRects(i), 'Position', [cars(i).x cars(i).y-carWidth/2 carLength carWidth]);
end
end
% Remove cars that go offscreen
toRemove = [];
for i = 1:length(cars)
if abs(cars(i).x) > mainLength/2 + 50 || abs(cars(i).y) > mainLength/2 + 50
delete(carRects(i));
toRemove(end+1) = i;
end
end
cars(toRemove) = [];
carRects(toRemove) = [];
% Random spawning in all directions
if rand < 0.02
% Right
cars(end+1).x = -mainLength/2 - 10;
cars(end).y = -laneWidth/2;
cars(end).dir = 'right';
elseif rand < 0.02
% Left
cars(end+1).x = mainLength/2 + 10;
cars(end).y = laneWidth/2;
cars(end).dir = 'left';
elseif rand < 0.02
elseif rand < 0.02
% Up
cars(end+1).x = rightOffset + laneWidth/2; % Right lane
cars(end).y = -mainLength/2 - 10;
cars(end).dir = 'up';
elseif rand < 0.02
% Down
cars(end+1).x = leftOffset - laneWidth/2; % Left lane
cars(end).y = mainLength/2 + 10;
cars(end).dir = 'down';
end
if length(cars) > length(carRects)
idx = length(cars);
cars(idx).v_current = v_max;
cars(idx).turn = randi([0 2]);
cars(idx).turned = false;
cars(idx).color = carColors(mod(randi(20), size(carColors,1))+1,:);
if strcmp(cars(idx).dir, 'up') || strcmp(cars(idx).dir, 'down')
carRects(idx,1) = rectangle('Position', [cars(idx).x - carWidth/2 cars(idx).y carWidth carLength], ...
'FaceColor', cars(idx).color, 'EdgeColor', 'none');
else
carRects(idx,1) = rectangle('Position', [cars(idx).x cars(idx).y - carWidth/2 carLength carWidth], ...
'FaceColor', cars(idx).color, 'EdgeColor', 'none');
end
end
pause(0.01);
end
2 Comments
Torsten
on 14 May 2025
What a strange if-elseif construct ...
% Random spawning in all directions
if rand < 0.02
% Right
cars(end+1).x = -mainLength/2 - 10;
cars(end).y = -laneWidth/2;
cars(end).dir = 'right';
elseif rand < 0.02
% Left
cars(end+1).x = mainLength/2 + 10;
cars(end).y = laneWidth/2;
cars(end).dir = 'left';
elseif rand < 0.02
elseif rand < 0.02
% Up
cars(end+1).x = rightOffset + laneWidth/2; % Right lane
cars(end).y = -mainLength/2 - 10;
cars(end).dir = 'up';
elseif rand < 0.02
% Down
cars(end+1).x = leftOffset - laneWidth/2; % Left lane
cars(end).y = mainLength/2 + 10;
cars(end).dir = 'down';
end
Answers (1)
Harsh
on 5 Jun 2025
This looks like an interesting project, using MATLAB Copilot in MATLAB R2025a I have made the following changes to the script:
- Each junction (leftJunction, rightJunction) now has its own state machine (EW_GREEN, EW_YELLOW, NS_GREEN, NS_YELLOW) and timers.
- Variables like countLW (Left West), countLS (Left South), etc., track car densities for all 8 approaches.
- Lights switch based on comparing car counts on green vs. red approaches, after a minimum green time.
- Lights are now hLightLW, hLightLS, etc., for easier identification.
- Cars now check the specific light for their direct path of approach.
- The traffic light visuals are positioned more appropriately for each approach.
- Initial and random car spawning is more structured, though you might want to expand it to ensure all 8 approaches are consistently fed with traffic for more dynamic testing.
- A simple leftJunctionLocked and rightJunctionLocked mechanism is kept to prevent multiple cars from being in the absolute center of the junction simultaneously.
- Cars and their graphical rectangles are now linked by a UserData ID for more robust removal and updating.
I believe these changes have been successful in increasing the efficiency of the traffic signal network. As you can see in the following image the traffic signals are working as expected.

PFA the modified ".m" script.
I hope this helps, thanks!
0 Comments
See Also
Categories
Find more on Computational Geometry in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!