Stewart并联结构两自由度正逆解计算和工作空间仿真

发布于:2025-06-30 ⋅ 阅读:(18) ⋅ 点赞:(0)

目录

A、所有程序打包下载连接

一、逆解计算

1、逆解计算

(1)两自由度平台三维模型

(2)两自由度平台结构简图

(3)Matlab逆解计算代码

(4)测试计算

2、逆解计算代码优化和函数封装

(1)优化上述代码

(2)封装后代码

(3)测试计算

二、正解计算

1、正解计算代码

2、正解计算测试1

3、正解计算测试2

(1)俯仰角10度

(2)翻滚角15度

三、动画仿真运动

1、动画仿真实现功能

2、动画仿真效果展示

3、程序代码

四、工作空间分析与可视化

1、图像效果

2、程序代码

五、运动平台中心点工作空间计算

1、工作空间计算功能要求

2、工作空间图像效果

3、程序代码


A、所有程序打包下载连接

https://download.csdn.net/download/panjinliang066333/91186145

一、逆解计算

1、逆解计算

(1)两自由度平台三维模型

平台由两个自由度由两个电动缸运动实现,两个自由度分别为俯仰运动、翻滚运动。固定点,为万向节平衡点和两个电动缸共同支撑上平面。

(2)两自由度平台结构简图

根据结构简图,进行数学建模

电动缸总行程为250,在行程为125的情况下,上平台的俯仰角和翻滚角都为0.

依次分别计算出:四个点A、B、a、b的坐标

D和d分别为O、O到AB、ab的距离

D=sqrt(L1 * L1 - (L2/2) * (L2/2));
A1=[-L2/2;                          D;                        0];
A2=[L2/2;                           D;                        0];

d=sqrt(S1 * S1 - (S2/2) * (S2/2));
a1=[-S2/2;                          d;                         0];
a2=[S2/2;                           d;                         0];

(3)Matlab逆解计算代码


syms L1 L2 ;                                
syms S1 S2 ;                                
syms H h;                                   
syms A B C x y z ;                          

syms Tx Ty Tz T  ;                           
syms A1 A2  a1 a2 ;                   
syms D d;

syms ML1 ML2 ;                                

%设备参数
L1=250;
L2=250*1.41421356;
S1=250;
S2=250*1.41421356;
H=746;                                      %缸体长度
L=250;                                      %电动缸行程

D=sqrt(L1 * L1 - (L2/2) * (L2/2));
A1=[-L2/2;                          D;                        0];
A2=[L2/2;                           D;                        0];

d=sqrt(S1 * S1 - (S2/2) * (S2/2));
a1=[-S2/2;                          d;                         0];
a2=[S2/2;                           d;                         0];

A=input('请输入俯仰角A:');
B=input('请输入翻滚角B:');

A=(A/180)*pi;
B=(B/180)*pi;

x=0;
y=0;
z=0;
z=H+L/2;
P=[x;y;z];  

Tx=[1               0               0;
    0               cos(A)          -sin(A);
    0               sin(A)         cos(A)];    

Ty=[cos(B)          0               sin(B);
    0               1               0;
   -sin(B)          0               cos(B)];

T=Tx * Ty;


ML1=sqrt((a1(1,1)-A1(1,1))^2+(a1(2,1)-A1(2,1))^2+(a1(3,1)-A1(3,1))^2);
ML2=sqrt((a2(1,1)-A2(1,1))^2+(a2(2,1)-A2(2,1))^2+(a2(3,1)-A2(3,1))^2);

%打印显示——根据下底板轴分布来确定
fprintf('1#电动缸长度是:%f \n',ML1);
fprintf('2#电动缸长度是:%f \n',ML2);

fprintf('1#电动缸当前行程:%f \n',ML1-H);
fprintf('2#电动缸当前行程:%f \n',ML2-H);

(4)测试计算

1、计算俯仰角10度

2、计算翻滚角15度

2、逆解计算代码优化和函数封装

(1)优化上述代码

先对上述代码进行优化,

优化上述并联结构两自由度逆解程序,主要改进包括:

1、使用更清晰的变量命名

2、添加注释说明

3、优化矩阵运算

4、增加输入验证

5、改进输出格式

优化后的代码

function NJ()
    % 并联平台两自由度逆解计算程序
    % 输入俯仰角和翻滚角,计算两个电动缸的伸长量
    
    % 清空工作区
    clearvars;
    close all;
    %clc;
    
    %% 平台几何参数定义
    % 上平台安装点参数
    upper_platform.L1 = 250;         % 上平台特征长度1 (mm)
    upper_platform.L2 = 250*sqrt(2); % 上平台特征长度2 (mm)
    upper_platform.H = 746;          % 缸体长度 (mm)
    upper_platform.stroke = 250;     % 电动缸最大行程 (mm)
    
    % 下平台安装点参数
    lower_platform.S1 = 250;         % 下平台特征长度1 (mm)
    lower_platform.S2 = 250*sqrt(2); % 下平台特征长度2 (mm)
    
    %% 安装点位置计算
    % 计算上平台安装点位置
    upper_platform.D = sqrt(upper_platform.L1^2 - (upper_platform.L2/2)^2);
    upper_platform.A1 = [-upper_platform.L2/2; upper_platform.D; 0];
    upper_platform.A2 = [ upper_platform.L2/2; upper_platform.D; 0];
    
    % 计算下平台安装点位置
    lower_platform.d = sqrt(lower_platform.S1^2 - (lower_platform.S2/2)^2);
    lower_platform.a1 = [-lower_platform.S2/2; lower_platform.d; 0];
    lower_platform.a2 = [ lower_platform.S2/2; lower_platform.d; 0];
    
    %% 用户输入
    % 获取用户输入的姿态角度(度)
    while true
        try
            pitch_angle_deg = input('请输入俯仰角Pitch (度): ');
            roll_angle_deg = input('请输入翻滚角Roll (度): ');
            
            % 验证输入是否为数值
            if ~isnumeric(pitch_angle_deg) || ~isnumeric(roll_angle_deg)
                error('输入必须为数值');
            end
            
            % 转换为弧度
            pitch_angle = deg2rad(pitch_angle_deg);
            roll_angle = deg2rad(roll_angle_deg);
            break;
            
        catch
            fprintf('输入无效,请重新输入数值\n');
        end
    end
    
    %% 平台位置和姿态计算
    % 平台中心位置(初始位置在中立点)
    platform_center = [0; 0; upper_platform.H + upper_platform.stroke/2];
    
    % 旋转矩阵
    % 俯仰旋转矩阵 (绕X轴)
    Rx = [1,  0,          0;
           0,  cos(pitch_angle), -sin(pitch_angle);
           0,  sin(pitch_angle),  cos(pitch_angle)];
    
    % 翻滚旋转矩阵 (绕Y轴)
    Ry = [cos(roll_angle),  0,  sin(roll_angle);
           0,          1,        0;
          -sin(roll_angle), 0,  cos(roll_angle)];
    
    % 组合旋转
    R = Rx * Ry;
    
    
    % 计算电动缸长度
    actuator1_length = norm(rotated_a1 - upper_platform.A1);
    actuator2_length = norm(rotated_a2 - upper_platform.A2);
    
    % 计算电动缸行程(相对于中立位置)
    actuator1_stroke = actuator1_length - upper_platform.H;
    actuator2_stroke = actuator2_length - upper_platform.H;
    
    %% 结果输出
    fprintf('\n=== 计算结果 ===\n');
    fprintf('电动缸1总长度: %.3f mm\n', actuator1_length);
    fprintf('电动缸2总长度: %.3f mm\n', actuator2_length);
    fprintf('------------------\n');
    fprintf('电动缸1行程: %.3f mm\n', actuator1_stroke);
    fprintf('电动缸2行程: %.3f mm\n', actuator2_stroke);
    fprintf('==================\n');
    
    % 检查是否超出行程限制
%     max_stroke = upper_platform.stroke/2;
%     if abs(actuator1_stroke) > max_stroke || abs(actuator2_stroke) > max_stroke
%         fprintf('\n警告:电动缸行程超出限制 (±%.1f mm)!\n', max_stroke);
%     end

    % 明确定义中立位置和行程方向
    neutral_length = upper_platform.H;  % 中立位置长度
    min_length = neutral_length - upper_platform.stroke;  % 最短长度
    max_length = neutral_length + upper_platform.stroke;  % 最长长度

    %$ 检查是否超出物理限制
    if actuator1_length < min_length || actuator1_length > max_length || ...
       actuator2_length < min_length || actuator2_length > max_length
        fprintf('警告:电动缸长度超出物理限制 (%.1f mm ~ %.1f mm)!\n', min_length, max_length);
    end
end

(2)封装后代码

function [actuator_lengths, actuator_strokes] = parallel_platform_ik(pitch_angle_deg, roll_angle_deg)
    % PARALLEL_PLATFORM_IK 并联平台两自由度逆运动学计算
    %
    % 输入参数:
    %   pitch_angle_deg : 俯仰角(度)
    %   roll_angle_deg  : 翻滚角(度)
    %
    % 输出参数:
    %   actuator_lengths : 2x1向量,两个电动缸的总长度 [mm]
    %   actuator_strokes : 2x1向量,两个电动缸的行程(相对于中立位置)[mm]
    %
    % 示例:
    %   [lengths, strokes] = parallel_platform_ik(10, 5);
    %   fprintf('电动缸长度: %.2f mm, %.2f mm\n', lengths(1), lengths(2));
    %   fprintf('电动缸行程: %.2f mm, %.2f mm\n', strokes(1), strokes(2));

    %% 平台几何参数定义
    % 上平台安装点参数
    upper_platform.L1 = 250;         % 上平台特征长度1 (mm)
    upper_platform.L2 = 250*sqrt(2); % 上平台特征长度2 (mm)
    upper_platform.H = 746;          % 缸体长度 (mm)
    upper_platform.stroke = 250;     % 电动缸最大行程 (mm)
    
    % 下平台安装点参数
    lower_platform.S1 = 250;         % 下平台特征长度1 (mm)
    lower_platform.S2 = 250*sqrt(2); % 下平台特征长度2 (mm)
    
    %% 安装点位置计算
    % 计算上平台安装点位置
    upper_platform.D = sqrt(upper_platform.L1^2 - (upper_platform.L2/2)^2);
    upper_platform.A1 = [-upper_platform.L2/2; upper_platform.D; 0];
    upper_platform.A2 = [ upper_platform.L2/2; upper_platform.D; 0];
    
    % 计算下平台安装点位置
    lower_platform.d = sqrt(lower_platform.S1^2 - (lower_platform.S2/2)^2);
    lower_platform.a1 = [-lower_platform.S2/2; lower_platform.d; 0];
    lower_platform.a2 = [ lower_platform.S2/2; lower_platform.d; 0];
    
    %% 输入验证
    if ~isnumeric(pitch_angle_deg) || ~isnumeric(roll_angle_deg)
        error('输入角度必须为数值');
    end
    
    %% 平台位置和姿态计算
    % 将角度转换为弧度
    pitch_angle = deg2rad(pitch_angle_deg);
    roll_angle = deg2rad(roll_angle_deg);
    
    % 平台中心位置(初始位置在中立点)
    platform_center = [0; 0; upper_platform.H + upper_platform.stroke/2];
    
    % 旋转矩阵
    % 俯仰旋转矩阵 (绕X轴)
    Rx = [1,  0,          0;
          0,  cos(pitch_angle), -sin(pitch_angle);
          0,  sin(pitch_angle),  cos(pitch_angle)];
    
    % 翻滚旋转矩阵 (绕Y轴)
    Ry = [cos(roll_angle),  0,  sin(roll_angle);
          0,          1,        0;
         -sin(roll_angle),  0,  cos(roll_angle)];
    
    % 组合旋转
    R = Rx * Ry;
    
    
    % 计算电动缸长度
    actuator_lengths = [
        norm(rotated_a1 - upper_platform.A1);
        norm(rotated_a2 - upper_platform.A2)
    ];
    
    % 计算电动缸行程(相对于中立位置)
    actuator_strokes = actuator_lengths - upper_platform.H;
    
    %% 行程限制检查(可选)
    max_stroke = upper_platform.stroke;
    if any(abs(actuator_strokes) > max_stroke)
        warning('电动缸行程超出限制 (±%.1f mm)', max_stroke);
    end
end

(3)测试计算

1、计算俯仰角10度

[actuator_lengths, actuator_strokes] = parallel_platform_ik(10, 0)

2、计算翻滚角15度

[actuator_lengths, actuator_strokes] = parallel_platform_ik(0, 15)

二、正解计算

正解计算(即已知电动缸长度,求平台姿态)通常需要数值迭代方法,这里采用牛顿-拉夫森法(Newton-Raphson)进行求解

1、正解计算代码

function [pitch_angle_deg, roll_angle_deg] = parallel_platform_fk(L1_actual, L2_actual)
    % PARALLEL_PLATFORM_FK 并联平台两自由度正运动学计算
    %
    % 输入参数:
    %   L1_actual : 电动缸1的实际长度 (mm)
    %   L2_actual : 电动缸2的实际长度 (mm)
    %
    % 输出参数:
    %   pitch_angle_deg : 俯仰角 (度)
    %   roll_angle_deg  : 翻滚角 (度)
    %
    % 示例:
    %   [pitch, roll] = parallel_platform_fk(800, 820);

    %% 平台几何参数(与逆解一致)
    % 上平台安装点参数
    upper.L1 = 250;         % 上平台特征长度1 (mm)
    upper.L2 = 250*sqrt(2); % 上平台特征长度2 (mm)
    upper.H = 746;          % 缸体长度 (mm)
    upper.stroke = 250;     % 电动缸最大行程 (mm)
    
    % 下平台安装点参数
    lower.S1 = 250;         % 下平台特征长度1 (mm)
    lower.S2 = 250*sqrt(2); % 下平台特征长度2 (mm)
    
    %% 安装点位置计算
    upper.D = sqrt(upper.L1^2 - (upper.L2/2)^2);
    upper.A1 = [-upper.L2/2; upper.D; 0];
    upper.A2 = [ upper.L2/2; upper.D; 0];
    
    lower.d = sqrt(lower.S1^2 - (lower.S2/2)^2);
    lower.a1 = [-lower.S2/2; lower.d; 0];
    lower.a2 = [ lower.S2/2; lower.d; 0];
    
    %% 初始猜测(中立位置)
    pitch_angle = 0;  % 俯仰角初始猜测 (rad)
    roll_angle = 0;   % 翻滚角初始猜测 (rad)
    
    %% 牛顿-拉夫森法迭代求解
    max_iter = 100;       % 最大迭代次数
    tolerance = 1e-6;     % 收敛容差
    iter = 0;             % 迭代计数器
    converged = false;    % 收敛标志
    
    % 中立位置平台中心高度
    neutral_height = upper.H + upper.stroke/2;
    
    while ~converged && iter < max_iter
        % 计算当前姿态下的电动缸长度
        [L1_calculated, L2_calculated] = compute_actuator_lengths(...
            pitch_angle, roll_angle, upper, lower, neutral_height);
        
        % 计算残差(实际长度与计算长度的差)
        residual = [L1_actual - L1_calculated;
                   L2_actual - L2_calculated];
        
        % 检查是否收敛
        if norm(residual) < tolerance
            converged = true;
            break;
        end
        
        % 计算雅可比矩阵(数值近似)
        delta = 1e-6;  % 微小扰动
        
        % 对俯仰角的偏导
        [L1_pitch, L2_pitch] = compute_actuator_lengths(...
            pitch_angle + delta, roll_angle, upper, lower, neutral_height);
        J(1,1) = (L1_pitch - L1_calculated) / delta; % dL1/dPitch
        J(2,1) = (L2_pitch - L2_calculated) / delta; % dL2/dPitch
        
        % 对翻滚角的偏导
        [L1_roll, L2_roll] = compute_actuator_lengths(...
            pitch_angle, roll_angle + delta, upper, lower, neutral_height);
        J(1,2) = (L1_roll - L1_calculated) / delta; % dL1/dRoll
        J(2,2) = (L2_roll - L2_calculated) / delta; % dL2/dRoll
        
        % 求解线性系统并更新角度
        delta_angles = J \ residual;
        pitch_angle = pitch_angle + delta_angles(1);
        roll_angle = roll_angle + delta_angles(2);
        
        iter = iter + 1;
    end
    
    %% 输出结果
    if ~converged
        warning('正解计算未收敛,结果可能不准确');
    end
    
    % 转换为角度输出
    pitch_angle_deg = rad2deg(pitch_angle);
    roll_angle_deg = rad2deg(roll_angle);
    
    % 可选:打印迭代信息
    fprintf('正解计算完成,迭代次数: %d\n', iter);
    fprintf('最终残差: %.6f mm\n', norm(residual));
end

2、正解计算测试1

测试代码

% 示例1:已知电动缸长度求姿态
%翻滚角-38度,两个电动缸长度
[pitch, roll] = parallel_platform_fk(763.086, 980.551);         
fprintf('平台姿态: 俯仰角=%.2f°, 翻滚角=%.2f°\n', pitch, roll);

% 示例2:验证正逆解一致性
% 先给定角度计算长度
[lengths, ~] = parallel_platform_ik(10, 5);
% 再用长度反求角度
[pitch, roll] = parallel_platform_fk(lengths(1), lengths(2));
fprintf('验证结果应与输入角度(10°,5°)接近:\n');
fprintf('计算姿态: 俯仰角=%.4f°, 翻滚角=%.4f°\n', pitch, roll);

3、正解计算测试2

(1)俯仰角10度

(2)翻滚角15度

三、动画仿真运动

1、动画仿真实现功能

功能要求:

1、计算该运动平台在中立位置开始运动:俯仰角±15度范围内、翻滚角±35度范围内的工作空间。平台先完成俯仰运动(±15°)再完成翻滚运动(±35°)。

2、绘制出该两自由度并联运动平台三维结构图、并绘制出工作空间的三维曲面图形,图像动画显示。

3、生成相应的视频动画,视频保存在指定文件夹中。

2、动画仿真效果展示

平台运动模拟画面

电动缸数据

3、程序代码

%%俯仰和翻滚先后运动
%俯仰角±15度、翻滚角:±38度
function parallel_platform_sequential_motion()
    % 主函数:先俯仰后翻滚的顺序运动
    
    % 1. 初始化平台参数
    [upper, lower] = init_platform_parameters();
    
    % 2. 计算工作空间数据
    [PITCH, ROLL, L1, L2, stroke_usage] = calculate_workspace(upper, lower);
    
    % 3. 绘制工作空间曲面
    plot_workspace_surfaces(PITCH, ROLL, L1, L2, stroke_usage);
    
    % 4. 执行顺序运动动画(先俯仰后翻滚)
    animate_sequential_motion(upper, lower);
end

function [upper, lower] = init_platform_parameters()
    % 初始化平台几何参数
    upper.L1 = 250;
    upper.L2 = 250*sqrt(2);
    upper.H = 746;
    upper.stroke = 250;
    
    lower.S1 = 250;
    lower.S2 = 250*sqrt(2);
    
    % 计算安装点位置
    upper.D = sqrt(upper.L1^2 - (upper.L2/2)^2);
    upper.A1 = [-upper.L2/2; upper.D; 0];
    upper.A2 = [upper.L2/2; upper.D; 0];
    
    lower.d = sqrt(lower.S1^2 - (lower.S2/2)^2);
    lower.a1 = [-lower.S2/2; lower.d; 0];
    lower.a2 = [lower.S2/2; lower.d; 0];
end

function [PITCH, ROLL, L1, L2, stroke_usage] = calculate_workspace(upper, lower)
    % 计算工作空间数据
    pitch_range = linspace(-15, 15, 30);
    roll_range = linspace(-35, 35, 30);
    [PITCH, ROLL] = meshgrid(pitch_range, roll_range);
    
    L1 = zeros(size(PITCH));
    L2 = zeros(size(PITCH));
    
    for i = 1:numel(PITCH)
        [L1(i), L2(i)] = compute_actuator_lengths(...
            deg2rad(PITCH(i)), deg2rad(ROLL(i)), upper, lower);
    end
    
    stroke_usage = (L1 - upper.H) / (upper.stroke/2) * 100;
end

function [L1, L2] = compute_actuator_lengths(pitch, roll, upper, lower)
    % 计算电动缸长度
    platform_center = [0; 0; upper.H + upper.stroke/2];
    
    Rx = [1 0 0; 0 cos(pitch) -sin(pitch); 0 sin(pitch) cos(pitch)];
    Ry = [cos(roll) 0 sin(roll); 0 1 0; -sin(roll) 0 cos(roll)];
    R = Rx * Ry;
    
    rotated_a1 = R * lower.a1 + platform_center;
    rotated_a2 = R * lower.a2 + platform_center;
    
    L1 = norm(rotated_a1 - upper.A1);
    L2 = norm(rotated_a2 - upper.A2);
end

function plot_workspace_surfaces(PITCH, ROLL, L1, L2, stroke_usage)
    % 绘制工作空间曲面图
    figure('Name', '工作空间分析', 'Color', 'white', 'Position', [100 100 1200 800]);
    
    subplot(2,2,1);
    surf(PITCH, ROLL, L1, 'EdgeColor', 'none');
    title('电动缸1长度 (mm)');
    xlabel('俯仰角 (°)'); ylabel('翻滚角 (°)'); zlabel('长度 (mm)');
    colorbar; axis tight; view(3);
    
    subplot(2,2,2);
    surf(PITCH, ROLL, L2, 'EdgeColor', 'none');
    title('电动缸2长度 (mm)');
    xlabel('俯仰角 (°)'); ylabel('翻滚角 (°)'); zlabel('长度 (mm)');
    colorbar; axis tight; view(3);
    
    subplot(2,2,3);
    surf(PITCH, ROLL, stroke_usage, 'EdgeColor', 'none');
    title('电动缸行程使用率 (%)');
    xlabel('俯仰角 (°)'); ylabel('翻滚角 (°)'); zlabel('使用率 (%)');
    colorbar; caxis([-100 100]); view(3);
    
    subplot(2,2,4);
    contour(PITCH, ROLL, stroke_usage, 'LineWidth', 2);
    title('工作空间边界');
    xlabel('俯仰角 (°)'); ylabel('翻滚角 (°)');
    colorbar; caxis([-100 100]);
    hold on;
    plot(0, 0, 'ro', 'MarkerSize', 10, 'LineWidth', 2);
    text(0, 0, ' 中立位置', 'VerticalAlignment', 'bottom');
end



function animate_sequential_motion(upper, lower)
    % 顺序运动动画:先俯仰后翻滚
    fig = figure('Name', '平台顺序运动动画', 'Color', 'white', 'Position', [200 200 800 600]);
    
    % 创建临时视频文件
    try
        %video_path = fullfile(tempdir, 'sequential_motion.mp4');
        video_path = 'C:\Users\97205\Desktop\两自由度-Matlab\platform_animation.mp4';  % Windows示例
        writerObj = VideoWriter(video_path, 'MPEG-4');
        writerObj.FrameRate = 20;
        open(writerObj);
    catch
        error('无法创建视频文件,请检查写入权限');
    end
    
    % ========== 第一阶段:俯仰运动 ==========
    pitch_range = linspace(0, 15, 15);  % 0°→15°
    for pitch = [pitch_range, fliplr(pitch_range), -pitch_range, fliplr(-pitch_range)]
        clf(fig);
        plot_single_pose(upper, lower, pitch, 0); % 保持roll=0
        title(sprintf('俯仰运动阶段\n俯仰角: %.1f°, 翻滚角: %.1f°', pitch, 0));
        
        frame = getframe(fig);
        writeVideo(writerObj, frame);
        pause(0.05);
    end
    
    % ========== 第二阶段:翻滚运动 ==========
    roll_range = linspace(0, 35, 20);  % 0°→35°
    for roll = [roll_range, fliplr(roll_range), -roll_range, fliplr(-roll_range)]
        clf(fig);
        plot_single_pose(upper, lower, 0, roll); % 保持pitch=0
        title(sprintf('翻滚运动阶段\n俯仰角: %.1f°, 翻滚角: %.1f°', 0, roll));
        
        frame = getframe(fig);
        writeVideo(writerObj, frame);
        pause(0.05);
    end
    
    close(writerObj);
    fprintf('顺序运动动画已保存到: %s\n', video_path);
    
    % 显示复合运动(可选)
    figure('Name', '复合运动演示', 'Position', [300 300 800 600]);
    for pitch = linspace(-15, 15, 30)
        for roll = linspace(-35, 35, 30)
            clf;
            plot_single_pose(upper, lower, pitch, roll);
            title(sprintf('复合运动演示\n俯仰角: %.1f°, 翻滚角: %.1f°', pitch, roll));
            drawnow;
        end
    end
end


function plot_single_pose(upper, lower, pitch_deg, roll_deg)
    % 绘制单个姿态
    pitch = deg2rad(pitch_deg);
    roll = deg2rad(roll_deg);
    platform_center = [0; 0; upper.H + upper.stroke/2];
    
    % 旋转矩阵
    Rx = [1 0 0; 0 cos(pitch) -sin(pitch); 0 sin(pitch) cos(pitch)];
    Ry = [cos(roll) 0 sin(roll); 0 1 0; -sin(roll) 0 cos(roll)];
    R = Rx * Ry;
    
    % 计算平台位置
    lower_pts = [lower.a1, lower.a2, -lower.a1, -lower.a2];
    lower_pts = R * lower_pts + repmat(platform_center, 1, 4);
    
    rotated_a1 = R * lower.a1 + platform_center;
    rotated_a2 = R * lower.a2 + platform_center;
    
    % 绘制平台
    fill3(lower_pts(1,[1 2 3]), lower_pts(2,[1 2 3]), lower_pts(3,[1 2 3]), 'b', 'FaceAlpha', 0.3);
    hold on;
    fill3(lower_pts(1,[3 4 1]), lower_pts(2,[3 4 1]), lower_pts(3,[3 4 1]), 'b', 'FaceAlpha', 0.3);
    
    upper_pts = [upper.A1, upper.A2, -upper.A1, -upper.A2];
    fill3(upper_pts(1,[1 2 3]), upper_pts(2,[1 2 3]), upper_pts(3,[1 2 3]), 'r', 'FaceAlpha', 0.3);
    fill3(upper_pts(1,[3 4 1]), upper_pts(2,[3 4 1]), upper_pts(3,[3 4 1]), 'r', 'FaceAlpha', 0.3);
    
    % 绘制电动缸
    plot3([upper.A1(1), rotated_a1(1)], [upper.A1(2), rotated_a1(2)], [upper.A1(3), rotated_a1(3)], 'k', 'LineWidth', 3);
    plot3([upper.A2(1), rotated_a2(1)], [upper.A2(2), rotated_a2(2)], [upper.A2(3), rotated_a2(3)], 'k', 'LineWidth', 3);
    
    % 设置图形属性
    axis equal; grid on;
    xlabel('X (mm)'); ylabel('Y (mm)'); zlabel('Z (mm)');
    view(30, 30);
    xlim([-500 500]); ylim([-500 500]);
    zlim([0, upper.H + upper.stroke]);
end

四、工作空间分析与可视化

实现功能要求:给定几个姿态角度,得到上平台运动图像和电动缸长度

1、图像效果

平台结构

工作空间分析

2、程序代码


%% 主程序:工作空间分析与可视化
function parallel_platform_workspace_analysis()
    % 清空工作区
    clear; close all; clc;
    
    %% 1. 平台几何参数定义
    % 上平台安装点参数
    upper.L1 = 250;         % 上平台特征长度1 (mm)
    upper.L2 = 250*sqrt(2); % 上平台特征长度2 (mm)
    upper.H = 746;          % 缸体长度 (mm)
    upper.stroke = 250;     % 电动缸最大行程 (mm)
    
    % 下平台安装点参数
    lower.S1 = 250;         % 下平台特征长度1 (mm)
    lower.S2 = 250*sqrt(2); % 下平台特征长度2 (mm)
    
    % 计算安装点位置
    [upper, lower] = calculate_platform_geometry(upper, lower);
    
    %% 2. 工作空间计算
    % 定义角度范围
    pitch_range = linspace(-15, 15, 30); % 俯仰角范围 ±15°
    roll_range = linspace(-35, 35, 30);  % 翻滚角范围 ±35°
    
    % 初始化存储矩阵
    [PITCH, ROLL] = meshgrid(pitch_range, roll_range);
    L1 = zeros(size(PITCH));
    L2 = zeros(size(PITCH));
    Z_pos = zeros(size(PITCH));
    
    % 遍历所有角度组合
    for i = 1:numel(PITCH)
        % 计算当前姿态下的电动缸长度
        [L1(i), L2(i)] = compute_actuator_lengths(...
            deg2rad(PITCH(i)), deg2rad(ROLL(i)), upper, lower);
        
        % 计算平台中心高度
        Z_pos(i) = upper.H + upper.stroke/2;
    end
    
    %% 3. 绘制工作空间曲面
    figure('Name', '工作空间分析', 'Color', 'white');
    
    % 电动缸长度曲面
    subplot(2,2,1);
    surf(PITCH, ROLL, L1, 'EdgeColor', 'none');
    title('电动缸1长度 (mm)');
    xlabel('俯仰角 (deg)'); ylabel('翻滚角 (deg)'); zlabel('长度 (mm)');
    colorbar; axis tight; view(3);
    
    subplot(2,2,2);
    surf(PITCH, ROLL, L2, 'EdgeColor', 'none');
    title('电动缸2长度 (mm)');
    xlabel('俯仰角 (deg)'); ylabel('翻滚角 (deg)'); zlabel('长度 (mm)');
    colorbar; axis tight; view(3);
    
    % 行程使用率曲面
    subplot(2,2,3);
    stroke_usage1 = (L1 - upper.H) / (upper.stroke/2) * 100;
    surf(PITCH, ROLL, stroke_usage1, 'EdgeColor', 'none');
    title('电动缸1行程使用率 (%)');
    xlabel('俯仰角 (deg)'); ylabel('翻滚角 (deg)'); zlabel('使用率 (%)');
    colorbar; caxis([-100 100]); view(3);
    
    subplot(2,2,4);
    stroke_usage2 = (L2 - upper.H) / (upper.stroke/2) * 100;
    surf(PITCH, ROLL, stroke_usage2, 'EdgeColor', 'none');
    title('电动缸2行程使用率 (%)');
    xlabel('俯仰角 (deg)'); ylabel('翻滚角 (deg)'); zlabel('使用率 (%)');
    colorbar; caxis([-100 100]); view(3);
    
    %% 4. 绘制平台三维结构图
    % 选择几个典型姿态进行可视化
    demo_angles = [0 0; 15 0; 0 35; -10 -20]; % [pitch, roll]
    
    figure('Name', '平台三维结构', 'Color', 'white', 'Position', [100 100 1200 800]);
    for i = 1:4
        subplot(2,2,i);
        plot_platform_3d(upper, lower, demo_angles(i,1), demo_angles(i,2));
        title(sprintf('姿态: Pitch=%.0f°, Roll=%.0f°', demo_angles(i,1), demo_angles(i,2)));
    end
    
    %% 5. 工作空间边界分析
    figure('Name', '工作空间边界', 'Color', 'white');
    
    % 计算边界条件
    [boundary_pitch, boundary_roll] = find_workspace_boundary(pitch_range, roll_range, L1, L2, upper);
    
    % 绘制工作空间边界
    plot3(boundary_pitch, boundary_roll, zeros(size(boundary_pitch)), 'r-', 'LineWidth', 2);
    hold on;
    scatter3(PITCH(:), ROLL(:), zeros(numel(PITCH),1), 10, 'filled', 'MarkerFaceAlpha', 0.3);
    xlabel('俯仰角 (deg)'); ylabel('翻滚角 (deg)');
    title('工作空间边界 (红色)');
    grid on; axis tight; view(2);
end

%% 几何计算函数
function [upper, lower] = calculate_platform_geometry(upper, lower)
    % 计算上平台安装点位置
    upper.D = sqrt(upper.L1^2 - (upper.L2/2)^2);
    upper.A1 = [-upper.L2/2; upper.D; 0];
    upper.A2 = [ upper.L2/2; upper.D; 0];
    
    % 计算下平台安装点位置
    lower.d = sqrt(lower.S1^2 - (lower.S2/2)^2);
    lower.a1 = [-lower.S2/2; lower.d; 0];
    lower.a2 = [ lower.S2/2; lower.d; 0];
end

%% 电动缸长度计算函数
function [L1, L2] = compute_actuator_lengths(pitch, roll, upper, lower)
    % 平台中心位置(中立高度)
    platform_center = [0; 0; upper.H + upper.stroke/2];
    
    % 旋转矩阵
    Rx = [1,  0,        0;
           0, cos(pitch), -sin(pitch);
           0, sin(pitch),  cos(pitch)];
    
    Ry = [cos(roll), 0, sin(roll);
           0,        1,       0;
          -sin(roll), 0, cos(roll)];
    
    R = Rx * Ry;
    
    % 计算旋转后的下平台安装点位置
    rotated_a1 = R * lower.a1 + platform_center;
    rotated_a2 = R * lower.a2 + platform_center;
    
    % 计算电动缸长度
    L1 = norm(rotated_a1 - upper.A1);
    L2 = norm(rotated_a2 - upper.A2);
end

%% 工作空间边界计算函数
function [boundary_pitch, boundary_roll] = find_workspace_boundary(pitch_range, roll_range, L1, L2, upper)
    % 找到达到行程限制的点
    max_stroke = upper.stroke/2;
    stroke1 = L1 - upper.H;
    stroke2 = L2 - upper.H;
    
    % 找出接近行程限制的边界点
    threshold = 0.95; % 识别阈值为95%行程
    boundary_idx = find(abs(stroke1) > max_stroke*threshold | abs(stroke2) > max_stroke*threshold);
    
    % 提取边界角度
    boundary_pitch = PITCH(boundary_idx);
    boundary_roll = ROLL(boundary_idx);
    
    % 对边界点进行排序(便于绘制闭合曲线)
    [~, idx] = sort(atan2d(boundary_roll, boundary_pitch));
    boundary_pitch = boundary_pitch(idx);
    boundary_roll = boundary_roll(idx);
end


五、运动平台中心点工作空间计算

1、工作空间计算功能要求

该两自由度上平台中心点,在上述给定的俯仰角、翻滚角范围内,俯仰角和翻滚角以0.1的分辨率进行迭代,计算所有可能存在的空间位置,绘制出所有空间位置的坐标点图像。

2、工作空间图像效果

3、程序代码

%%绘制工作空间图像
%平台中心点,在上述给定的俯仰角、翻滚角范围内,俯仰角和翻滚角以0.1的分辨率进行迭代,
%计算所有可能存在的空间位置,绘制出所有空间位置的坐标点图像
function plot_highres_platform_workspace()
    % 初始化平台参数
    [upper, lower] = init_platform_parameters();
    
    % 定义角度范围及分辨率(0.1°步长)
    pitch_range = -15:0.1:15;    % 俯仰角±15°,0.1°分辨率
    roll_range = -35:0.1:35;     % 翻滚角±35°,0.1°分辨率
    
    % 预分配内存(估算点数)
    num_points = length(pitch_range) * length(roll_range);
    points = zeros(num_points, 3);
    colors = zeros(num_points, 3); % 用于存储颜色数据
    
    % 计算所有可能的空间位置
    idx = 1;
    for pitch = pitch_range
        for roll = roll_range
            % 计算平台中心位置(考虑高度变化)
            platform_center = calculate_platform_center(...
                deg2rad(pitch), deg2rad(roll), upper);
            
            points(idx,:) = platform_center';
            
            % 生成颜色映射(基于角度)
            colors(idx,:) = [ 
                (pitch - min(pitch_range))/range(pitch_range), ...  % 红色分量表示俯仰
                (roll - min(roll_range))/range(roll_range), ...     % 绿色分量表示翻滚
                0.5 ];                                             % 固定蓝色分量
            
            idx = idx + 1;
        end
    end
    
    % 绘制高分辨率点云图
    figure('Name', '高分辨率平台工作空间', 'Color', 'white', 'Position', [100 100 1400 800]);
    
    % 3D点云(使用scatter3提高渲染性能)
    subplot(2,2,[1,3]);
    scatter3(points(:,1), points(:,2), points(:,3), 6, colors, 'filled');
    title(sprintf('平台中心点工作空间 (分辨率: 0.1°)\n点数: %d', size(points,1)));
    xlabel('X (mm)'); ylabel('Y (mm)'); zlabel('Z (mm)');
    axis equal; grid on; view(40, 30);
    
    % 添加参考坐标系
    hold on;
    plot3([0 50], [0 0], [0 0], 'r-', 'LineWidth', 2); % X轴
    plot3([0 0], [0 50], [0 0], 'g-', 'LineWidth', 2); % Y轴
    plot3([0 0], [0 0], [0 50], 'b-', 'LineWidth', 2); % Z轴
    text(50,0,0,'X','Color','r','FontWeight','bold');
    text(0,50,0,'Y','Color','g','FontWeight','bold');
    text(0,0,50,'Z','Color','b','FontWeight','bold');
    
    % XY平面投影
    subplot(2,2,2);
    scatter(points(:,1), points(:,2), 6, colors, 'filled');
    title('XY平面投影');
    xlabel('X (mm)'); ylabel('Y (mm)');
    axis equal; grid on;
    
    % XZ平面投影
    subplot(2,2,4);
    scatter(points(:,1), points(:,3), 6, colors, 'filled');
    title('XZ平面投影');
    xlabel('X (mm)'); ylabel('Z (mm)');
    axis equal; grid on;
    
    % 显示工作空间统计信息
    fprintf('=== 工作空间高分辨率分析 ===\n');
    fprintf('角度范围: 俯仰 %.1f° 到 %.1f°, 翻滚 %.1f° 到 %.1f°\n',...
        min(pitch_range), max(pitch_range), min(roll_range), max(roll_range));
    fprintf('角度分辨率: 0.1°\n');
    fprintf('总点数: %d\n', size(points,1));
    fprintf('X范围: %.3fmm 到 %.3fmm\n', min(points(:,1)), max(points(:,1)));
    fprintf('Y范围: %.3fmm 到 %.3fmm\n', min(points(:,2)), max(points(:,2)));
    fprintf('Z范围: %.3fmm 到 %.3fmm\n', min(points(:,3)), max(points(:,3)));
    
    % 保存数据到文件(可选)
    save('platform_workspace_points.mat', 'points', 'pitch_range', 'roll_range');
end

function center = calculate_platform_center(pitch, roll, upper)
    % 精确计算平台中心位置(考虑运动学模型)
    
    % 中立位置高度
    neutral_height = upper.H + upper.stroke/2;
    
    % 旋转矩阵
    Rx = [1 0 0; 0 cos(pitch) -sin(pitch); 0 sin(pitch) cos(pitch)];
    Ry = [cos(roll) 0 sin(roll); 0 1 0; -sin(roll) 0 cos(roll)];
    R = Rx * Ry;
    
    % 平台坐标系法向量(旋转后)
    normal_vector = R * [0; 0; 1];
    
    % 高度修正(考虑平台倾斜)
    height_correction = neutral_height * normal_vector(3);
    
    % 平台中心位置 (考虑可能的XY偏移)
    center = [
        0.25 * neutral_height * sin(roll);   % 经验公式-X偏移
        0.25 * neutral_height * sin(pitch);  % 经验公式-Y偏移
        height_correction                    % 精确高度
    ];
end

function [upper, lower] = init_platform_parameters()
    % 平台几何参数(与之前一致)
    upper.L1 = 250;
    upper.L2 = 250*sqrt(2);
    upper.H = 746;
    upper.stroke = 250;
    
    lower.S1 = 250;
    lower.S2 = 250*sqrt(2);
    
    % 安装点计算
    upper.D = sqrt(upper.L1^2 - (upper.L2/2)^2);
    upper.A1 = [-upper.L2/2; upper.D; 0];
    upper.A2 = [upper.L2/2; upper.D; 0];
    
    lower.d = sqrt(lower.S1^2 - (lower.S2/2)^2);
    lower.a1 = [-lower.S2/2; lower.d; 0];
    lower.a2 = [lower.S2/2; lower.d; 0];
end