Используйте рукописный код, чтобы интегрировать сообщения C++ с POSIX

В этом примере показано, как интегрировать сгенерированный Код С++ с POSIX, чтобы упростить коммуникацию сообщения. Пример приложения является системой позиционирования мультидатчика, спроектированной, чтобы оценить положение транспортного средства. Система позиционирования мультидатчика состоит из двух компонентов: датчики (многоуровневые модели) и модель оценки. Обрисованный в общих чертах рабочий процесс показывает, как подготовить каждый компонент, сгенерировать код и интегрировать сгенерированный код, чтобы передать сообщения между компонентами системы. Этот пример принимает, что вы знакомы с использованием сообщений в окружении Simulink. Для получения дополнительной информации смотрите, Генерируют сообщения C++, чтобы Связаться Между Simulink и Операционной системой или Промежуточным программным обеспечением.

Модели датчика

Первый компонент в системе позиционирования мультидатчика является датчиками. Система позиционирования использует accelometer и датчик GPS, чтобы оценить положение транспортного средства. Каждая модель датчика состоит из Функционального блока, блока Send и Выходного порта. Каждая модель датчика отправляет сообщения в модель оценки при помощи сообщений POSIX.

Подготовьте модели

Откройте модели rtwdemo_accel_send датчика и rtwdemo_gps_send.

Для каждой модели выполните эти шаги:

  1. В галерее Apps нажмите Embedded Coder.

  2. На панели инструментов, набор Время остановки к 100 секунды. Время остановки задает длительность сбора данных при оценке положения транспортного средства.

  3. В модели щелкните, чтобы открыть Функциональный блок. В Параметрах блоков, набор Имя файла к MAT-файлу для модели. Установите Шаг расчета на 0.01.

Сгенерируйте код

1. Для каждой модели датчика, в диалоговом окне Configuration Parameters, устанавливает эти параметры:

  • На панели Генерации кода, Языке набора к C++. Под Продвинутыми параметрами, Конфигурацией сборки набора к Specify и добавьте -lrt компоновщику C++.

  • На Интерфейсной панели, упаковке интерфейса Code набора к C++ class и диагностика ошибки в коде Мультиэкземпляра к none. Под Продвинутыми параметрами выберите MAT-file logging.

2. Сгенерируйте код. На вкладке C ++ Code нажмите Build.

Интегрируйте код

Чтобы интегрировать сгенерированный Код С++ из каждой модели датчика с POSIX, рука пишет реализацию отправить класса и сгенерировала основную программу (или создайте свое собственное). Этот пример предоставляет индивидуально настраиваемой основной программе реализованный, отправляют класс. Чтобы интегрировать код из каждой модели датчика, замените сгенерированный основной файл на индивидуально настраиваемый основной файл.

Рассмотрите индивидуально настраиваемый основной файл для каждого датчика:

1. Индивидуально настраиваемый основной файл для каждого датчика реализован таким же образом. Как пример, откройте индивидуально настраиваемый основной файл rtwdemo_accel_send_ert_main_customized.cpp.

2. Анализ реализованный отправляет класс:

  • Отправить функция класса, SendData, вызовы в API POSIX (mq_send) отправить сообщения.

  • Чтобы обеспечить доступ к очереди сообщений, очередь сообщений POSIX добавляется как переменная класса, и метод установки реализован, чтобы установить очередь.

class accelSendModelClassSendData_real_T : public SendData_real_T{
     mqd_t msgQueue;
     public:
     // Use POSIX to send messages
     void SendData(const real_T* data, int32_T length, int32_T* status)
     {
         unsigned int priority = 1;
         *status = mq_send(msgQueue, (char*)data, length, priority);
     }
     // Set method for class POSIX queue
     void SetMQ(mqd_t mq)
     {
         msgQueue = mq;
     }
 };

После отправить реализации класса создается экземпляр отправить класса (отправить объект). Отправить объект затем присоединен к модели датчика, чтобы позволить датчику отправить сообщения в оценочную модель.

// Create send object
static accelSendModelClassSendData_real_T Out1SendData_arg;
// Attach send object to sensor model to send messages
static accelSendModelClass rtObj( Out1SendData_arg);

3. Рассмотрите добавленные поведенческие функции очереди POSIX. Основная функция использует эти функции, чтобы открыть и закрыть очередь POSIX.

mqd_t openMQ(const char *name, int flags, int maxmsg, int msgsize)
 {
     struct mq_attr attr;
     attr.mq_flags = 0;
     attr.mq_maxmsg = maxmsg;
     attr.mq_msgsize = msgsize;
     mqd_t msgQueue = mq_open(name, flags, 0664, &attr);
     if (msgQueue < 0) {
         printf("mq_open failed\n");
         exit(1);
     }
     return msgQueue;
 }
void closeMQ(mqd_t msgQueue)
 {
     mq_close(msgQueue);
 }

4. Рассмотрите основную функцию. Реализованная основная функция использует ранее заданный класс и функции очереди, чтобы отправить сообщения и управлять очередью сообщений POSIX. Основная функция выполняет следующее:

  • Открывает очередь сообщений POSIX.

  • Отправляет сообщения.

  • Закрывает очередь POSIX.

int_T main(int_T argc, const char *argv[])
 {
     // Unused arguments
     (void)(argc);
     (void)(argv);
     // Initialize model
     rtObj.initialize();
     // Open POSIX message queue
     mqd_t msgQueue = openMQ("/PosixMQ_accel", O_CREAT | O_WRONLY, 2, 16);
     Out1SendData_arg.SetMQ(msgQueue);
     // Send messages
     while (rtmGetErrorStatus(rtObj.getRTM()) == (NULL)) {
     rt_OneStep();
     }
     // Matfile logging
     rt_StopDataLogging(MATFILE, rtObj.getRTM()->rtwLogInfo);
     // Disable rt_OneStep() here
     // Close POSIX message queue
     closeMQ(msgQueue);
     return 0;
 }

Оценочная модель

Второй компонент является оценочной моделью. Оценочная модель получает сообщения, которые имеют входные данные из моделей датчика, и вычисляет предполагаемое положение транспортного средства.

Подготовьте модель

Откройте модель rtwdemo_pos_estimate.

  1. В галерее Apps нажмите Embedded Coder.

  2. На панели инструментов, набор Время остановки к 100 секунды.

  3. В модели щелкните, чтобы открыть каждый импорт. В Параметрах блоков, Типе данных набора к double, Размерности порта к 3, и Шаг расчета к 0.01.

  4. Щелкните, чтобы открыть каждый блок Receive сообщения. Очистите Использование внутренний параметр очереди, чтобы позволить модели использовать очередь сообщений POSIX.

  5. Щелкните, чтобы открыть Функциональный блок. Этот блок реализует алгоритм оценки.

Сгенерируйте код

1. В диалоговом окне Configuration Parameters, установленном эти параметры:

  • На панели Генерации кода, Языке набора к C++. Под Продвинутыми параметрами, Конфигурацией сборки набора к Specify и добавьте -lrt компоновщику C++.

  • На Интерфейсной панели, упаковке интерфейса Code набора к C++ class и диагностика ошибки в коде Мультиэкземпляра набора к none. Под Продвинутыми параметрами выберите MAT-file logging.

2. Сгенерируйте код. На вкладке C ++ Code нажмите Build.

Интегрируйте код

Чтобы интегрировать сгенерированный Код С++ из оценочной модели с POSIX, рука пишет реализацию получить класса и сгенерировала основную программу (или создайте свое собственное). Оценочная модель получает сообщения от моделей датчика и вычисляет предполагаемое положение транспортного средства. Это примеры предоставляют индивидуально настраиваемой основной программе реализованный, получает класс. Чтобы интегрировать код из оценочной модели, замените сгенерированный основной файл на индивидуально настраиваемый основной файл.

Рассмотрите индивидуально настраиваемый основной файл:

1. Откройте индивидуально настраиваемый основной файл rtwdemo_pos_estimate_ert_main_customized.cpp.

2. Анализ реализованный получает класс:

  • Получить функция класса, RecvData, вызовы в API POSIX (mq_receive) получить сообщения.

  • Чтобы обеспечить доступ к очереди сообщений, очередь сообщений POSIX добавляется как переменная класса, и метод установки реализован, чтобы установить очередь.

class positionEstimateModelClassRecvData_real_T : public RecvData_real_T{
     mqd_t msgQueue;
     public:
     // Uses POSIX API mq_receive to receive messages
     void RecvData(real_T* data, int32_T length, int32_T* status)
     {
     // Add receive data logic here
     unsigned int priority = 1;
     *status = mq_receive(msgQueue, (char *)data, length, &priority);
     }
     // Set method for class POSIX queue
     void SetMQ(mqd_t mq)
     {
         msgQueue = mq;
     }
  };

После получить реализации класса экземпляр получить класса (получить объект) создается для каждой модели датчика. Получить объекты затем присоединены к оценочной модели, чтобы позволить модели получить сообщения от каждого датчика.

// Create receive objects
static positionEstimateModelClassRecvData_real_T In1RecvData_arg;
static positionEstimateModelClassRecvData_real_T In2RecvData_arg;
// Attach receive objects to estimate model to receive messages
static positionEstimateModelClass rtObj( In1RecvData_arg, In2RecvData_arg);

3. Рассмотрите добавленные поведенческие функции очереди POSIX. Основная функция использует эти функции, чтобы открыть, закрыть, и расцепить очередь POSIX.

mqd_t openMQ(const char *name, int flags, int maxmsg, int msgsize)
 {
     struct mq_attr attr;
     attr.mq_flags = 0;
     attr.mq_maxmsg = maxmsg;
     attr.mq_msgsize = msgsize;
     mqd_t msgQueue = mq_open(name, flags, 0664, &attr);
     if (msgQueue < 0) {
         printf("mq_open failed\n");
         exit(1);
     }
     return msgQueue;
 }
void closeMQ(mqd_t msgQueue)
 {
     mq_close(msgQueue);
 }
void unlinkMQ(const char *name)
 {
     if (mq_unlink(name) < 0) {
         printf("mq_unlink failed\n");
         exit(1);
     }
 }

4. Рассмотрите основную функцию. Реализованная основная функция использует ранее заданный класс и функции очереди, чтобы получить сообщения и управлять очередью POSIX. Основная функция выполняет следующее:

  • Открывает очередь сообщений POSIX.

  • Получает сообщения.

  • Закрывает очередь POSIX.

int_T main(int_T argc, const char *argv[])
 {
     // Unused arguments
     (void)(argc);
     (void)(argv);
     // Initialize model
     rtObj.initialize();
     // Open POSIX message queues
     mqd_t msgQueueAccel = openMQ("/PosixMQ_accel", O_CREAT | O_RDONLY, 2, 16);
     mqd_t msgQueueGPS = openMQ("/PosixMQ_gpspos", O_CREAT | O_RDONLY, 2, 16);
     In1RecvData_arg.SetMQ(msgQueueAccel);
     In2RecvData_arg.SetMQ(msgQueueGPS);
     // Receive messages
     while (rtmGetErrorStatus(rtObj.getRTM()) == (NULL)) {
         rt_OneStep();
     }
     // Matfile logging
     rt_StopDataLogging(MATFILE, rtObj.getRTM()->rtwLogInfo);
     // Disable rt_OneStep() here
     // Close POSIX message queues
      closeMQ(msgQueueAccel);
      closeMQ(msgQueueGPS);
      unlinkMQ("/PosixMQ_accel");
      unlinkMQ("/PosixMQ_gpspos");
     return 0;
 }

Выполните систему позиционирования мультидатчика

Чтобы выполнить систему позиционирования мультидатчика, восстановите и запустите исполняемые файлы для всех моделей. Чтобы просмотреть результаты, запустите предоставленный скрипт сборки rtwdemo_positioning_system_script. Пример результатов показывают в этом рисунке.