实时控制软件设计第三周作业

实时控制软件设计第三周作业

一. 博客作业

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.

原文地址:https://www.cnblogs.com/jokerisol/p/6159479.html