实验数据旋转角度处理过程中的常见问题

news2024/9/27 12:08:40

问题

做实验过程中使用 EM tracker 测量自己机器人末端旋转时的角度。
尾部 设置EMTracker 1,作为固定基准,其轴线与机器人中心轴线近似重合,EM Tracker 2 固定在机器人活动关节上,两者轴线夹角近似为机器人旋转角度。论文尚未发表,图片仅展示部分。
在这里插入图片描述

实验结果

在这里插入图片描述
实验数据中存在的问题

  1. 上述方式存在安装误差,图中可以看出,初始误差有接近10 度
  2. 角度只有正值,并且不能展示左右两侧,峰值小一点的应该是弯去另一侧,其值应该为负数。
  3. 在 6度 多的时候存在换向,换向附近,角度斜率明显降低

解决办法

向量夹角,最低点处翻转


t_0 = 32;							% 第一个周期的开始时间
Period=90.5-31.2;			% 周期
t_1 = t_0; 
t_2 = t_0;
while true
    t_1 = t_2;
    t_2 = t_1 + Period;
    t_tmp= t_1 + Period*0.5;
    if t_2 > t_max_min			% 还在实验时间内
        break;
    end
idx_1 = round(t_1/0.05)+1;			% 计算时间对应的 index 索引
idx_2 = round(t_2/0.05)+1;
idx_tmp= round(t_tmp/0.05)+1; 	% 分割周期中心,分别求两个拐点
[M_1,I_1] = min(Ang_EM2inEM20(idx_1:idx_tmp));		% 前半个周期的最小值,是第一个拐点
[M_2,I_2] = min(Ang_EM2inEM20(idx_tmp:idx_2));

idx_start = idx_1 + I_1 - 1;			% 根据最小值的 index 还原到整个数据序列的索引
idx_stop  = idx_tmp + I_2 - 1;

% Ang_EM2inEM20(idx_start:idx_stop) = M_1 + M_2 -Ang_EM2inEM20(idx_start:idx_stop);
% Ang_EM2inEM1(idx_start:idx_stop) = M_1 + M_2 -Ang_EM2inEM1(idx_start:idx_stop);


end

不使用两个向量夹角表示旋转角

安装过程中,两个 EM tracker 不可能在同一条轴线 或者同一个平面运动,因此,前端 EM tracker 2 随机器人运动过程中,其轴线与末端固定的 EM Tracker 1 一直是空间角。空间角基本不存在夹角为 0 的时候。这是为什么实验数据中最小值在 6 度就拐弯了。另外空间角对时间的变化率在接近其最小值的时候会变化,这是为什么接近最小值时,明显有弧度拐弯的原因。

改进方法: 采用 EM tracker 2 与其初始未运动时向量夹角表示机器人旋转角度。

Ang_EM2inEM20 = VectorAngle(z2_in_YOZ, mean(z2_in_YOZ(:, 5:100), 2));

function vect_ang = VectorAngle(Vect_1, Vect_2)
% This function is to calculate the angle between two axes
% Input
%	Vect_1      ----- the variable vector, column vector
%	Vect_2      ----- reference vector, column vectors, or a unchangable
%               ----- column vector
% Output 
% 	vect_ang    ----- Angle series in degree

    
for i = 1:size(Vect_1,2)
    if size(Vect_2,2)==1
        V_2 = Vect_2;
    else
        V_2 = Vect_2(:,i);
    end
    V_1 = Vect_1(:,i);
    vect_ang(i) = rad2deg( atan2(norm(cross(V_2', V_1')), dot(V_2, V_1)) );
end

% theta = subspace(Vect_1,Vect_2);
disp('')

end

解决空间角变化速率的问题

上一节分析中知道 空间角变化了 会导致拐角处圆角。由于机器人运动轴线是 x 轴,机器人实际在 YOZ 平面运动,因此讲 EM Tracker 2 的轴向向量投影到 EM tracker base frame 的 YOZ 平面在计算夹角。

[z2_series, ~] = Quat2zaxis(EM_mat_2);  		% 原始 四元数转 z 轴
z2_in_YOZ = VectorProjection(z2_series);
Ang_EM2inEM20 = VectorAngle(z2_in_YOZ, mean(z2_in_YOZ(:, 5:100), 2));

function vector2plane = VectorProjection(Vect_1, Vect_2)
% This function is to calculate the projection of Vect_1 in a plane (with 
% norm vector Vect_2)
% Input
%	Vect_1      ----- the variable vector, column vector
%	Vect_2      ----- Normal vector of the projection plane, default YOZ
%                     plane of EM tracker, [1 0 0]
% Output 
% 	vector_plane----- the projection vector of vect_1 in plane of normal
%                     vector vect_2
% reference     ----- https://www.maplesoft.com/support/help/maple/view.aspx?path=MathApps%2FProjectionOfVectorOntoPlane

if nargin == 1
    Vect_2 = [1; 0; 0;];
end

for i = 1:size(Vect_1,2)
    vector2plane(:, i) = Vect_1(:,i)- dot(Vect_1(:,i), Vect_2)/norm(Vect_2) * Vect_2;
end


end

结果

在这里插入图片描述

附录


function [z_axis_series, time_series] = Quat2zaxis(EM_mat)
% This function is to extract the z-axis of EM tracker in EM base frame
% Input
%	EM_mat      ----- .mat file of the EM tracker
% Output 
% 	z_in_base   ----- each row is the z-axis coordinate in EM base frame
%   time_series ----- time series, 


load(EM_mat);
disp('');
varlist = who;
TF = contains(varlist,'EM_tracker');
EM_Name = varlist(TF);
if contains(EM_Name, '_1')
    EM_Data = PosAndOri_EM_tracker_1;
elseif contains(EM_Name, '_2')
    EM_Data = PosAndOri_EM_tracker_2;
elseif contains(EM_Name, '_3')
    EM_Data = PosAndOri_EM_tracker_3;
elseif contains(EM_Name, '_4')
    EM_Data = PosAndOri_EM_tracker_4;
else
    disp('----------------------------------');
    disp('Variable Name Error!')
    disp('----------------------------------');
end

time_series = EM_Data(1,:);
quat_data = EM_Data(5:8,:);
z_axis_series = [];

for i = 1:size(quat_data,2)
    rotm = quat2rotm(transpose( quat_data(:,i)) );
    z_axis_series(1:3, i) = rotm(:,3);
end

% z_in_base(1,:) = time_series;
% z_in_base(2:4,:) = z_axis_series;


end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1130665.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jenkins 安装全攻略:从入门到精通

目录 一:安装文件夹准备 1.打开,/home/admin目录 2.新建三个文件夹 二:安装tomcat 1.打开tomcat目录进行tomcat安装 2.解压tomcat文件 3.开放端口号 4.启动tomcat 5.浏览器访问tomcat 三:安装Maven 1.打开maven目录进行…

VB.NET 三层登录系统实战:从设计到部署全流程详解

目录 前言: 什么是三层 为什么要用到三层: 饭店→软件 理解: 过程: 1.三层包图: 2.数据库 3.三层项目 4.用户界面 5.添加引用 代码实现: Entity层 BLL层 DAL层 UI层 总结: 前言: 什么是三层 三层就是把各个功能模块划分为表示层&#…

python访问Wikipedia

import wikipedia # doc: https://pypi.org/project/wikipedia/def searchWikiPedia(keyword, language) -> str:wikipedia.set_lang(language)result wikipedia.page(keyword)return result.contentif __name__"__main__":# 设置语言https://meta.wikimedia.org…

Leetcode刷题详解——x的平方根

1. 题目链接:69. x 的平方根 2. 题目描述: 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 **注意:**不允许使用任何内置指数函数和…

网站搬家的多种方法

网站搬家,把网站从一个服务器迁移到另一个服务器,涉及到网站文件和数据库的备份、上传、导入等操作,最重要的是备份网站,避免迁移出现问题无法恢复网站。 根据不同的情景和需求,网站搬家的方法有多种,下面…

什么是Docker CLI

Docker CLI(命令行界面)是一个工具,允许用户通过命令行或终端与Docker进行交互。Docker是一个开源平台,用于开发、运送和运行应用程序。Docker使用容器化技术来打包应用程序及其依赖项,以确保在不同环境中的一致性和隔…

Axure 9 使用 font awesome 字体发布原型

我使用的版本为Font awesome 6.1.1,安装后在axure中新增3个字体 如果直接发布,在没有安装Font awesome的电脑上无法正常显示字体图标,需要在发布前进行设置。 设置方法: 点击共享 点开设置 在字体设置页,填入图中所示…

golang小游戏:飞翔的小鸟

游戏开发总体思路 首先要选取一个合适的图形化界面进行开发。该项目选取的是 ebiten 一个用于创建2D游戏和图形应用程序的游戏引擎,提供了一些简单的GUI功能。 其次明确游戏设计思路。飞翔的小鸟共分为三个场景。 第一个场景就是游戏开始前的准备阶段&#xff0c…

微信小程序:点击按钮出现右侧弹窗

效果 代码 wxml <!-- 弹窗信息 --> <view class"popup-container" wx:if"{{showPopup}}"><view class"popup-content"><!-- 弹窗内容 --><text>这是一个右侧弹窗</text></view> </view> <…

【Spring】使用aop切面编程时要给那些类加注解

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理 Spring 中使用aop切面编程时要给那些类加注解 &#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一…

python 之运算符

文章目录 总的介绍代码例子 总的介绍 Python中有许多不同类型的运算符&#xff0c;它们用于执行各种操作&#xff0c;包括算术运算、比较、逻辑运算等。以下是Python中常用的运算符&#xff1a; 算术运算符&#xff1a; &#xff1a;加法&#xff0c;用于将两个数相加。-&…

PhpStorm快速注释与取消注释

ctrl / 单行注释 ctrl shift / 多行注释 重复以上操作&#xff0c;取消注释。

Slax Linux 获得增强的会话管理和启动参数选项

Slax Linux 的创建者和维护者托马斯-马特吉切克&#xff08;Tomas Matejicek&#xff09;在自己生日这天&#xff08;生日快乐&#xff01;&#xff09;发布了其小巧便携的 GNU/Linux 发行版的新版本&#xff0c;带来了各种增强功能和错误修复。 新发布的 Slax Linux 版本&…

优雅的使用String字符串处理各种类型转换

文章目录 &#x1f31f; 优雅的使用String字符串处理各种类型转换&#x1f34a; 基本类型转字符串&#x1f34a; 字符串转基本类型&#x1f34a; 字符串与字符数组的转换&#x1f34a; 字符串与字节数组的转换&#x1f34a; 其他类型转字符串&#x1f34a; 总结 &#x1f4d5;我…

AIGC实战——深度学习 (Deep Learning, DL)

AIGC实战——深度学习 0. 前言1. 深度学习基本概念1.1 基本定义1.2 非结构化数据 2. 深度神经网络2.1 神经网络2.2 学习高级特征 3. TensorFlow 和 Keras4. 多层感知器 (MLP)4.1 准备数据4.2 构建模型4.3 检查模型4.4 编译模型4.5 训练模型4.6 评估模型 小结系列链接 0. 前言 …

UE4 中可全局获取的变量(例如游戏实例、玩家控制器等) 详解

目录 0 引言1 全局对象&#xff08;全局变量&#xff09;1.1 游戏实例 GameInstance1.1.1 介绍1.1.2 使用 GameInstance 1.2 玩家控制器 PlayerController1.3 游戏世界类 UWorld &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;UE虚幻引擎专栏&…

Vue3.3指北(二)

Vue3.3指北 Vue31、组件基础1.1、全局组件1.2、局部组件1.3、组件的命名1.4、组件的数据存放1.5、组件标签化 2、父组件向子组件传递数据2.1、props2.2、动态props2.3、props传数组2.4、props传对象2.4.1、默认值和必传值 3、子组件向父组件传递数据4、父子组件互相访问4.1、父…

[SQL开发笔记]AND OR运算符复杂表达式开发实例

结合 AND & OR实例&#xff1a;通过圆括号使用and或or来组成复杂的表达式 目标数据库及表&#xff1a;使用 DRobot数据库&#xff0c;"T_Drobot" 表 假设我们需要查询"T_Drobot" 表&#xff0c;并从"T_Drobot"表中查询选取creator为 "…

腾讯云 AI 绘画:文生图、图生图、图审图 快速入门

腾讯云 AI 绘画是腾讯云推出的一款基于人工智能的图像生成和编辑产品&#xff0c;能够根据输入的图片或描述文本&#xff0c;智能生成与输入内容相关的图片&#xff0c;支持多样化的图片风格选择。 在本文中&#xff0c;我们将介绍如何使用腾讯云 AI 绘画的三项主要功能&#…

24装饰器

目录 1、一些案例导入&#xff1a;这个要求必须是&#xff0c;在发东西之前有那个登录验证 2、开始理装饰器的一些原理了 3、最后就是把代码再简洁一些了 1、一些案例导入&#xff1a;这个要求必须是&#xff0c;在发东西之前有那个登录验证 def fss():print(发说说) def ft…