1.mfc绘制直方之后只出现了坐标轴怎么读出像数据
2.I5加工中心坐标旋转90度怎么编程?
3.7.AMCL包源码分析 | 粒子滤波器模型与pf文件夹(三)
4.VINS-Mono 代码详细解读4——feature_manager.cpp
5.tf2系列教程(十六):了解ROS 2中的坐标tf2和时间(C++)
6.坐标转换&点云变换&姿态互转| TransForms3d
mfc绘制直方之后只出现了坐标轴怎么读出像数据
我封装了一个类,可以直接用来画图像处理的码坐码直方图,也可用于画各种统计图,标代话不多说~直接上代码供大家使用吧
对了,坐标这篇文章我改编自zhenxiaohui这个作者的码坐码文章,做的标代手机版副图指标源码修改如下:
1.改编了类,可以用于所有的坐标柱形统计图,不仅仅是码坐码直方图
2.修改了里面的一个计算错误,原文的标代:NowPos.y = - .0f * .0f * ImagData[i] / (max * );
应该改为:NowPos.y = - ((float)Ystep*)* .0f * ImagData[i] / (max * );
当然,我这里对他的坐标程序作了很大改进,所以上面这句话会以不同的码坐码形式出现:
[cpp] view plaincopy
<span style="font-size:px;">/*函数说明:画柱形统计图或直方图</span>
[cpp] view plaincopy
<span style="font-size:px;">By:ZXX
参数说明:
count:保存要输出的数据的数组
control:要显示在那个控件的ID
num:数组的维数
比如直方图的调用:DrawHistogram(count,IDC_OLDHISTOGRAM,);
*/
void CImhistDlg::DrawHistogram(int count[],int control,int num)
{
CClientDC dc(this);
//得到控件的大小
CRect rect;
GetDlgItem(control)->GetWindowRect(&rect);//获取控件相对于屏幕的位置
ScreenToClient(rect);//转化为对话框上的相对位置
CPen* pPenBlue = new CPen; //创建画笔对象
pPenBlue->CreatePen(PS_SOLID, 2, RGB(0,0,0)); //黑色画笔
CPen* pPenBlack = new CPen; //创建画笔对象
pPenBlack->CreatePen(PS_SOLID, 1, RGB(0,0,0)); //黑色画笔
//选中黑色画笔,并保存当前画笔
CGdiObject* pOldPen = dc.SelectObject(pPenBlack);
int i = 0;
CString str;
//绘制坐标系
int OriX=rect.left+,标代OriY=rect.bottom-;//坐标系原点OriX,OriY
CPoint OPos(OriX,坐标OriY),NowPos; //OPos是原点坐标
//绘制x坐标轴
dc.MoveTo(OPos);
int flag=0;//flag=0,原比例坐标,flag=1,码坐码扩大比例坐标
int temp= + (num-1)*2 + 5;
//str.Format("%d",标代temp);
//AfxMessageBox(str);
if(rect.right-rect.left>temp)
{
flag=1;
NowPos.x = OriX + temp;
}
else
{
flag=0;
NowPos.x = OriX + (num-1) + 5;
}
NowPos.y = OriY;
dc.LineTo(NowPos);
//绘制箭头
dc.LineTo(NowPos.x-5,NowPos.y-5);
dc.MoveTo(NowPos);
dc.LineTo(NowPos.x-5,NowPos.y+5);
//绘制x轴坐标系数
for (i = 0;i < num;i = i+5)
{
if (i % == 0)
{
if(flag==1)
{
dc.MoveTo(OPos.x + 2 * i,OPos.y);
dc.LineTo(CPoint(OPos.x + 2 * i,OPos.y - 5));
}
else
{
dc.MoveTo(OPos.x + i,OPos.y);
dc.LineTo(CPoint(OPos.x + i,OPos.y - 5));
}
}
if (i % == 0)
{
str.Format("%d",i);
if(flag==1)
{
dc.TextOut(OPos.x + 2 * i,OPos.y + 1,str);
}
else
{
dc.TextOut(OPos.x + i,OPos.y + 1,str);
}
}
}
//绘制最大的
str.Format("%d",(num-1));
if(flag==1)
{
dc.MoveTo(OPos.x + 2 * (num-1),OPos.y);
dc.LineTo(CPoint(OPos.x + 2 * (num-1),OPos.y - 5));
dc.TextOut(OPos.x + 2 * (num-1),OPos.y + 1,str);
}
else
{
dc.MoveTo(OPos.x + (num-1),OPos.y);
dc.LineTo(CPoint(OPos.x + (num-1),OPos.y - 5));
dc.TextOut(OPos.x + (num-1),OPos.y + 1,str);
}
//AfxMessageBox("a");
//绘制y轴坐标系数
dc.MoveTo(OPos);
NowPos.x = OPos.x;
NowPos.y = rect.top;
dc.LineTo(NowPos);
//绘制箭头
dc.LineTo(NowPos.x - 5,NowPos.y + 5);
dc.MoveTo(NowPos);
dc.LineTo(NowPos.x + 5,NowPos.y + 5);
//寻找数据数组最大的数据
int max = 0;
for (i = 0;i < num;i++)
{
if (max < count[i])
{
max = count[i];
}
}
//y轴坐标系数的数据步长
int Tstep = max / ; //个数据
//y轴坐标系数的刻度步长
int Ystep = (OriY-rect.top) / ;//除以的原因是,有是因为上面的数据步长是,现在就是2格显示一个步长,还有一个1是多出来的好看
//显示y坐标的刻度和数据
for (i = 1;i != ;i++)//显示个刻度
{
dc.MoveTo(OPos.x,OPos.y - Ystep * i );
dc.LineTo(CPoint(OPos.x + 5,OPos.y - Ystep * i));
if (i % 2 == 0)
{
str.Format("%d",Tstep * i / 2);
dc.TextOut(rect.left,OPos.y - Ystep * i - ,str);
}
}
//绘制灰度图像的直方图
<span style="color:#ff;">int RealStep = OPos.y-rect.top-(OriY-rect.top-Ystep*);</span>
dc.SelectObject(pPenBlue); //选择蓝色画笔
for (i = 0;i < num;i++)
{
if(flag==1)
{
NowPos.x = OPos.x + (2 * i);
}
else
{
NowPos.x = OPos.x + i;
}
NowPos.y = OPos.y;
dc.MoveTo(NowPos);
<span style="color:#ff;">NowPos.y = OPos.y - (float)(((float)(RealStep*))/(*max))*count[i];
//说明:上面这个大家可能不懂为什么,先注意一下上面的y轴坐标系数的数据步长,y轴坐标系数的刻度步长
//比例这样计算的:(RealStep/):(max/)=X:1,然后要求X,X表示1个数据用多少格表示</span>
dc.LineTo(NowPos);
}
//恢复以前的画笔
dc.SelectObject(pOldPen);
delete pPenBlue;
delete pPenBlack;
}</span>
I5加工中心坐标旋转度怎么编程?
在编程中实现I5加工中心坐标的旋转度,您可以使用数学中的鸿蒙源码linux旋转变换公式来完成。下面是一个简单的示例代码,演示如何通过对X和Y坐标进行旋转计算来实现旋转度:
```cpp
#include <iostream>
#include <cmath>
// 定义旋转函数
void rotateCoordinates(double& x, double& y, double angle)
{
// 将角度转换为弧度
angle = angle * M_PI / .0;
// 计算旋转后的坐标
double newX = x * cos(angle) - y * sin(angle);
double newY = x * sin(angle) + y * cos(angle);
// 更新坐标值
x = newX;
y = newY;
}
int main()
{
double x = 1.0; // 原始X坐标
double y = 2.0; // 原始Y坐标
std::cout << "初始坐标:(" << x << ", " << y << ")" << std::endl;
// 进行度旋转
rotateCoordinates(x, y, .0);
std::cout << "旋转后坐标:(" << x << ", " << y << ")" << std::endl;
return 0;
}
```
上述代码会输出旋转前和旋转后的坐标结果。您可以根据实际的坐标值进行修改。请注意,这只是一个基本的示例代码,如果涉及到更复杂的坐标系统或旋转方式,可能需要进行额外的调整。
7.AMCL包源码分析 | 粒子滤波器模型与pf文件夹(三)
在上一讲中,我们深入探讨了pf.cpp文件,它将Augmented-MCL算法和KLD-sampling算法融合使用。重点在于pf_pdf_gaussian_sample(pdf)函数、pf_init_model_fn_t初始化模型以及pf->random_pose_fn方法进行粒子初始化。粒子的插入和存储采用kd树数据结构,同时kd树也表达直方图的k个bins,通过叶子节点数展现。
本讲聚焦kd树在粒子滤波器模型中的作用(pf_kdtree.cpp)、概率密度函数pdf与特征值分解的关系(eig3.cpp、pf_vector.cpp)以及如何利用pdf生成随机位姿(pf_pdf.cpp),同时解释kd树与直方图的对应关系。
在概率密度函数pdf的创建中,我们首先定义一个高斯PDF结构体pf_pdf_gaussian_t,pnx指标源码包含均值和协方差的描述,接着进行协方差矩阵的分解,通过Housholder算子和QR分解完成特征值分解过程。
通过pdf结构体实现随机位姿的生成,具体在pf_pdf.cpp中pf_pdf_gaussian_sample函数实现,使用无均值带标准差的高斯分布进行生成。
kd树数据结构在pf_kdtree.cpp中定义,包括节点和树的初始化,以及新位姿的插入。kd树的插入依据树的性质,通过计算max_split、中位数和分支点维数来定位新节点位置。查找节点和计算给定位姿权重则通过kd树结构实现,最终将树中叶子节点打标签,以统计特性如均值和协方差计算整个粒子集。
kd树在AMCL中承担直方图功能,以叶子节点数目表示bin个数(k),概率密度函数pdf依赖于输入的均值和协方差生成,用于随机位姿的产生。此外,kd树还用于判断粒子集是组件跳转源码否收敛。最后,kd树表达直方图的过程在pf.cpp中pf_update_resample函数中实现,而pf_resample_limit函数用于设定采样限制。
kd树在粒子滤波器模型中的作用包括存储粒子样本集、查找和插入新位姿,以及统计特性计算。概率密度函数pdf的使用除了初始化粒子位姿外,还有判断粒子收敛的作用。下一讲将探讨amcl_node.cpp的处理内容,包括初始位姿、激光数据和坐标系转换,以及粒子滤波器pf的运用。
VINS-Mono 代码详细解读4——feature_manager.cpp
VINS-Mono 代码详细解读4——feature_manager.cpp文章内容:
在对关键函数 processImage()以及 IMU预积分的 integrationBase类进行解读后,本文将深入解析 estimator.cpp 中的 feature_manager.cpp 文件,重点聚焦于特征点管理。主要涉及的类有 FeatureManager、FeaturePerId、FeaturePerFrame。特征点管理器的核心类为 FeatureManager。
### 目录
#### 涉及的类的成员函数
#### 一、FeatureManager、许昌源码开发FeaturePerId、FeaturePerFrame1、三者关系
FeatureManager 通过 list 容器存储特征点属性,FeaturePerId 指某 feature_id 下的所有 FeaturePerFrame,而 FeaturePerFrame 则是每帧的基本数据,包含特征点坐标、td IMU与cam同步时间差。
#### 二、主要函数
#### 1、endFrame()返回最后一个观测到特定特征点的图像帧ID。
#### 2、getFeatureCount()
返回窗口内被跟踪特征点的数量,标准是特征点需被两帧以上观测到且非最后帧观测。
#### 3、addFeatureCheckParallax()检查视差以维持窗口大小。在VINS中,为了控制优化计算量,只对当前帧之前的部分帧进行优化。通过视差比较决定是否边缘化旧帧。
#### 4、compensatedParallax2()计算特征点在次新帧和次次新帧的视差。实际是计算两帧特征点在归一化平面上的坐标距离。
#### 5、getCorresponding()得到给定两帧之间的对应特征点3D坐标。
#### 6、setDepth()设置特征点的逆深度估计值。代码中求解逆深度时,最后乘上的(++feature_index)用于循环遍历下一个特征点。
#### 7、trangulate()对特征点进行三角化求深度(SVD分解)。
#### 8、三个边缘化函数 removeBackShiftDepth():边缘化最老帧时处理特征点帧号,转移起始帧是老帧的特征点深度。 removeBack():边缘化最老帧时直接向前滑动特征点帧号。 removeFront():边缘化次新帧时移除特征点在次新帧的信息。### 结论
本文详细解析了 feature_manager.cpp 文件中的关键类和函数,强调了特征点管理的重要性,包括如何通过 FeatureManager 管理所有特征点,FeaturePerId 和 FeaturePerFrame 如何关联特定特征点的帧数据,以及核心函数如何在特征点跟踪和管理过程中发挥关键作用。这些解析有助于深入理解 VINS-Mono 的特征点处理机制。
tf2系列教程(十六):了解ROS 2中的tf2和时间(C++)
在ROS 2中,tf2是一个核心组件,用于管理坐标系变换树,跟踪和传播不同坐标系之间的变换信息。在本教程中,我们将探讨如何在lookupTransform()函数中使用超时设置以等待tf2坐标变换树上的坐标变换可用。
理解tf2的时间机制非常重要。每个坐标系变换都保存了一个时间快照,默认最多秒。使用lookupTransform()函数时,我们获取最新的坐标变换,但并不知道该变换的确切时间。本教程将指导你如何获取特定时间的坐标变换。
具体步骤如下:
1. 打开学习tf2的C++软件包中的src/turtle_tf2_listener.cpp源代码文件。在回调函数on_timer()中,我们关注to_frame_rel参数的定义,即在FrameListener类的构造函数中。将to_frame_rel参数设置为turtle1,让第二只小乌龟跟随第一只小乌龟。
2. 移除或注释掉启动文件中设置target_frame参数的代码行,这将让turtle2跟随turtle1,而不是固定坐标系“胡萝卜(carrot1)”。
3. 更改tf2::TimePoint()为this->now(),这指定了查找当前时刻的坐标变换,并移除超时参数。这导致lookupTransform()函数失败,输出消息提示坐标变换不可用。
4. 使用tf2提供的等待工具,通过在lookupTransform()函数中添加Duration参数来解决此问题。在本例中,等待ms,或者使用以下代码。该函数有四个参数:目标坐标系、源坐标系、查找的时刻以及可选的等待超时时长。设置超时时长后,lookupTransform()将阻塞直到坐标变换可用,或在超时时长内无法获取时引发异常。
5. 超时参数的设置至关重要。如果未设置,系统可能会报错坐标系不存在或坐标变换消息在将来。但也不能设置过长,否则会导致系统阻塞。
6. 重新编译并运行软件包,现在可以正常运行了。
通过本教程,你将了解到如何在ROS 2环境中通过设置超时等待来确保tf2坐标变换的可用性,从而在实时系统中实现稳定的坐标系跟踪。
坐标转换&点云变换&姿态互转| TransForms3d
本文分享的开源库TransForms3d,专为坐标转换和点云变换提供解决方案,基于Eigen库构建,无需额外依赖,适用于机器人开发和导航系统构建。 开源地址:gitee.com/ohhuo/transfo... 或 github.com/fishros/tran... 该库提供丰富的函数,覆盖角度、欧拉角、四元数和齐次矩阵等基础转换,以及坐标变换组操作。安装与使用
1. **源码引入**:将trans_forms_group.cpp,trans_forms.cpp,transforms3d.h文件复制至项目中。 2. **编译安装**:根据项目需求进行编译。 3. **使用样例**:- **手眼矩阵估算**:通过TransformsGroup实现。
- **点云坐标转换**:利用TransformsGroup完成。
- **欧拉角转换**:支持多种格式转换。
函数列表
基础部分:角度、弧度、欧拉角、四元数、齐次矩阵等转换。 坐标变换组:添加、打印、查找坐标转换关系。鸣谢与反馈
欢迎贡献代码、提供反馈,共同提升TransForms3d库的性能与功能。