locked
Control loops RRS feed

  • Question

  • Hi
    I am writing an application in which I need to control a mobile robot using Microsoft Robotics Studio. For this I need control loop which runs with around 100Hz.

    I know MSRS is non-real-time and asynchronously, hence a precise time interval cannot be guaranteed. However, I would like to hear about experiences with this sort of problem and what to do to get the best results.

    Currently I am using the
    Code Block

    Microsoft::Robotics::Services::Sample::Timer::Proxy

    timer to generate events with 100Hz. This works fine when running with a little cpu usage, but when the cpu usage gets high (as it does when running a simulation) the timing is way off.

    I should mention that I am running on a single core cpu and in addition to the service with the control-loop I need to run at least 3 or 4 other services.

    Any good ideas?

    Best regards
    Lars-Peter Ellekilde
    Friday, October 26, 2007 6:48 PM

Answers

  • I believe the best way to implement a timer in CCR is to use the TimeoutPort and post a message to invoke the next loop at the end of the timer handler code.

     

    See this post for an example of how to implement a timer.

     

    The TimeoutPort lets you do a pause at the end of each loop. The following code creates a timer that sets the timeout to adjust the specified maximum frequency, however as you increase the frequency the timer gets less accurate:

     

    Code Block

    const int _maxFrequency = 10; //Hz

    private Port<DateTime> _timerPort = new Port<DateTime>();

     

    protected override void Start()

    {

        base.Start();

     

        Activate(Arbiter.Receive(true, _timerPort, TimerHandler));

     

        _timerPort.Post(DateTime.Now);

    }

     

    int _timerStartTicks = System.Environment.TickCount;

    int _frequency = 0;

     

    void TimerHandler(DateTime signal)

    {

        int startTicks = System.Environment.TickCount;

     

        // Do something here...

        Console.WriteLine("Tick!");

     

        int endTicks = System.Environment.TickCount;

        int deltaTicks = endTicks - startTicks;

        int deltaTimerTicks = endTicks - _timerStartTicks;

        _frequency++;

     

        if (deltaTimerTicks >= 1000)

        {

            _timerStartTicks = System.Environment.TickCount;

            Console.WriteLine("\t" + _frequency + "Hz");

            _frequency = 0;

        }

     

        int timeout = (1000 - deltaTicks * _maxFrequency) / _maxFrequency;

        if (timeout > 0)

        {

            Activate(

                Arbiter.Receive(false, TimeoutPort(timeout),

                    delegate(DateTime time)

                    {

                        _timerPort.Post(time);

                    }

                )

            );

        }

        else

        {

            _timerPort.Post(DateTime.Now);

        }

    }

     

    Tuesday, October 30, 2007 6:10 PM
  • The services inside the Utility assembly (including the Timer service) are primarily designed to be used in VPL, as they modularize the functionality in a service and services are represented as Activity blocks in VPL. For example when you're coding a service you can simply use the System.String class to manipulate strings, but in VPL you have to use the String service (displayed as "Text Functions" block) that wraps some of the String methods in that service's operations. So when implementing the service in code you don't need to use those utility services.

     

    For the timer also, using the TimeoutPort is a little more lightwight than using the Timer service which needs the Utility assembly to be loaded and the Timer service running. However, neither one guarantees an accurate frequency because on each tick CCR descides when to handle the request for the next tick depending on the tasks being scheduled.

    Tuesday, October 30, 2007 7:05 PM

All replies

  • I believe the best way to implement a timer in CCR is to use the TimeoutPort and post a message to invoke the next loop at the end of the timer handler code.

     

    See this post for an example of how to implement a timer.

     

    The TimeoutPort lets you do a pause at the end of each loop. The following code creates a timer that sets the timeout to adjust the specified maximum frequency, however as you increase the frequency the timer gets less accurate:

     

    Code Block

    const int _maxFrequency = 10; //Hz

    private Port<DateTime> _timerPort = new Port<DateTime>();

     

    protected override void Start()

    {

        base.Start();

     

        Activate(Arbiter.Receive(true, _timerPort, TimerHandler));

     

        _timerPort.Post(DateTime.Now);

    }

     

    int _timerStartTicks = System.Environment.TickCount;

    int _frequency = 0;

     

    void TimerHandler(DateTime signal)

    {

        int startTicks = System.Environment.TickCount;

     

        // Do something here...

        Console.WriteLine("Tick!");

     

        int endTicks = System.Environment.TickCount;

        int deltaTicks = endTicks - startTicks;

        int deltaTimerTicks = endTicks - _timerStartTicks;

        _frequency++;

     

        if (deltaTimerTicks >= 1000)

        {

            _timerStartTicks = System.Environment.TickCount;

            Console.WriteLine("\t" + _frequency + "Hz");

            _frequency = 0;

        }

     

        int timeout = (1000 - deltaTicks * _maxFrequency) / _maxFrequency;

        if (timeout > 0)

        {

            Activate(

                Arbiter.Receive(false, TimeoutPort(timeout),

                    delegate(DateTime time)

                    {

                        _timerPort.Post(time);

                    }

                )

            );

        }

        else

        {

            _timerPort.Post(DateTime.Now);

        }

    }

     

    Tuesday, October 30, 2007 6:10 PM
  • Hi,
    Thanks for the reply. I will give the TimeoutPort a try.

    Any reasons would I should/shouldn't expect it to work better (that is closer to a constant frequency) than when partnering with a Timer.Proxy service found in the  Utility.Y2006.M08.Proxy.dll?

    - Lars-Peter
    Tuesday, October 30, 2007 6:33 PM
  • The services inside the Utility assembly (including the Timer service) are primarily designed to be used in VPL, as they modularize the functionality in a service and services are represented as Activity blocks in VPL. For example when you're coding a service you can simply use the System.String class to manipulate strings, but in VPL you have to use the String service (displayed as "Text Functions" block) that wraps some of the String methods in that service's operations. So when implementing the service in code you don't need to use those utility services.

     

    For the timer also, using the TimeoutPort is a little more lightwight than using the Timer service which needs the Utility assembly to be loaded and the Timer service running. However, neither one guarantees an accurate frequency because on each tick CCR descides when to handle the request for the next tick depending on the tasks being scheduled.

    Tuesday, October 30, 2007 7:05 PM
  • Ok thanks again.
    Tuesday, October 30, 2007 7:09 PM