5.27机器人基础-机械臂逆解

news/2024/9/20 1:21:50/ 标签: 机器人

前面简单讲了机械臂的正解问题,即通过原位姿和控制各关节的角度得到终点位姿。而在实际应用的时候,我们通常都是知道起始点和末端终点的位姿,需要考虑如何达到,即运动学机械臂的运动学逆解问题。

求解操作臂运动学方程是一个非线性问题。我们需要考虑解的存在性、多重解性以及求解方法。

 1.解的存在性

解是否存在的问题完全取决于操作臂的工作空间。工作空间是操作臂末端执行器所能达到的范围。如果解存在,则被指定的目标点必须在工作空间内。灵巧工作空间是指机器人的末端执行器能后从各个方向达到的空间区域,可达工作区间是机器人至少从一个方向上有一个方位可以达到的空间。灵巧工作空间是可达工作空间的子集。

2.多重解问题

在求解过程中可能遇到另一个问题就是多重解问题。

解的选择标准。最短形成?权重?干涉?

 3.解法

 代数解法

二幅角反切公式:

atan2_百度百科

 

 几何解

4.MATLAB 实操

这真的是一件难过的事情,在求逆解的时候我曲曲折折烦躁不已,还是没有很好地求出来,还是参考了其他同学的代码。本来想通过控制几何关系来求解,但是应该是一堆bug,已经无力修改了,如果有人帮忙看看问题是什么就更好了

 

clear; clc;%% 参数
L1 = 100;
L2 = 105;
L3 = 98;
L4 = 245;
IN_theta = [0, -45, 30,10, 0];% DH 参数
C_a = [0, 0, L2, L3, 0, 0, 0];
C_d = [0, L1, 0, 0, 0, 0, L4];
C_alpha = [0, -90, 0, 0, -90, 0, 0];
C_theta = [0, IN_theta(1), IN_theta(2), IN_theta(3), IN_theta(4)-90, IN_theta(5), 0];T_target = eye(4); % 初始化结果为单位矩阵for i = 1:6T = [cosd(C_theta(i+1)), -sind(C_theta(i+1)), 0, C_a(i);sind(C_theta(i+1))*cosd(C_alpha(i)), cosd(C_theta(i+1))*cosd(C_alpha(i)), -sind(C_alpha(i)), -sind(C_alpha(i))*C_d(i+1);sind(C_theta(i+1))*sind(C_alpha(i)), cosd(C_theta(i+1))*sind(C_alpha(i)), cosd(C_alpha(i)), cosd(C_alpha(i))*C_d(i+1);0, 0, 0, 1]; % 根据给定的公式计算 T[i]T_target = T_target * T; % 乘以每个 T[i]
end% 提取目标位置
x_target = T_target(1, 4);
y_target = T_target(2, 4);
z_target = T_target(3, 4);% 初始化最优解
best_theta = [];
min_error = inf;%% 逆运动学求解
for apha1 = -90:1:90  % L4与x轴的夹角,角度步长为1度% 方程组定义syms theta2 theta3 theta4% 几何约束条件eq1 = L4 * cosd(apha1) + L3 * cosd(apha1 + theta4) + L2 * cosd(theta2) == x_target;eq2 = L1 + L4 * sin(apha1) + L3 * sind(apha1 + theta4) + L2 * sind(theta2) == z_target;eq3 = theta2 == apha1 + theta3 + theta4;%eq4 = cos(2/pi + theta2 + theta4 + deg2rad(apha1)) == (L2^2 + L4^2 - (L3 * cosd(apha1 + theta4) + L2 * cosd(theta2))^2 + (L3 * sind(apha1 + theta4) + L2 * sind(theta2))^2) / (2 * L2 * L3);% 几何约束的非负性%condition1 = L1 + L2 * cosd(theta2) > 0;%condition2 = L1 + L3 * cosd(apha1 + theta4) + L2 * cosd(theta2) > 0;% 组合所有方程和约束条件equations = [eq1, eq2, eq3];% 求解方程组solutions = solve(equations, [theta2, theta3, theta4], 'Real', true);% 提取并验证解theta2_sol = double(solutions.theta2);theta3_sol = double(solutions.theta3);theta4_sol = double(solutions.theta4);for i = 1:length(theta2_sol)theta2_val = theta2_sol(i);theta3_val = theta3_sol(i);theta4_val = theta4_sol(i);% 计算误差x_calc = L4 * cosd(apha1) + L3 * cosd(apha1 + theta4_val) + L2 * cosd(theta2_val);z_calc = L1 + L4 * sind(apha1) + L3 * sind(apha1 + theta4_val) + L2 * sind(theta2_val);% 计算误差error = sqrt((x_calc - x_target)^2 + (z_calc - z_target)^2);% 更新最优解if error < min_errormin_error = error;best_theta = [0, theta2_val, theta3_val, theta4_val, 0, 0];endend
endC_theta1= [0, 0,theta2_val, theta3_val, theta4_val-90, 0, 0];T_result = eye(4); % 初始化结果为单位矩阵for i = 1:6T = [cosd(C_theta1(i+1)), -sind(C_theta1(i+1)), 0, C_a(i);sind(C_theta1(i+1))*cosd(C_alpha(i)), cosd(C_theta1(i+1))*cosd(C_alpha(i)), -sind(C_alpha(i)), -sind(C_alpha(i))*C_d(i+1);sind(C_theta1(i+1))*sind(C_alpha(i)), cosd(C_theta1(i+1))*sind(C_alpha(i)), cosd(C_alpha(i)), cosd(C_alpha(i))*C_d(i+1);0, 0, 0, 1]; % 根据给定的公式计算 T[i]T_result = T_result * T; % 乘以每个 T[i]
end%% 输出结果
if isempty(best_theta)fprintf('无法找到满足条件的解。\n');
elsefprintf('最优解:\n');fprintf('theta1: %.2f\n', best_theta(1));fprintf('theta2: %.2f\n', best_theta(2));fprintf('theta3: %.2f\n', best_theta(3));fprintf('theta4: %.2f\n', best_theta(4));fprintf('theta5: %.2f\n', best_theta(5));fprintf('theta6: %.2f\n', best_theta(6));fprintf('最小误差: %.2f\n', min_error);fprintf('x_calc: %.2f\n', x_calc);fprintf('z_calc: %.2f\n', z_calc);disp('T_result 矩阵:');disp(T_result);disp('T_target 矩阵:');disp(T_target);
end

成功的代码,验证了一下效果很好

clc; clear;
% 机械臂关节长度
l1 = 100;
l2 = 105;
l3 = 98;
l4 = 245;
IN_theta = [0, -45, 20, 90, 0];% DH 参数
C_a = [0, 0, l2, l3, 0, 0, 0];
C_d = [0, l1, 0, 0, 0, 0, l4];
C_alpha = [0, -90, 0, 0, -90, 0, 0];
C_theta = [0, IN_theta(1), IN_theta(2), IN_theta(3), IN_theta(4)-90, IN_theta(5), 0];
T_target = eye(4); % 初始化结果为单位矩阵for i = 1:6T = [cosd(C_theta(i+1)) -sind(C_theta(i+1)) 0 C_a(i-1+1);sind(C_theta(i+1))*cosd(C_alpha(i-1+1)) cosd(C_alpha(i-1+1))*cosd(C_theta(i+1)) -sind(C_alpha(i-1+1)) -sind(C_alpha(i-1+1))*C_d(i+1);sind(C_theta(i+1))*sind(C_alpha(i-1+1)) cosd(C_theta(i+1))*sind(C_alpha(i-1+1)) cosd(C_alpha(i-1+1)) cosd(C_alpha(i-1+1))*C_d(i+1);0 0 0 1]; % 根据给定的公式计算T[i]T_target = T_target * T; % 乘以每个T[i]
endC_theta1 = calculate_joint_angles(T_target(1, 4), T_target(2, 4), T_target(3, 4));
T_result = eye(4); % 重新初始化结果为单位矩阵
for i = 1:6T = [cosd(C_theta1(i+1)) -sind(C_theta1(i+1)) 0 C_a(i-1+1);sind(C_theta1(i+1))*cosd(C_alpha(i-1+1)) cosd(C_alpha(i-1+1))*cosd(C_theta1(i+1)) -sind(C_alpha(i-1+1)) -sind(C_alpha(i-1+1))*C_d(i+1);sind(C_theta1(i+1))*sind(C_alpha(i-1+1)) cosd(C_theta1(i+1))*sind(C_alpha(i-1+1)) cosd(C_alpha(i-1+1)) cosd(C_alpha(i-1+1))*C_d(i+1);0 0 0 1]; % 根据给定的公式计算T[i]T_result = T_result * T; % 乘以每个T[i]
enddisp('T_target 矩阵:');
disp(T_target);
disp('T_result 矩阵:');
disp(T_result);function C_theta1 = calculate_joint_angles(x, y, z)% 机械臂关节长度l1 = 100;l2 = 105;l3 = 98;l4 = 245;% 计算 theta1theta1 = atan2(y, x);% 在 x-y 平面投影中的半径r = sqrt(x^2 + y^2);% 初始化找到解的标志found_solution = false;% 循环尝试不同的 a 值for a_deg = -90:90a = deg2rad(a_deg);% 计算 xc 和 zcxc = r - cos(a) * l4;zc = z - sin(a) * l4;% 计算 lac_sqlac_sq = xc^2 + (zc - l1)^2;% 检查是否在范围内if lac_sq > (l2 + l3)^2 || lac_sq < (l2 - l3)^2continue;end% 计算 jbac 和 jcac_primejbac = acos((l2^2 + lac_sq - l3^2) / (2 * l2 * sqrt(lac_sq)));jcac_prime = atan2(zc - l1, xc);% 计算 theta2theta2 = -jbac - jcac_prime;% 计算 theta3theta3 = pi - acos((l2^2 + l3^2 - lac_sq) / (2 * l2 * l3));% 检查是否有虚数部分if isreal(theta2) && isreal(theta3)% 计算 theta4theta4 = - theta2 - theta3 - a;% 标记已找到解found_solution = true;break; % 结束循环endendif found_solution% 返回关节角度数组C_theta1 = [0, rad2deg(theta1), rad2deg(theta2), rad2deg(theta3), rad2deg(theta4)-90, 0, 0];disp(['Theta1: ', num2str(rad2deg(theta1)), ' degrees']);disp(['Theta2: ', num2str(rad2deg(theta2)), ' degrees']);disp(['Theta3: ', num2str(rad2deg(theta3)), ' degrees']);disp(['Theta4: ', num2str(rad2deg(theta4)), ' degrees']);elsedisp('找不到合适的逆解');C_theta1 = NaN(1, 7); % 返回 NaN 表示未找到解end
end

加入插值之后用于机械臂画直线的代码:

clc;clear;
%%根据起始点和末端点插值
% 定义起始点和终止点
startPoint = [280, 0, 371];
endPoint = [252, 0, 404];% 定义插值点的数量
numPoints = 11;% 使用 linspace 生成插值点
xValues = linspace(startPoint(1), endPoint(1), numPoints);
yValues = linspace(startPoint(2), endPoint(2), numPoints);
zValues = linspace(startPoint(3), endPoint(3), numPoints);% 存储插值点的坐标
interpolatedPoints = [xValues; yValues; zValues]';params = [xValues; yValues; zValues];% 调用函数计算关节角度
results = calculate_joint_angles(interpolatedPoints);function results = calculate_joint_angles(params)% 初始化角度theta1 = 0;theta2 = 0;theta3 = 0;theta4 = 0;% 机械臂关节长度l1 = 153;l2 = 105;l3 = 98;l4 = 173;% 初始化结果数组num_points = size(params, 1);results = zeros(num_points, 4);for i = 1:num_pointsx = params(i, 1);y = params(i, 2);z = params(i, 3);% 计算 theta1theta1 = atan2(y, x);% 在 x-y 平面投影中的半径r = sqrt(x^2 + y^2);% 初始化找到解的标志found_solution = false;% 循环尝试不同的 a 值for a_deg = -90:90a = deg2rad(a_deg);% 计算 xc 和 zcxc = r - cos(a) * l4;zc = z - sin(a) * l4;% 计算 lac_sqlac_sq = xc^2 + (zc - l1)^2;% 检查是否在范围内if lac_sq > (l2 + l3)^2 || lac_sq < (l2 - l3)^2continue;end% 计算 jbac 和 jcac_primejbac = acos((l2^2 + lac_sq - l3^2) / (2 * l2 * sqrt(lac_sq)));jcac_prime = atan2(zc - l1, xc);% 计算 theta2theta2 = -jbac - jcac_prime;% 计算 theta3theta3 = pi - acos((l2^2 + l3^2 - lac_sq) / (2 * l2 * l3));% 检查是否有虚数部分if isreal(theta2) && isreal(theta3)% 计算 theta4theta4 = -a - theta2 - theta3;% 保存计算结果results(i, :) = [rad2deg(theta1), rad2deg(theta2)+180, rad2deg(theta3)+135, rad2deg(theta4)+135];%180,135是使机械臂处于正的初始位置(正水平放置)的舵机的角度% 标记已找到解found_solution = true;break; % 结束循环endend% 如果没有找到解,提示错误if ~found_solutionerror(['No valid solution found for point ', num2str(i)]);endend% 输出结果disp('Calculated Joint Angles (in degrees):');disp(results);
end


http://www.ppmy.cn/news/1467497.html

相关文章

LLaSM:Large language and speech model

1.Introduction 级联方法使用ASR将语音输入转化为文本输入,语音到文本会导致信息损失,本文提出LLaSM,一个具有跨模态对话能力的大型语音与语言模型,能够理解和遵循语音与语言指令,借鉴LLaVA,利用预训练的语音模态编码器和大语言模型,使用Whisper作为语音编码器,将语音…

DP动态规划(上)

文章目录 动态规划基本概念斐波那契数列问题C 实现Python 实现Java 实现 迷你结C、Python和Java在实现动态规划时有哪些性能差异&#xff1f;迷你结哪种语言在动态规划中更适合大规模数据处理?迷你结C有哪些知名的库适用于动态规划和大数据处理?动态规划辅助库大数据处理库 迷…

NLP(21)--任务型对话机器人

前言 仅记录学习过程&#xff0c;有问题欢迎讨论 问答系统 闲聊、任务型&#xff08;帮我设闹钟&#xff09;、回答型&#xff08;Q&A&#xff09; 任务型对话机器人&#xff1a;&#xff08;帮我定火车票/多轮次&#xff09; 领域识别&#xff08;分类、匹配&#xff…

【Python字符串攻略】:玩转文字,编织程序的叙事艺术

文章目录 &#x1f680;一.字符串基础&#x1f308;二.查看数据类型⭐三.转化❤️四.字符串索引&#x1f6b2;五.字符串切片&#x1f3ac;六.字符串切片-步长☔七.反向切片注意事项&#x1f6b2;八.字符串&#x1f4a5;查&#x1f4a5;改&#x1f4a5;删 ❤️九.字符串拼接&…

DS:数与二叉树的相关概念

欢迎来到Harper.Lee的学习世界&#xff01;博主主页传送门&#xff1a;Harper.Lee的博客主页想要一起进步的uu可以来后台找我哦&#xff01; 一、树的概念及其结构 1.1 树的概念亲缘关系 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限节点…

idea 常用插件推荐

文章目录 1、Lombok2、Convert YAML and Properties File3、Grep Console4、MyBatisX5、Free MyBatis Tool6、MyBatis Log EasyPlus &#xff08;SQL拼接&#xff09;7、MyBatisPlus8、Eclipse theme9、Eclipse Plus Theme10、Rainbow Brackets Lite - Free and OpenSource&…

Windows API 开发桌面应用程序,在窗口按下鼠标左键不放可以拖图,并且拖图期间鼠标图标变成手掌

在Windows API中&#xff0c;要实现鼠标左键按下并拖动以移动窗口中的某个图形&#xff0c;并且同时改变鼠标图标为“手掌”形状&#xff08;这通常指的是“拖动”或“移动”的图标&#xff09;&#xff0c;你需要执行几个步骤。 以下是一个基本的步骤指南&#xff0c;用于在W…

多扇区轮询存储提高FLASH使用寿命

/********************************************************************************* brief flash 多扇区轮询存储(用于提高flash使用寿命)******************************************************************************1.数组首位UserData[第一位] 和 UserData[最后一…

常用maven - jar 下载与 安装

1. guava 如果你想直接将 JAR 文件安装到本地 Maven 仓库&#xff0c;而不使用 POM 文件&#xff0c;可以使用 mvn install:install-file 命令并手动提供必要的元数据。以下是步骤&#xff1a; 下载 Guava JAR 文件&#xff1a; 从 Maven Central 仓库下载 Guava JAR 文件&am…

Django 默认 CSRF 保护机制

Django 的默认 CSRF 保护机制旨在防止跨站请求伪造攻击(CSRF)。CSRF 攻击是一种恶意攻击,其中攻击者通过伪造用户的请求来执行未授权的操作。Django 通过以下方式实现 CSRF 保护: 1. CSRF 中间件 Django 包含一个 CSRF 中间件 (CsrfViewMiddleware),它会自动添加到项目的…

U9C的数据查询视图Sql

U9C的数据查询视图Sql if object_id(TEMPDB..#priceTable) is not null begin drop table #priceTable endcreate table #priceTable (polineCreatedOn date,price varchar(max),itemid varchar(max),purchaseOrderdocno varchar(max),)insert into #priceTable select max(…

代理IP类型有哪些?定义与区别

您应该对代理有了一定的了解。但是&#xff0c;代理服务器也有不同的类型。就其来源而言&#xff0c;最常见的代理服务器类型是住宅代理和数据中心代理&#xff1a; 1、住宅代理 住宅代理是 ISP 向房主提供的 IP 地址。它是与物理位置关联的真实 IP 地址&#xff0c;因此允许…

make_ext4fs:not found

报错信息&#xff1a; 解决&#xff1a; sudo apt-get install android-tools-fsutils sudo apt-get install android-sdk-libsparse-utils sudo apt-get install android-sdk-ext4-utils

二叉树练习题(2024/6/5)

1翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;[2,3,1]…

Docker 入门版

目录 1. 关于Docker 2. Dockr run命令中常见参数解读 3. Docker常见命令 4. Docker 数据卷 5. Docker本地目录挂载 6. 自定义镜像 Dockerfile 语法 自定义镜像模板 Demo 7. Docker网络 1. 关于Docker 在docker里面下载东西&#xff0c;就是相当于绿色面安装板&#x…

【JavaEE】留言板与图书管理系统

目录 留言板1. 准备工作2. 约定前后端交互接口lombok3. 服务器代码4. 调整前端页面代码 图书管理系统1. 准备工作2. 约定前后端交互接口3. 服务器代码4. 调整前端页面代码 留言板 需求: 界⾯如下图所⽰ 输⼊留⾔信息, 点击提交. 后端把数据存储起来.⻚⾯展⽰输⼊的表⽩墙的信…

2024国内热门大语言模型在科研方面的应用

本博客总结了几款热门的国产大语言模型&#xff0c;帮助大家利用这些大语言模型更好的进行科研。 模型介绍 1.文心一言 链接:https://yiyan.baidu.com/ 开发方&#xff1a;百度 特点&#xff1a;专注于中文语言理解与生成&#xff0c;适合中文文本的语义理解任务。 百度推出…

数据仓库与数据挖掘实验练习8

pivot_table()透视表 sales.pivot_table(values Revenue,index Date, columns Name,aggfunc sum,fill_value 0,margins True,margins_name 总计 ) 使用 Pandas 的 pivot_table 函数将一个名为 sales 的 DataFrame 转化为透视表。 1. sales.pivot_table(...) sales: …

【UnityShader入门精要学习笔记】第十六章 Unity中的渲染优化技术 (上)

本系列为作者学习UnityShader入门精要而作的笔记&#xff0c;内容将包括&#xff1a; 书本中句子照抄 个人批注项目源码一堆新手会犯的错误潜在的太监断更&#xff0c;有始无终 我的GitHub仓库 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 文章目录 移动平台上…

STM32作业实现(七)OLED显示数据

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…