% 反射镜系统光路轨迹分析(增强版)
clear; clc; close all;
% ========== 参数设置 ==========
mirror_radius = 20; % 圆形镜子半径
N = 120; % 动画帧数
ray_length = 100; % 出射光线延伸长度 (cm)
plot_trajectory = true; % 是否绘制轨迹
save_animation = false; % 是否保存动画为GIF
% ========== 用户可修改的偏差参数 (单位:度) ==========
deviation_angles = [
0.5, -0.5; % M1 偏差
-0.5, 0.5; % M2 偏差
0.5, 0.5; % M3 偏差
-0.5, -0.5; % M4 偏差
0.0, 0.0 % M5 偏差
];
% ========== 初始光路关键点 ==========
M1 = [0, 0, 0]; % 镜子1中心
M2 = [0, 0, 100]; % 镜子2中心
M3 = [100, 0, 100]; % 镜子3中心
M4 = [100, 0, 200]; % 镜子4中心
M5 = [0, 0, 200]; % 镜子5中心
start_pt = [-100, 0, 0]; % 光线起始点
% ========== 旋转矩阵函数 ==========
Rx = @(theta) [1, 0, 0; 0, cosd(theta), -sind(theta); 0, sind(theta), cosd(theta)];
Ry = @(theta) [cosd(theta), 0, sind(theta); 0, 1, 0; -sind(theta), 0, cosd(theta)];
Rz = @(theta) [cosd(theta), -sind(theta), 0; sind(theta), cosd(theta), 0; 0, 0, 1];
% ========== 应用偏差到法向量 ==========
M1_n0 = [-sqrt(2)/2, 0, sqrt(2)/2]‘;
M2_n0 = [-sqrt(2)/2, 0, sqrt(2)/2]’;
M3_n0 = [-sqrt(2)/2, 0, sqrt(2)/2]‘;
M4_n0 = [sqrt(2)/2, 0, sqrt(2)/2]’;
M5_n0 = [sqrt(2)/2, 0, sqrt(2)/2]';
M1_n = apply_deviation(M1_n0, deviation_angles(1,:));
M2_n = apply_deviation(M2_n0, deviation_angles(2,:));
M3_n = apply_deviation(M3_n0, deviation_angles(3,:));
M4_n = apply_deviation(M4_n0, deviation_angles(4,:));
M5_n = apply_deviation(M5_n0, deviation_angles(5,:));
% ======================================================================
% 图1:镜子5绕x轴旋转(带偏差)
% ======================================================================
fig1 = figure(‘Position’, [50, 100, 1000, 800], ‘Name’, ‘镜子5绕x轴旋转(带偏差)’);
hold on; grid on; axis equal;
view(45, 30);
xlabel(‘X (cm)’); ylabel(‘Y (cm)’); zlabel(‘Z (cm)’);
title(‘镜子5绕x轴旋转 - 带偏差光路轨迹’,‘FontSize’,16,‘FontWeight’,‘bold’);
% 绘制固定元素
draw_mirror_circle(M1, M1_n, mirror_radius, [0.8, 0.8, 0.9], ‘M1’);
draw_mirror_circle(M2, M2_n, mirror_radius, [0.9, 0.8, 0.8], ‘M2’);
draw_mirror_circle(M3, M3_n, mirror_radius, [0.8, 0.9, 0.8], ‘M3’);
draw_mirror_circle(M4, M4_n, mirror_radius, [0.9, 0.8, 0.9], ‘M4’);
% 绘制旋转轴和轨迹平面
plot3([-50, 50], [0, 0], [200, 200], ‘m–’, ‘LineWidth’, 2);
text(50, 0, 200, ‘旋转轴 (x轴)’, ‘FontSize’, 12, ‘Color’, ‘m’);
[Y, Z] = meshgrid(linspace(-100,100,10), linspace(100,300,10));
surf(zeros(size(Y)), Y, Z, ‘FaceAlpha’, 0.1, ‘EdgeColor’, ‘k’, ‘FaceColor’, ‘cyan’);
text(0, 0, 100, ‘轨迹平面 (yz平面)’, ‘FontSize’, 12, ‘Color’, ‘b’);
% 计算初始光路
[path, reflection_pts, final_spot] = calculate_light_path(start_pt, [M1; M2; M3; M4; M5], …
[M1_n, M2_n, M3_n, M4_n, M5_n], ray_length);
plot_light_path(path, reflection_pts, ‘r-b-g-m-c’, 2);
% 初始化轨迹存储
phi_range = linspace(0, 2*pi, N);
circle5 = zeros(N, 3); % 光斑轨迹
% 初始状态绘制
draw_mirror_circle(M5, M5_n, mirror_radius, [1, 0.6, 0.6], ‘M5’);
plot3(final_spot(1), final_spot(2), final_spot(3), ‘go’, ‘MarkerSize’, 8, ‘MarkerFaceColor’, ‘g’);
% 动画展示
if save_animation
filename1 = ‘rotation_mode1.gif’;
end
for i = 1:2:N
% 删除动态元素
delete(findobj(gca, ‘Tag’, ‘moving_point’));
delete(findobj(gca, ‘Tag’, ‘rotating_mirror’));
delete(findobj(gca, ‘Tag’, ‘current_light_path’));
phi = phi_range(i); n5_rot = Rx(rad2deg(phi)) * M5_n; % 绘制旋转后的镜子 draw_mirror_circle(M5, n5_rot, mirror_radius, [1, 0.6, 0.6], 'rotating_mirror'); % 计算当前光路 [current_path, current_reflection_pts, current_spot] = calculate_light_path(start_pt, [M1; M2; M3; M4; M5], ... [M1_n, M2_n, M3_n, M4_n, n5_rot], ray_length); circle5(i, :) = current_spot; % 绘制当前光斑 plot3(current_spot(1), current_spot(2), current_spot(3), 'o', ... 'MarkerSize', 12, 'MarkerFaceColor', 'g', 'Tag', 'moving_point'); % 绘制当前光路 plot_light_path(current_path, current_reflection_pts, 'r-b-g-m-c', 2, 'current_light_path'); % 捕获帧用于GIF if save_animation frame = getframe(fig1); im = frame2im(frame); [imind, cm] = rgb2ind(im, 256); if i == 1 imwrite(imind, cm, filename1, 'gif', 'Loopcount', inf, 'DelayTime', 0.1); else imwrite(imind, cm, filename1, 'gif', 'WriteMode', 'append', 'DelayTime', 0.1); end end pause(0.05);
end
% 绘制光斑轨迹
if plot_trajectory
plot3(circle5(:,1), circle5(:,2), circle5(:,3), ‘b-’, ‘LineWidth’, 2);
% 轨迹分析 trajectory_analysis(circle5, '镜子5旋转轨迹分析');
end
% 添加图例和偏差信息
legend(‘M1’, ‘M2’, ‘M3’, ‘M4’, ‘旋转轴’, ‘轨迹平面’, ‘初始光路’, ‘M5’, ‘初始光斑’, …
‘旋转镜子’, ‘当前光斑’, ‘当前光路’, ‘光斑轨迹’, ‘Location’, ‘eastoutside’);
deviation_text = sprintf(‘镜子偏差:\nM1: Yaw=%.1f°, Pitch=%.1f°\nM2: Yaw=%.1f°, Pitch=%.1f°\nM3: Yaw=%.1f°, Pitch=%.1f°\nM4: Yaw=%.1f°, Pitch=%.1f°\nM5: Yaw=%.1f°, Pitch=%.1f°’, …
deviation_angles(1,1), deviation_angles(1,2), …
deviation_angles(2,1), deviation_angles(2,2), …
deviation_angles(3,1), deviation_angles(3,2), …
deviation_angles(4,1), deviation_angles(4,2), …
deviation_angles(5,1), deviation_angles(5,2));
annotation(‘textbox’, [0.05, 0.7, 0.2, 0.2], ‘String’, deviation_text, …
‘BackgroundColor’, ‘white’, ‘FontSize’, 10);
axis([-150 150 -150 150 0 300]);
% ======================================================================
% 图2:镜子2-5整体绕z轴旋转(带偏差)
% ======================================================================
fig2 = figure(‘Position’, [900, 100, 1000, 800], ‘Name’, ‘整体绕z轴旋转(带偏差)’);
hold on; grid on; axis equal;
view(45, 30);
xlabel(‘X (cm)’); ylabel(‘Y (cm)’); zlabel(‘Z (cm)’);
title(‘镜子2-5整体绕z轴旋转 - 带偏差光路轨迹’,‘FontSize’,16,‘FontWeight’,‘bold’);
% 绘制固定元素
draw_mirror_circle(M1, M1_n, mirror_radius, [0.8, 0.8, 0.9], ‘M1’);
% 绘制旋转轴和光屏
plot3([0, 0], [0, 0], [-50, 300], ‘m–’, ‘LineWidth’, 2);
text(0, 0, 300, ‘旋转轴 (z轴)’, ‘FontSize’, 12, ‘Color’, ‘m’);
[X, Y] = meshgrid(linspace(-150,150,10), linspace(-150,150,10));
surf(X, Y, 300*ones(size(X)), ‘FaceAlpha’, 0.1, ‘EdgeColor’, ‘k’, ‘FaceColor’, ‘cyan’);
rectangle = [-100, -100, 300;
100, -100, 300;
100, 100, 300;
-100, 100, 300];
patch(‘Vertices’, rectangle, ‘Faces’, [1,2,3,4], …
‘FaceColor’, ‘cyan’, ‘FaceAlpha’, 0.1, ‘EdgeColor’, ‘b’);
text(0, 0, 310, ‘光屏平面 (z=300)’, ‘FontSize’, 12, ‘Color’, ‘b’);
% 初始化轨迹存储
theta_range = linspace(0, 2*pi, N);
final_spots = zeros(N, 3); % 光斑轨迹
screen_hits = false(N, 1); % 记录是否击中光屏
% 动画展示
if save_animation
filename2 = ‘rotation_mode2.gif’;
end
for i = 1:2:N
% 删除动态元素
delete(findobj(gca, ‘Tag’, ‘rotating_mirrors’));
delete(findobj(gca, ‘Tag’, ‘current_light_path’));
delete(findobj(gca, ‘Tag’, ‘final_spot’));
theta = theta_range(i); % 计算旋转后的位置和法向量 R_z = [cos(theta), -sin(theta), 0; sin(theta), cos(theta), 0; 0, 0, 1]; M2_rot = (R_z * (M2 - M1)')' + M1; M3_rot = (R_z * (M3 - M1)')' + M1; M4_rot = (R_z * (M4 - M1)')' + M1; M5_rot = (R_z * (M5 - M1)')' + M1; M2_n_rot = R_z * M2_n; M3_n_rot = R_z * M3_n; M4_n_rot = R_z * M4_n; M5_n_rot = R_z * M5_n; % 绘制旋转的镜子 draw_mirror_circle(M2_rot, M2_n_rot, mirror_radius, [0.9, 0.8, 0.8], 'rotating_mirrors'); draw_mirror_circle(M3_rot, M3_n_rot, mirror_radius, [0.8, 0.9, 0.8], 'rotating_mirrors'); draw_mirror_circle(M4_rot, M4_n_rot, mirror_radius, [0.9, 0.8, 0.9], 'rotating_mirrors'); draw_mirror_circle(M5_rot, M5_n_rot, mirror_radius, [1, 0.6, 0.6], 'rotating_mirrors'); % 计算当前光路 mirror_positions = [M1; M2_rot; M3_rot; M4_rot; M5_rot]; mirror_normals = [M1_n, M2_n_rot, M3_n_rot, M4_n_rot, M5_n_rot]; [path, reflection_pts, final_spot] = calculate_light_path(start_pt, mirror_positions, mirror_normals, ray_length); final_spots(i, :) = final_spot; % 检查是否击中光屏 screen_hits(i) = (abs(final_spot(1)) <= 100 && abs(final_spot(2)) <= 100 && abs(final_spot(3) - 300) < 1); % 绘制当前光路 plot_light_path(path, reflection_pts, 'r-b-g-m-c', 2, 'current_light_path'); % 绘制最终光斑(根据是否击中光屏使用不同颜色) if screen_hits(i) plot3(final_spot(1), final_spot(2), final_spot(3), 'go', ... 'MarkerSize', 10, 'MarkerFaceColor', 'g', 'Tag', 'final_spot'); else plot3(final_spot(1), final_spot(2), final_spot(3), 'ro', ... 'MarkerSize', 10, 'MarkerFaceColor', 'r', 'Tag', 'final_spot'); end % 捕获帧用于GIF if save_animation frame = getframe(fig2); im = frame2im(frame); [imind, cm] = rgb2ind(im, 256); if i == 1 imwrite(imind, cm, filename2, 'gif', 'Loopcount', inf, 'DelayTime', 0.1); else imwrite(imind, cm, filename2, 'gif', 'WriteMode', 'append', 'DelayTime', 0.1); end end pause(0.05);
end
% 绘制光斑轨迹
if plot_trajectory
% 分离击中光屏和未击中的点
hit_indices = find(screen_hits);
miss_indices = find(~screen_hits);
% 绘制击中光屏的轨迹 if ~isempty(hit_indices) plot3(final_spots(hit_indices,1), final_spots(hit_indices,2), final_spots(hit_indices,3), 'g-', 'LineWidth', 2); end % 绘制未击中光屏的轨迹 if ~isempty(miss_indices) plot3(final_spots(miss_indices,1), final_spots(miss_indices,2), final_spots(miss_indices,3), 'r-', 'LineWidth', 2); end % 轨迹分析 trajectory_analysis(final_spots, '整体旋转轨迹分析'); % 显示击中率 hit_rate = sum(screen_hits) / N * 100; text(0, 0, 320, sprintf('光屏击中率: %.1f%%', hit_rate), 'FontSize', 12, 'Color', 'b', 'HorizontalAlignment', 'center');
end
% 添加图例
legend(‘M1’, ‘旋转轴’, ‘光屏平面’, ‘光屏边界’, ‘M2’, ‘M3’, ‘M4’, ‘M5’, …
‘当前光路’, ‘击中光屏’, ‘未击中光屏’, ‘光斑轨迹(击中)’, ‘光斑轨迹(未击中)’, ‘Location’, ‘eastoutside’);
annotation(‘textbox’, [0.05, 0.7, 0.2, 0.2], ‘String’, deviation_text, …
‘BackgroundColor’, ‘white’, ‘FontSize’, 10);
plot3([0, 0], [0, 0], [290, 310], ‘c-’, ‘LineWidth’, 2);
text(0, 0, 310, ‘光屏平面 (z=300)’, ‘FontSize’, 12, ‘Color’, ‘b’);
axis([-150 150 -150 150 0 350]);
% ========== 增强功能:轨迹分析 ==========
function trajectory_analysis(points, title_str)
% 轨迹分析函数
figure(‘Name’, title_str);
subplot(2,2,1);
plot(points(:,1), points(:,2), ‘b.’);
title(‘XY平面投影’);
xlabel(‘X’); ylabel(‘Y’); axis equal;
subplot(2,2,2); plot(points(:,1), points(:,3), 'r.'); title('XZ平面投影'); xlabel('X'); ylabel('Z'); axis equal; subplot(2,2,3); plot(points(:,2), points(:,3), 'g.'); title('YZ平面投影'); xlabel('Y'); ylabel('Z'); axis equal; subplot(2,2,4); plot3(points(:,1), points(:,2), points(:,3), 'm-'); title('3D轨迹'); xlabel('X'); ylabel('Y'); zlabel('Z'); grid on; axis equal; sgtitle(title_str, 'FontSize', 14, 'FontWeight', 'bold'); % 计算轨迹范围 x_range = max(points(:,1)) - min(points(:,1)); y_range = max(points(:,2)) - min(points(:,2)); z_range = max(points(:,3)) - min(points(:,3)); fprintf('\n%s:\n', title_str); fprintf('X方向范围: %.2f cm\n', x_range); fprintf('Y方向范围: %.2f cm\n', y_range); fprintf('Z方向范围: %.2f cm\n', z_range); fprintf('轨迹中心: (%.2f, %.2f, %.2f)\n', mean(points(:,1)), mean(points(:,2)), mean(points(:,3)));
end
% ========== 辅助函数 ==========
function n_dev = apply_deviation(n0, angles)
% 应用水平和俯仰偏差到法向量
Ry = @(theta) [cosd(theta), 0, sind(theta); 0, 1, 0; -sind(theta), 0, cosd(theta)];
Rx = @(theta) [1, 0, 0; 0, cosd(theta), -sind(theta); 0, sind(theta), cosd(theta)];
n_dev = Rx(angles(2)) * Ry(angles(1)) * n0; n_dev = n_dev / norm(n_dev);
end
function [path, reflection_pts, final_spot] = calculate_light_path(start_pt, mirror_positions, mirror_normals, ray_length)
path = start_pt;
reflection_pts = zeros(5, 3);
current_point = start_pt; incident_dir = (mirror_positions(1,:) - current_point)'; incident_dir = incident_dir / norm(incident_dir); for i = 1:5 mirror_center = mirror_positions(i,:)'; mirror_normal = mirror_normals(:,i); denom = dot(incident_dir, mirror_normal); if abs(denom) < 1e-10 t = 1e10; else t = dot(mirror_center - current_point', mirror_normal) / denom; end reflection_point = current_point' + t * incident_dir; reflection_pts(i,:) = reflection_point'; path = [path; reflection_point']; reflection_dir = incident_dir - 2 * dot(incident_dir, mirror_normal) * mirror_normal; reflection_dir = reflection_dir / norm(reflection_dir); current_point = reflection_point'; incident_dir = reflection_dir; end final_spot = reflection_pts(5,:) + reflection_dir' * ray_length; path = [path; final_spot];
end
function draw_mirror_circle(center, normal, radius, color, tag)
theta = linspace(0, 2pi, 100);
v = null(normal’);
points = repmat(center, 100, 1) + radius(cos(theta)‘*v(:,1)’ + sin(theta)‘*v(:,2)’);
patch('Vertices', points, 'Faces', 1:100, ... 'FaceColor', color, 'EdgeColor', 'k', ... 'FaceAlpha', 0.7, 'LineWidth', 1.5, 'Tag', tag);
end
function plot_light_path(path, reflection_pts, colors, width, tag)
if nargin < 5, tag = ‘’; end
color_list = strsplit(colors, ‘-’);
plot3([path(1,1), reflection_pts(1,1)], ... [path(1,2), reflection_pts(1,2)], ... [path(1,3), reflection_pts(1,3)], ... [color_list{1}, '-'], 'LineWidth', width, 'Tag', tag); for i = 1:4 plot3([reflection_pts(i,1), reflection_pts(i+1,1)], ... [reflection_pts(i,2), reflection_pts(i+1,2)], ... [reflection_pts(i,3), reflection_pts(i+1,3)], ... [color_list{i+1}, '-'], 'LineWidth', width, 'Tag', tag); end plot3([reflection_pts(5,1), path(end,1)], ... [reflection_pts(5,2), path(end,2)], ... [reflection_pts(5,3), path(end,3)], ... [color_list{end}, '-'], 'LineWidth', width, 'Tag', tag);
end
报错
镜子5旋转轨迹分析:
X方向范围: 49.58 cm
Y方向范围: 199.92 cm
Z方向范围: 283.39 cm
轨迹中心: (-0.21, 1.67, 89.91)
警告: 忽略额外的图例条目。
位置:legend>process_inputs (第 592 行)
位置: legend>make_legend (第 319 行)
位置: legend (第 263 行)
位置: xuanzhuan4 (第 135 行)
整体旋转轨迹分析:
X方向范围: 30.19 cm
Y方向范围: 30.38 cm
Z方向范围: 297.36 cm
轨迹中心: (4.27, 2.07, 144.94)
警告: 忽略额外的图例条目。
位置:legend>process_inputs (第 592 行)
位置: legend>make_legend (第 319 行)
位置: legend (第 263 行)
位置: xuanzhuan4 (第 277 行)