《实时控制软件设计》第三两全作业

同、不同实时操作系统的特性及于

1、Vxworks

Vxworks在实时操作系统行业外处于领先地位,拥有不少的用户。它支持32员、64员与多按处理器,支持ARM、Intel、PowerPC等系统。主要采取被国防、航空航天、汽车、医疗及工业领域。它具备可以之支出条件以及软件支持,但是昂贵的价格被开发者望而却步。

2、QNX

QNX是一个分布式、嵌入式、可圈扩大、遵从POSIX规范之类Unix微内核硬实时操作系统。主要用来商用,目标市场要是面向嵌入式系统。
其根本独立自处于一个深受保障之地方空间,驱动程序、网络协议和应用程序处于程序空间受到。内核仅提供4种服务:进程调度、进程中通信、底层网络通信和刹车处理。所有其他OS服务,都实现啊合作的用户进程,在单身的地方空间运行。因此QNX内核非常小巧(QNX4.x光景为12Kb),运行速度极快;操作系统模块和本相互独立,具有非常高之可靠性。而且跟UNIX具有高度相似性,使得为数众多的平静成熟之UNIX、LINUX应用可一直移植到QNX这个更平稳快速的实时嵌入式平台上。

3、Xenomai

Xenomai是一个于Linux平台上建由底通用实时框架的自由软件项目。
前期Xenomai是同样种植在采用双基础机制时对非克用于强实时用的Linux内核的扩张,其先级高于Linux
内核。后来慢慢发展变成一个熟的实时Linux架构。
Xenomai
实时内按为开发强实时行使提供了长的功能,主要包括实时线程调度和管理、用户空间实时任务支持、线程同步服务、时钟服务、中断服务、动态内存申请和实时对象注册服务等。主要用来工业自动化行业。

4、Intime

INtime是暨 Windows 操作系统共享硬件平台的实时操作系统。
Windows内核驱动程序管理用于运行基本和实时应用程序的内存,并且管理这半单网中的报道接口。INtime
内核为实时虚拟机提供操作系统服务,包括一个因优先级的抢先式计划程序,该程序执行基于优先级的暂停处理。内核计划程序已经进行优化,以获得最佳的中断性能。

4、Sylixos

SylixOS 是一律款款由中国人口自主设计开的大型嵌入式硬实时操作系统,支持 SMP
多按,具有丰富的文件系统、网络体系以及众多设施驱动支持,并提供完善之合开发环境。经过多年的穿梭开发同改善,已经化为一个可靠稳定,功能健全,易于开发调试之嵌入式实时系统出平台。SylixOS的落地可以解脱国内部分中心设备对海外嵌入式操作系统的靠,为国内的嵌入式信息技术行业提供一个全新的选项。现就运为航空航天及国防导弹等世界。

5、ucos

UCOS
是一个足以因ROM运行的、可减掉的、抢占式、实时多任务基本,具有莫大可移植性的嵌入式实时操作系统。特别吻合给电脑和控制器,适合多商业操作系统。有着完整的纱体系和文件系统,并且开放源代码。功能支持TCP/IP、USB、CAN总线、Modbus。具有一个强硬的文件系统和图形用户界面。UCOS采用可剥夺型实时多任务基本,其任务调度是全依据任务优先级的抢占式调度,具有可靠和快速等特征。在打工业控制、医疗装备、航天系统等领域有大的以。

亚、团队项目

做到一个团项目,主要作用是兑现一个两轴机械手的活动控制仿真,主要职能包括:

  • 用户接口任务:负责接来自用户之求,并发送运动指令给轨道插补任务。
  • 轨道插补任务:接收运动指令,实时计算各轴的岗位与速而定值。
  • 大体引擎接口:基于ODE开源物理引擎,创建一个两轴机械手与条件之大体模型,用轨迹插补任务输出的各轴位置及进度而定值控制模型的移位,并拿实时状态汇报让轨道插补任务。
  • 图形化用户接口:可依据qt把上述功效集成及一个GUI界面。

我对轨道插补任务及图形化用户接口比较感兴趣。我前与过部分嵌入式项目,有比强之编纂代码的力。在《数控系统》的念过程被,就本着插补很感兴趣。另外,我啊想可以触发部分图形化的编程,学习一下即地方的学识。

老三、编程实现稳定运动轨迹生成器

在task_trajectory_generator任务中增加代码来拍卖来自task_command_sender的永恒运动命令new_cmd,按照该令中吃起之位置、速度、加速度、减速度,实现一个梯形加减速(原理见数控技术教材)的移位轨迹生成器,当达到目标位置时,把new_cmd.Done设为true,主程序检测及new_cmd.Done为true时拿竣工运行。
编程要求:

  • 轨道生成器的代码结构能充分体现出因状态机的编程方法。
  • 管第一个可以运作的版发布到好的github账号上,并频频优化以及付。
  • 创建一个TODO.md文档写下自己之编程思路以及生一样步要举行的行事。

以缩短运行时刻及改善输出的效果,我转了new_cmd命令中的Position值,注释掉了Task
Time的printf部分,并将task_trajectory_generator的任务周期航天科工改也0.1s。
V1.0代码已经发表到GitHub上

https://github.com/liqi120150/simple_motion.git

如下:

#include <stdio.h>
#include <math.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>

#include <native/task.h>
#include <native/timer.h>

// Data Type

typedef struct
{
    bool Request;
    bool Response;
    bool Done;
    double Position;
    double Velocity;
    double Acceleration;
    double Deceleration;
    double Jerk;
} tPosCmd;

typedef struct
{
    double Position;
    double Velocity;
} tAxisSetpoint;

//Global variables

RT_TASK task_trajectory_generator;
RT_TASK task_command_sender;

tPosCmd new_cmd;
tAxisSetpoint axis1_setpoint;

int cycle_count = 0;

/*****************************************************
 * status machine
 * 
*****************************************************/
typedef enum
{
    Idel = 0,
    Accelerate,
    Decelerate,
    UniformVelocity 
}trajectoryStatusDef;

#define Position_DeadSize   10
#define Velocity_DeadSize   10
void task_trajectory_generator_proc(void *arg)
{
    RTIME now, previous;
    trajectoryStatusDef Status = Idel;

    /*
     * Arguments: &task (NULL=self),
     *            start time,
     *            period (here: 0.1 s)
     */
    rt_task_set_periodic(NULL, TM_NOW, 100000000);
    previous = rt_timer_read();

    axis1_setpoint.Position = 0;
    axis1_setpoint.Velocity = 0;

    int temp;

    float delta_T;
    while (1) {
        rt_task_wait_period(NULL);
        now = rt_timer_read();

        /*
         * NOTE: printf may have unexpected impact on the timing of
         *       your program. It is used here in the critical loop
         *       only for demonstration purposes.
         */
        /*
        printf("Task A Time since last turn: %ld.%06ld ms\n",
               (long)(now - previous) / 1000000,
               (long)(now - previous) % 1000000);
        */


        //  Add your code
        delta_T = ((double)(now - previous) / 1000000000);
        previous = now;

        if(new_cmd.Request)
        {
            printf("Position:%10.3f,Velocity:%10.3f at time:%10.3f s.\r\n", 
                axis1_setpoint.Position,
                axis1_setpoint.Velocity,
                (double)now / 1000000000);
            if(fabs(new_cmd.Position - axis1_setpoint.Position) > Position_DeadSize)
            {
                if(fabs(new_cmd.Velocity - axis1_setpoint.Velocity) > Velocity_DeadSize)
                {
                    if(fabs((axis1_setpoint.Velocity * axis1_setpoint.Velocity) / (2*new_cmd.Deceleration)) >= fabs(new_cmd.Position - axis1_setpoint.Position))
                    {
                        if(axis1_setpoint.Velocity > 0)
                            Status = Decelerate;
                        else
                            Status = Accelerate;
                    }
                    else if(new_cmd.Velocity > axis1_setpoint.Velocity)
                        Status = Accelerate;
                    else
                        Status = Decelerate;
                }
                else
                {
                    if(fabs((axis1_setpoint.Velocity * axis1_setpoint.Velocity) / (2*new_cmd.Deceleration)) >= fabs(new_cmd.Position - axis1_setpoint.Position))
                    {
                        if(axis1_setpoint.Velocity > 0)
                            Status = Decelerate;
                        else
                            Status = Accelerate;
                    }
                    else
                        Status = UniformVelocity;
                }
            }
            else
            {
                Status = Idel;
                new_cmd.Response = true;
                new_cmd.Done = true;
            }
            switch(Status)
            {
                case Accelerate:
                    //s = s0 + v0*delta_T + 0.5*acce*(delta_T^2)
                    axis1_setpoint.Position += axis1_setpoint.Velocity*delta_T + 0.5*new_cmd.Acceleration * (delta_T * delta_T);
                    //v = v0 + acce*delta_T
                    axis1_setpoint.Velocity += new_cmd.Acceleration*delta_T;
                    break;
                case Decelerate:
                    //s = s0 + v0*delta_T - 0.5*Deceleration*(delta_T^2)
                    axis1_setpoint.Position += axis1_setpoint.Velocity*delta_T - 0.5*new_cmd.Deceleration * (delta_T * delta_T);
                    //v = v0 - Deceleration*delta_T
                    axis1_setpoint.Velocity -= new_cmd.Deceleration*delta_T;    
                    break;
                case UniformVelocity:
                    //s = s0 + v0*delta_T;
                    axis1_setpoint.Position += axis1_setpoint.Velocity*delta_T;
                    break;
                case Idel:
                    break;
                default:
                    break;
            }
        }


    }
}

void task_command_sender_proc(void *arg)
{
    RTIME now, previous;

    /*
     * Arguments: &task (NULL=self),
     *            start time,
     *            period (here: 2 s)
     */
    rt_task_set_periodic(NULL, TM_NOW, 2000000000);
    previous = rt_timer_read();

        new_cmd.Request = false;
        new_cmd.Response = false;
        new_cmd.Done = false;
        new_cmd.Position = 0;
        new_cmd.Velocity = 0;
        new_cmd.Acceleration = 0;
        new_cmd.Deceleration = 0;
        new_cmd.Jerk = 0;

    while (1) {
        rt_task_wait_period(NULL);
        now = rt_timer_read();

        /*
         * NOTE: printf may have unexpected impact on the timing of
         *       your program. It is used here in the critical loop
         *       only for demonstration purposes.
         */
         /*
        printf("Task B Time since last turn: %ld.%06ld ms\n",
               (long)(now - previous) / 1000000,
               (long)(now - previous) % 1000000);
        */
               previous = now;
                cycle_count = cycle_count + 1;
                printf("cycle_count:%d\n",cycle_count);

                if(cycle_count == 5)
                {
                    new_cmd.Request = true;
                    new_cmd.Response = false;
                    new_cmd.Done = false;
                    new_cmd.Position = 20000;
                    new_cmd.Velocity = 1000;
                    new_cmd.Acceleration = 50;
                    new_cmd.Deceleration = 50;
                    new_cmd.Jerk = 0;

                }

    }
}

void catch_signal(int sig)
{

}


int main(int argc, char* argv[])
{
    signal(SIGTERM, catch_signal);
    signal(SIGINT, catch_signal);

    /* Avoids memory swapping for this program */
    mlockall(MCL_CURRENT|MCL_FUTURE);

        printf("A simple motion control demo\n");
    /*
     * Arguments: &task,
     *            name,
     *            stack size (0=default),
     *            priority,
     *            mode (FPU, start suspended, ...)
     */
    rt_task_create(&task_trajectory_generator, "rttask_trajectory_generator", 0, 99, 0);
    rt_task_create(&task_command_sender, "rttask_command_sender", 0, 98, 0);

    /*
     * Arguments: &task,
     *            task function,
     *            function argument
     */
    rt_task_start(&task_trajectory_generator, &task_trajectory_generator_proc, NULL);
    rt_task_start(&task_command_sender, &task_command_sender_proc, NULL);

        while(!new_cmd.Done);
        printf("End! \n");
    rt_task_delete(&task_trajectory_generator);
    rt_task_delete(&task_command_sender);
    return 0;
}

代码运行效果:
航天科工 1

众目睽睽,目前之代码用全局变量进行任务中的通信,且同样不良只能发送一个稳住命令。计划下一样步用Queue来进展通信,实现命令的缓冲和移动轨迹的平缓工作。

发表评论

电子邮件地址不会被公开。 必填项已用*标注