Сгенерируйте сообщения C++ для связи между Simulink и операционной системой или промежуточным ПО

Чтобы сгенерировать Код С++, который поддерживает коммуникацию сообщений между Simulink верхней части моделей и внешними приложениями, используйте блоки Simulink Messages & События Library Send и Receive. Генерация кода из модели верхней части для облегчения сообщений, передаваемых вне Окружения Simulink, позволяет вашему смоделированному приложению общаться в распределенной системе, которая использует службу протокола внешних сообщений, обычно называемую операционной системой или промежуточным программным обеспечением (для сообщений примера, DDS, ROS, SOMIP или POSIX).

Simulink верхней части моделей передает сообщения следующим образом:

  • Модели верхнего уровня содержат блоки сообщений для связи вне окружения Simulink. Если верхняя модель содержит блок Send, непосредственно соединенный с корневым блоком Outport, блок преобразует свои сигналы в сообщения и передает их вне окружения Simulink. Если верхняя модель содержит блок Receive, непосредственно соединенный с корневым блоком Inport, блок преобразует полученные сообщения в сигналы.

  • Протокол внешнего сообщения управляет сообщением в соответствии с его собственным стандартом (политиками, которые управляют емкостью, порядком доставки и другим поведением качества обслуживания (QoS)).

Чтобы сгенерировать сообщения C++ для связи между Simulink верхней части моделей и операционной системой или промежуточным ПО, подготовьте модель, сгенерируйте код и интегрируйте этот код с выбранной операционной системой или промежуточным ПО.

Подготовка модели

Чтобы настроить свою модель, чтобы она могла передавать сообщения с помощью операционной системы или промежуточного программного обеспечения, сконфигурируйте модель как верхнюю модель, которая имеет по крайней мере один блок сообщений (блок Send, соединенный с корневым блоком Outport или блок Receive, соединенный с корневым блоком Inport). Верхняя модель может затем соединиться с выбранной операционной системой или промежуточным ПО через блоки сообщений, как показано:

В рамках модели порты сообщений соединяются как показано:

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

Чтобы сгенерировать код С++ из модели:

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

  2. В диалоговом окне Параметров конфигурации установите следующие параметры:

    • На панели Code Generation установите значение Language C++.

    • На панели Interface задайте Code interface packaging C++ class.

    • На панели Templates выберите Generate an example main program.

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

  4. Просмотрите сгенерированный код. На вкладке C++ Code нажмите View Code.

Интеграция кода

Чтобы интегрировать сгенерированные Коды С++ из вашей модели с выбранной операционной системой или промежуточным программным обеспечением, используйте рукописный код для реализации классов отправки и получения сообщений и кода приложения, который использует эти классы для передачи сообщений. В частности:

  1. Если вы используете свой собственный основной, создайте конкретные подклассы из сгенерированных абстрактных классов, показанных в RecvData_<T>.h и SendData<T>.h. Если вы используете сгенерированную пример основной программы, конкретные подклассы предусмотрены для вас в файле.

  2. Реализуйте функции класса SendData и RecvData для вызова выбранной операционной системы или промежуточного программного обеспечения для отправки и приема сообщений.

  3. Создайте образец реализованных классов отправки и получения сообщений (объекты отправки и получения).

  4. Создайте образец класса модели с помощью образцов каждого класса сообщений (объектов отправки и приема) в качестве аргументов в конструкторе модели.

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

Для интеграции:

  1. Откройте сгенерированный пример основной программы (или создайте свою собственную). Если вы используете сгенерированную пример основной программы, то конкретные подклассы RecvData_real_T и SendData_real_T указаны в файле. Если вы создаете свою собственную основную, создайте конкретные подклассы в коде вашего приложения:

  2. Для получения сообщений вручную запишите реализацию сгенерированного класса приема. Реализуйте функцию класса RecvData для вызова выбранной операционной системы или промежуточного программного обеспечения для получения сообщений.

    Пример реализации для POSIX показан:

    class mHMIHandlerRecvData_real_T: public RecvData_real_T {
        public:
        void RecvData(real_T* data, int32_T length, int32_T* status)
        {
            // Use POSIX API mq_receive to receive messages
            unsigned int priority = 1;
            *status = mq_receive(msgQueue, (char *)data, length, &priority);
        }
    };
    

    Создайте объект приема.

    static mHMIHandlerRecvData_real_T InMsgRecvData_arg;
    
  3. Для отправки сообщений вручную запишите реализацию сгенерированного класса отправки. Реализуйте функцию класса SendData для вызова выбранной операционной системы или промежуточного программного обеспечения для отправки сообщений.

    Пример реализации для POSIX показан:

    class mHMIHandlerSendData_real_T : public SendData_real_T {
        public:
        void SendData(const real_T* data, int32_T length, int32_T* status)
        {
            // Use the POSIX API mq_send to send messages
            unsigned int priority = 1;
            *status = mq_send(msgQueue, (char*)data, length, priority);
        }
    };
    

    Создайте объект отправки.

    static mHMIHandlerSendData_real_T OutMesgSendData_arg;
    

    Создайте образец класса модели путем использования объектов send и receive в качестве аргументов в конструкторе модели.

    static mHMIHandler mHMI_Obj(InMsgRecvData_arg, OutMsgSendData_arg);
    
  4. Отправляйте и получайте сообщения в соответствии с требованиями вашего приложения и поддерживайте время жизни очереди сообщений.

    Пример реализации для POSIX показан:

    int_T main(int_T argc, const char *argv[])
    {
        // Unused arguments
        (void)(argc);
        (void)(argv);
    
        //Initialize model
        mHMI_obj.initialize();     
    
        // Open POSIX queue
         mqd_t msgQueue = mq_open("/PosixMQ_Example", O_RDONLY);
         if (msgQueue == -1)
         {
             printf("mq_open failed\n");
             exit(1);
         }     
    
        // Send and Receive messages
         while (rtmGetErrorStatus(mHMI_Obj.getRTM()) == (NULL)) {
             //perform application tasks here.
             rt_OneStep();
         }   
    
        // Close POSIX queue
         mq_close(msgQueue);     
    
        // Terminate model
         mHMI_Obj.terminat():
         return 0;
     }

Более сложный пример интегрированию POSIX см. в разделе Использование рукописного кода для интеграции сообщений C++ с POSIX

Факторы и ограничения

  • Рукописный код является единственным поддерживаемым методом интегрирования.

  • Необходимо выбрать Generate an example main program параметра. Приложения, которые требуют статического основного, не поддерживаются.

  • Управление прототипом функции (FPC) не может быть сконфигурировано для верхней модели, которая имеет корневые порты сообщений.

Похожие темы