实时控制软件设计第三周作业
一. 博客作业
1. 阅读笔记:Xenomai性能特点
Xenomai是一种采用双内核机制的Linux内核的强实时扩展。优先级高于Linux 内核,它负责处理系统的实时任务。由于Linux内核本身的实现方式和复杂度,使得Linux本身不能使用于强实时应用。在双内核技术下,存在一个支持强实时的微内核,它与Linux内核共同运行于硬件平台上,实时内核的优先级高于Linux内核,它负责处理系统的实时任务,而Linux则负责处理非实时任务,只有当实时内核不再有实时任务需要处理的时候,Linux内核才能得到运行的机会。Xenomai基于Adeos(Adaptive Domain Environment for Operating System)实现双内核机制,Adeos 是扩展Linux的基础环境。
对于一个计算机系统来说,系统的运行是由内部和外部的中断和异常所触发的,例如系统时钟中断对操作系统来说就是最重要的。所以,Adeos的主要工作就是管理硬件的中断,根据域的优先级依次执行相应域的中断服务程序,从而驱动域内的系统运行;同时,Adeos还提供域之间的通信机制实现域的调度等。为了实现对中断的管理和域之间的优先级控制,Adeos使用了中断管道(Interrupt Pipe)的概念。Adeos通过中断管道在不同的域之间传播中断,而且提供了相应的机制可以让域改变自己在中断管道中的优先级。
Xenomai在Adeos 系统中的域优先级高于Linux 域,每当中断到来之后,Adeos先调度Xenomai 对该中断进行处理、执行中断相应的实时任务,只有当Xenomai 没有实时任务和中断需要处理的时候,Adeos 才会调度Linux 运行,这就保证了Xenomai的中断响应速度和实时任务不受Linux 的影响,从而提供了实时系统的可确定性。
由此可见,Xenomai的最底层是Adeos,它与系统硬件直接交互,接管系统中所有的对中断的操作,是整个实时操作系统能够运行的关键。在Xenomai官网主页上,我们可以找到其如何实现实时性的原理,读者可自行访问参考链接。图1和图2分别是Xnemai系统结构图和Adeos处理中断流程示意图。
图1 Xnemai系统结构图
图2 Adeos处理中断流程
通过阅读资料,Xenoami的性能特点个人总结如下:
- 实时性好,包括硬件层和用户层,用户层实时程序的周期可轻易设定到us级
- 多API构架
- 核心技术表现在使用一个实时微内核(real-time nucleus)来构建实时API
- 兼容多种常见的商业实时操作系统
- 支持完全的、性能优异的用户态下的实时性
- 对系统调用号进行分段利用,巧妙地在用户层下为上层的各个不同的RTOS提供各种需要的服务
- 在多硬件平台上有很好的移植性
参考资料:
[1] Xenomai百度百科:http://baike.baidu.com/link?url=MB2qz0VXsvBjTzUs9pvmc0EjXZLL-
[2] Xenomai主页:http://xenomai.org/
[3] 晏来成,郑立新.基于Linux和Xenomai的实时测控系统[A]. 1671-4598 (2009) 04-0657-03
[4] 道客巴巴文章——基于Xenomai的实时Linux分析与研究:http://www.doc88.com/p-9899788850590.html
[5] 豆丁网文章——强实时应用环境下VxWorks, Linux, RTAI和Xenomai系统的性能比较:http://www.docin.com/p-1749346122.html
2. 团队项目初步分析
完成一个团队项目,主要功能是实现一个两轴机械手的运动控制仿真,主要功能包括:
- 用户接口任务:负责接收来自用户的请求,并发送运动指令给轨迹插补任务。
- 轨迹插补任务:接收运动指令,实时计算各轴的位置和速度设定值。
- 物理引擎接口:基于ODE开源物理引擎,创建一个两轴机械手及环境的物理模型,用轨迹插补任务输出的各轴位置和速度设定值控制模型的运动,并把实时状态反馈给轨迹插补任务。
- 图形化用户接口:可基于qt把上述功能集成到一个GUI界面。
关于团队协作开发,顾名思义,这是一项teamwork。跟其他团队项目一样,需要一个明确的项目题目或目的,需要项目负责人和项目参与者,需要有明确的项目分工和项目进度,以及监督管理等等。这是一个 既能提高与他人合作能力,又能提高自己锻炼自己的学习和解决问题的过程。就我们这次实时控制软件设计课程的项目而言,需要编程、算法、建模、项目管理等许多工作。个人对轨迹插补任务和ODE建模都比较感兴趣,即算法和建模,个人在编程方面平时接触和练习的较少,故此为弱项。因此,希望能在算法和建模,当然在后续做项目过程的中,一定会产生的一些新的自己感兴趣的工作。
二. 实时编程作业
1. 下载代码库编译任务
运行截图如下:
2. 编程实现定位运动轨迹生成器
由于基于状态机的编程思想还不太理解,所以任务开始简单做一个关于梯形加减速的速度和位移显示的C++程序,希望后续不断改进。代码如下:
include<iostream>
using namespace std;
class new_cmd
{
private:
double S ; //初始化位移为零
double Acceleration; // 加速度
double Deceleration; //减速度
double Speed; //速度
int T1; //加减速的时间
int T2; //匀速行驶时间
int T3; //
public:
void Assignment(double, double, double, double, int, int, int);
double GetS();
double GetAcceleration();
double GetDeceleration();
double GetSpeed();
int GetT1();
int GetT2();
int GetT3();
};
void new_cmd::Assignment(double s, double acceleration, double deceleration,
double speed, int t1, int t2, int t3)
{
S = s; Acceleration = acceleration; Deceleration = deceleration;
Speed = speed; T1 = t1; T2 = t2; T3 = t3;
}
double new_cmd::GetS()
{
return(S);
}
double new_cmd::GetAcceleration()
{
return(Acceleration);
}
double new_cmd::GetDeceleration()
{
return(Deceleration);
}
double new_cmd::GetSpeed()
{
return(Speed);
}
int new_cmd::GetT1()
{
return(T1);
}
int new_cmd::GetT2()
{
return(T2);
}
int new_cmd::GetT3()
{
return(T3);
}
void main()
{
double Input_S = 0; //初始化位移为零
double Input_Acceleration; // 加速度
double Input_Deceleration; //减速度
double Input_Speed = 0; //速度
int Input_T1; //加减速的时间
int Input_T2; //匀速行驶时间
int Input_T3;
cout << "正在初始化"<< '
';
while (1)
{
cout << "正在接收new_cmd" << '
';
cin >> Input_Acceleration >> Input_Deceleration >> Input_T1 >> Input_T2 >> Input_T3;
new_cmd new_order;
new_order.Assignment(Input_S, Input_Acceleration, Input_Deceleration, Input_Speed, Input_T1, Input_T2, Input_T3);
int t1 = 0 ;
double Speed_new;
double S_new;
while(t1 <= new_order.GetT1())
{
Speed_new = new_order.GetSpeed() + t1*new_order.GetAcceleration();
S_new = new_order.GetS() + 0.5*new_order.GetAcceleration()*t1*t1;
cout << "t=" << t1 << "时," << "速度为:" << Speed_new << " 位移为:" << S_new << '
';
t1++;
}
/*
t1 = new_order.GetT1();
Speed_new = new_order.GetSpeed() + t1*new_order.GetAcceleration();
S_new = new_order.GetS() + 0.5*new_order.GetAcceleration()*t1*t1;
cout << "t=" << t1 << "时," << "速度为:" << Speed_new << " 位移为:" << S_new << '
';
*/
while (t1 <= new_order.GetT1() + new_order.GetT2())
{
Speed_new = Speed_new;
S_new = S_new;
cout << "t=" << t1 << "时," << "速度为:" << Speed_new << " 位移为:" << S_new << '
';
t1++;
}
double sp = Speed_new;
double ss = S_new;
while ( t1 <= ( new_order.GetT1() + new_order.GetT2() + new_order.GetT3() ) )
{
Speed_new = sp - (t1 - new_order.GetT1() - new_order.GetT2())*new_order.GetDeceleration();
S_new = ss - 0.5*new_order.GetDeceleration()*(t1 - new_order.GetT1()
- new_order.GetT2())*(t1 - new_order.GetT1() - new_order.GetT2());
cout << "t=" << t1 << "时," << "速度为:" << Speed_new << " 位移为:" << S_new << '
';
t1++;
}
};
}
其功能还十分简单,仅仅是根据每次输入的加速度、减速度、相关运动时间,每个一个周期显示实时速度和位移。由于没有计时器,所有这里的“时间”并不是按照现实时间的快慢而推移的。后续将不断改进程序,已将程序上传至GitHub。运行功能截图如下:
Written with StackEdit.