Xenomai에서 지원하는 RT_task(스레드) 동기화 관련 질문



  • 안녕하세요 서울과학기술대학교 김정엽 교수님 연구실 입니다.

    현재 STEP-IMX를 이용하여 맥슨모터를 제어하고 있는데 두개의 스레드를 이용하여 하나는 250Hz로 기구학을 풀어 관절의 목표위치를 계산하고 나머지 하나는 1Khz로  목표위치를 인터폴레이션하여 모터에 직접적인 구동명령을 보냅니다.  이렇게 나누게 된 이유는 기구학 연산시간이 1ms(1Khz)를 넘기 때문에(즉 1khz 스레드를 4번카운트할때마다 한번 기구학연산하는것은 불가능함.) 연산시간을 넉넉히 주고자 이런 방식을 적용해 보았습니다. 하지만 두개의 스레드가 동시에 시작하는 것이 아니기 때문에 모터가 움직이면서 1Khz스레드에서 모터의 목표위치와 250hz에서 연산한 모터위치 간극이 커지면서(1Khz 스레드가 4번 시행한것과 250Hz스레드가 1번 시행한 횟수를 싸이클이라고 한다면 이 싸이클의 차이가 커지면서 ex)1Khz 200번 시행 50cycle하는동안  250hz 48회시행해서 2번의 cycle만큼 딜레이가 생김) 소음및 미미한 진동이 발생하고 있습니다. 따라서 두개 또는 여러개의 쓰레드를 동기화하여 동일한 시간에 시작할 수 있으면 한데 어떤 방법을 적용해야 하는지 알 수 있으면 좋겠습니다.

    현재는 아래와 같이 메인문에 폴링방식으로 스레드를 생성하고 시작하는데

    rt_task_create(&Thread1_task, "Thread1_task", 0, 99, 0);
    rt_task_start(&Thread1_task, &Thread1_run, NULL);

    rt_task_create(&Thread2_task, "Thread2_task", 0, 99, 0);
    rt_task_start(&Thread2_task,&Thread2_run, NULL);

    동시에 시작하고 4ms마다 동시에 끝나는 동기화가 가능한지 알고 싶습니다.



  • Hi,

    You may use Xenomai Event (https://xenomai.org/documentation/xenomai-2.6/html/api/group__event.html) to synchronize the tasks.

    Please refer to my example below.

    #include <native/event.h>
    RT_EVENT syncEvent;
    unsigned long evtMask = 0x1; // xenomai event mask
    unsigned long numTicks = 4; // 4 times of 1ms cycle
    unsigned long remainTicks; void masterRun(void *arg)
    {
        uint64_t* cycleTask = (uint64_t* ) arg;     rt_task_set_periodic(nullptr, TM_NOW, *cycleTask);     while (1)
        {
            rt_task_wait_period(nullptr);         if (remainTicks == 0)
            {
                remainTicks = numTicks - 1; // remainTicks gets value from 0 to 3            
                rt_event_signal(&syncEvent, evtMask); // trigger rt event with the mask
            }
            else
            {
                remainTicks -= 1; // counting down
            }
            
            /* TODO: Implementation */
        }
    } void longRun(void *arg)
    {
        while (1)
        {
            // Wait for master event        
            unsigned long evtValue;
            int res = rt_event_wait(&syncEvent, evtMask, &evtValue, EV_ANY, TM_INFINITE);
            rt_event_clear(&syncEvent, evtMask, nullptr);         /* TODO: Implementation */
        }
    } int main()
    {
        // create sync event    
        if (rt_event_create (&syncEvent, "SyncEventName", 0x0, EV_PRIO) != 0)
        {
            printf("Could not create timing event!\n");
            return -1;
        }
        
        
        // bind sync event    
        if (rt_event_bind (&syncEvent, "SyncEventName", TM_NONBLOCK) != 0)
        {
            printf("Could not find timing event!\n");
            return -1;
        }
        
        // start master thread
        uint64_t cycleTaskPeriod = 1000000; // 1ms
        rt_task_create(&master_task, "MasterTask", 0, 99, 0);
        rt_task_start(&master_task, &masterRun, &cycleTaskPeriod);
        
        // start long-time task
        rt_task_create(&long_task, "LongTask", 0, 95, 0);
        rt_task_start(&long_task, &longRun, nullptr); }

    Thanks.


Log in to reply