7

.cppソース コードを使用してリアルタイム シミュレーションを実行しています。0.2 秒 ( 200 ms ) ごとにサンプルを取得する必要があります...タイム ステップごとにサンプルを取得する while ループがあります... この while ループの実行を同期して、( 200 msごとに)サンプルを取得したい... while ループをどのように変更すればよいですか?

while (1){
          // get a sample every 200 ms
         }
4

5 に答える 5

2

リアルタイムオペレーティングシステムを使用していない限り、あなたが求めていることは難しいです。

ただし、Boost には必要なものをサポートするライブラリがあります。(ただし、正確に 200 ミリ秒ごとに呼び出されるという保証はありません。

Boost ASIO ライブラリはおそらくあなたが探しているものですが、チュートリアルのコードは次のとおりです。

//
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

int main()
{
  boost::asio::io_service io;

  boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
  t.wait();

  std::cout << "Hello, world!\n";

  return 0;
}

リンクはこちら:boost asioへのリンク

このコードを次のように再配置できます

#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

int main()
{
  boost::asio::io_service io;

  while(1)
  {
    boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));

    // process your IO here - not sure how long your IO takes, so you may need to adjust your timer

    t.wait();
  }    

  return 0;
}

次のページには、IO を非同期に処理するためのチュートリアルもあります。

于 2013-02-18T21:00:51.220 に答える
1

提供された回答は、これを達成するのに役立つツールがBoostで利用可能であることを示しています。私の最近の提供setitimer()は、反復タイマー用のPOSIX機能であるの使用方法を示しています。

基本的に次のような変更が必要です。

while (1){
          // wait until 200 ms boundary
          // get a sample
         }

反復タイマーを使用すると、発火した信号はブロックされた信号呼び出しを中断します。だから、あなたは永遠に何かをブロックすることができます。selectそのためにうまくいくでしょう:

while (1){
          int select_result = select(0, 0, 0, 0, 0);
          assert(select_result < 0 && errno == EINTR);
          // get a sample
         }

200ミリ秒ごとにインターバルタイマーを設定するには、を使用setitimer()して、適切なインターバルを渡します。以下のコードでは、間隔を200ミリ秒に設定しています。ここで、最初の間隔は150ミリ秒後に発生します。

struct itimerval it = { { 0, 200000 }, { 0, 150000 } };
if (setitimer(ITIMER_REAL, &it, 0) != 0) {
    perror("setitimer");
    exit(EXIT_FAILURE);
}

これで、シグナルハンドラーをインストールするだけで、SIGALRM何も実行されず、コードが完成します。

リンクをたどると、完成した例を見ることができます。

プログラムの実行中に複数のシグナルが発生する可能性がある場合は、中断されたシステムコールに依存するのではなく、SIGALRMハンドラーが決定論的な方法でウェイクアップできるものをブロックすることをお勧めします。1つの可能性は、パイプの読み取り端のwhileループブロックをオンにすることです。readシグナルハンドラは、そのパイプの書き込み端に書き込むことができます。

void sigalarm_handler (int)
{
    if (write(alarm_pipe[1], "", 1) != 1) {
        char msg[] = "write: failed from sigalarm_handler\n";
        write(2, msg, sizeof(msg)-1);
        abort();
    }
}

リンクをたどって、完成した例を確認してください。

于 2013-02-18T22:58:25.503 に答える
1
#include <thread>
#include <chrono>
#include <iostream>

int main() {
    std::thread timer_thread;
    while (true) {
        timer_thread = std::thread([](){
            std::this_thread::sleep_for (std::chrono::seconds(1));
         });

         // do stuff 
         std::cout << "Hello World!" << std::endl;

         // waits until thread has "slept" 
         timer_thread.join();

         // will loop every second unless the stuff takes longer than that.
    }

    return 0;
}
于 2017-03-29T07:23:57.140 に答える
0

絶対的な精度を得ることはほぼ不可能です - おそらく組み込みシステムでは。ただし、おおよその頻度のみが必要な場合は、std::chrono(c++11) やboost::chrono. そのようです:

while (1){
    system_clock::time_point now = system_clock::now();
    auto duration = now.time_since_epoch();
    auto start_millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
    //run sample
    now = system_clock::now();
    duration = now.time_since_epoch();
    auto end_millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
    auto sleep_for = max(0, 200 - (end_millis - start_millis ));
    std::this_thread::sleep_for( sleep_for );
}
于 2013-02-18T21:10:20.190 に答える