Main Content

Generate C++ Message Interfaces for Lane Following Controls and Sensor Fusion

This example shows how to generate C++ code that supports message-based communication between components of a highway lane following system. Generating code with message interfaces enables your application to communicate in a distributed system that uses an external message protocol service.

Introduction

Next generation autonomous vehicles (AVs) run highly complex algorithms to perform perception, planning, and control. Service-oriented architecture (SOA) is becoming a prevalent means of dealing with this increasing complexity. SOA promotes a distributed approach to implementing perception, planning, and control algorithms using local computing units. These units can exchange information with each other using message-based communication services such as Robot Operating System (ROS), Data Distribution Services (DDS), and the AUTOSAR Adaptive Platform.

This example focuses on modeling message-based communication between sensor fusion and controls components of a highway lane-following application. The example uses the Send (Simulink) and Receive (Simulink) blocks from the Simulink Messages and Events library to model the message-passing interface between the components of this system. This example also uses the HLFControlsWithSensorFusionTestBench model from the Automate Testing for Highway Lane Following Controls and Sensor Fusion example. In this example, you:

  1. Identify algorithm components for deployment — Review the test bench model with signals and identify the algorithm components in the test bench model.

  2. Add Simulink message interfaces to algorithm components — Review the test bench model with Simulink messages. Simulate the model and examine the results.

  3. Generate C++ code — Configure the algorithm components with Simulink messages to generate C++ code.

  4. Explore generated code — Explore the generated code and observe message interfaces.

In this example, you enable system-level simulation through integration with the Unreal Engine® from Epic Games®.

if ~ispc
    error(['This example is supported only on Microsoft',char(174),' Windows',char(174),'.'])
end

Identify Algorithm Components for Deployment

This example uses a system-level simulation test bench model to interface with Simulink messages. To explore the test bench model, load highway lane following controls with sensor fusion project.

openProject("HLFControlsSensorFusion");

Open the test bench model and highlight the model components for deployment.

open_system("HLFControlsWithSensorFusionTestBench")
hilite_system("HLFControlsWithSensorFusionTestBench/Forward Vehicle Sensor Fusion")
hilite_system("HLFControlsWithSensorFusionTestBench/Lane Following Decision Logic")
hilite_system("HLFControlsWithSensorFusionTestBench/Lane Following Controller")

The test bench model contains these subsystems:

  • Simulation 3D Scenario — Specifies the road, vehicles, vision detection generator, and radar sensors used for the simulation.

  • Forward Vehicle Sensor Fusion — Fuses the vision and radar sensor detections of vehicles in front of the ego vehicle.

  • Lane Following Decision Logic — Algorithm model that specifies the lateral and longitudinal decision logic, and provides lane center information and most important object (MIO) related information to the controller.

  • Lane Following Controller — Algorithm model that specifies the controller.

  • Vehicle Dynamics — Specifies the dynamic model for the ego vehicle.

  • Metrics Assessment — Assesses system-level behavior.

This example configures the Forward Vehicle Sensor Fusion, Lane Following Decision Logic, and Lane Following Controller components using Simulink messages.

Add Simulink Message Interfaces to Algorithm Components

To model a message passing interface for algorithm components, add Send and Receive blocks at the output and input ports, respectively, of the algorithm components. Open the test bench model that contains message interfaces.

open_system("SOAHLFControlsWithSensorFusionTestBench")

Observe the message interfaces between the components of the model. To explore the modeling pattern for the message Send and Receive interfaces, open each component model.

Open the Forward Vehicle Sensor Fusion component.

open_system("SOAForwardVehicleSensorFusion")

Open the Lane Following Decision Logic component.

open_system("SOALaneFollowingDecisionLogic")

Open the Lane Following Controller component.

open_system("SOALaneFollowingController")

Observe the Simulink message Send and Receive blocks connected to the Lane Following Controller reference component. Simulate the model and examine the results.

sim("SOAHLFControlsWithSensorFusionTestBench");
   Assuming no disturbance added to measured output #3.
-->Assuming output disturbance added to measured output #2 is integrated white noise.
   Assuming no disturbance added to measured output #1.
-->Assuming output disturbance added to measured output #4 is integrated white noise.
-->"Model.Noise" is empty. Assuming white noise on each measured output.

Plot performance metrics for the lateral controller.

hFigLatResults = helperPlotLFLateralResults(logsout);

Close the figure.

close(hFigLatResults)

Plot performance metrics for the longitudinal controller. For more information about the lateral and longitudinal controller metrics, see Highway Lane Following.

hFigLongResults = helperPlotLFLongitudinalResults(logsout,time_gap, ...
    default_spacing);

Close the figure.

close(hFigLongResults)

Generate C++ Code

Generate C++ code for the Forward Vehicle Sensor Fusion, Lane Following Decision Logic, and Lane Following Controller algorithm components.

Configure the reference model parameters for code generation support.

helperSetModelParametersForCodeGeneration({'SOAForwardVehicleSensorFusion', ...
                                           'SOALaneFollowingDecisionLogic', ...
                                           'SOALaneFollowingController'});
save_system("SOAForwardVehicleSensorFusion");
save_system("SOALaneFollowingDecisionLogic");
save_system("SOALaneFollowingController");
 
 Model  configuration parameters: 
 
                 Parameter                      Value                                                              Description                                                      
    ___________________________________    _______________    ______________________________________________________________________________________________________________________

    {'SystemTargetFile'               }    {'ert.tlc'    }    {'Code Generation>System target file'                                                                                }
    {'TargetLang'                     }    {'C++'        }    {'Code Generation>Language'                                                                                          }
    {'SolverType'                     }    {'Fixed-step' }    {'Solver>Type'                                                                                                       }
    {'FixedStep'                      }    {'auto'       }    {'Solver>Fixed-step size (fundamental sample time)'                                                                  }
    {'EnableMultiTasking'             }    {'on'         }    {'Solver>Treat each discrete rate as a separate task'                                                                }
    {'ProdLongLongMode'               }    {'on'         }    {'Hardware Implementation>Support long long'                                                                         }
    {'BlockReduction'                 }    {'on'         }    {'Simulation Target>Block reduction'                                                                                 }
    {'MATLABDynamicMemAlloc'          }    {'on'         }    {'Simulation Target>Simulation Target>Dynamic memory allocation in MATLAB functions'                                 }
    {'OptimizeBlockIOStorage'         }    {'on'         }    {'Simulation Target>Signal storage reuse'                                                                            }
    {'InlineInvariantSignals'         }    {'on'         }    {'Simulation Target>Inline invariant signals'                                                                        }
    {'BuildConfiguration'             }    {'Faster Runs'}    {'Code Generation>Build configuration'                                                                               }
    {'RTWVerbose'                     }    {'off'        }    {'Code Generation>Verbose build'                                                                                     }
    {'CombineSignalStateStructs'      }    {'on'         }    {'Code Generation>Interface>Combine signal/state structures'                                                         }
    {'SupportVariableSizeSignals'     }    {'on'         }    {'Code Generation>Interface>Support variable-size signals'                                                           }
    {'CodeInterfacePackaging'         }    {'C++ class'  }    {'Code Generation>Interface>Code interface packaging'                                                                }
    {'GenerateExternalIOAccessMethods'}    {'Method'     }    {'Code Generation>Interface>Data Member Visibility>External I/O access'                                              }
    {'EfficientFloat2IntCast'         }    {'on'         }    {'Code Generation>Optimization>Remove code from floating-point to integer conversions that wraps out-of-range values'}
    {'ZeroExternalMemoryAtStartup'    }    {'off'        }    {'Code Generation>Optimization>Remove root level I/O zero initialization (inverse logic)'                            }
    {'CustomSymbolStrGlobalVar'       }    {'$N$M'       }    {'Code Generation>Symbols>Global variables'                                                                          }
    {'CustomSymbolStrType'            }    {'$N$M_T'     }    {'Code Generation>Symbols>Global types'                                                                              }
    {'CustomSymbolStrField'           }    {'$N$M'       }    {'Code Generation>Symbols>Field name of global types'                                                                }
    {'CustomSymbolStrFcn'             }    {'APV_$N$M$F' }    {'Code Generation>Symbols>Subsystem methods'                                                                         }
    {'CustomSymbolStrTmpVar'          }    {'$N$M'       }    {'Code Generation>Symbols>Local temporary variables'                                                                 }
    {'CustomSymbolStrMacro'           }    {'$N$M'       }    {'Code Generation>Symbols>Constant macros'                                                                           }

Generate code for the Forward Vehicle Sensor Fusion component.

slbuild("SOAForwardVehicleSensorFusion");
### Searching for referenced models in model 'SOAForwardVehicleSensorFusion'.
### Found 1 model reference targets to update.
### Starting serial model reference code generation build.
### Starting build procedure for: ForwardVehicleSensorFusion
### Successful completion of code generation for: ForwardVehicleSensorFusion
### Starting build procedure for: SOAForwardVehicleSensorFusion
### Successful completion of code generation for: SOAForwardVehicleSensorFusion

Build Summary

Model reference code generation targets:

Model                       Build Reason                                            Status           Build Duration
===================================================================================================================
ForwardVehicleSensorFusion  Target (ForwardVehicleSensorFusion.cpp) did not exist.  Code generated.  0h 5m 19.496s 

Top model targets:

Model                          Build Reason                                         Status           Build Duration
===================================================================================================================
SOAForwardVehicleSensorFusion  Information cache folder or artifacts were missing.  Code generated.  0h 0m 15.385s 

2 of 2 models built (0 models already up to date)
Build duration: 0h 5m 43.973s

Generate code for the Lane Following Decision Logic component.

slbuild("SOALaneFollowingDecisionLogic");
### Searching for referenced models in model 'SOALaneFollowingDecisionLogic'.
### Found 1 model reference targets to update.
### Starting serial model reference code generation build.
### Starting build procedure for: LaneFollowingDecisionLogic
### Successful completion of code generation for: LaneFollowingDecisionLogic
### Starting build procedure for: SOALaneFollowingDecisionLogic
### Successful completion of code generation for: SOALaneFollowingDecisionLogic

Build Summary

Model reference code generation targets:

Model                       Build Reason                                            Status           Build Duration
===================================================================================================================
LaneFollowingDecisionLogic  Target (LaneFollowingDecisionLogic.cpp) did not exist.  Code generated.  0h 0m 18.362s 

Top model targets:

Model                          Build Reason                                         Status           Build Duration
===================================================================================================================
SOALaneFollowingDecisionLogic  Information cache folder or artifacts were missing.  Code generated.  0h 0m 14.061s 

2 of 2 models built (0 models already up to date)
Build duration: 0h 0m 33.819s

Generate code for the Lane Following Controller component.

slbuild("SOALaneFollowingController");
### Searching for referenced models in model 'SOALaneFollowingController'.
### Found 1 model reference targets to update.
### Starting serial model reference code generation build.
### Starting build procedure for: LaneFollowingController
   Assuming no disturbance added to measured output #3.
-->Assuming output disturbance added to measured output #2 is integrated white noise.
   Assuming no disturbance added to measured output #1.
-->Assuming output disturbance added to measured output #4 is integrated white noise.
-->"Model.Noise" is empty. Assuming white noise on each measured output.
### Successful completion of code generation for: LaneFollowingController
### Starting build procedure for: SOALaneFollowingController
### Successful completion of code generation for: SOALaneFollowingController

Build Summary

Model reference code generation targets:

Model                    Build Reason                                         Status           Build Duration
=============================================================================================================
LaneFollowingController  Target (LaneFollowingController.cpp) did not exist.  Code generated.  0h 1m 15.455s 

Top model targets:

Model                       Build Reason                                         Status           Build Duration
================================================================================================================
SOALaneFollowingController  Information cache folder or artifacts were missing.  Code generated.  0h 0m 12.437s 

2 of 2 models built (0 models already up to date)
Build duration: 0h 1m 29.69s

Explore Generated Code

Explore the generated code for the Forward Vehicle Sensor Fusion component and verify the message interfaces.

Open the SOAForwardVehicleSensorFusion.cpp file and view these message interfaces:

  • TimeRecvData.RecvData — Receives system time from the Simulation 3D Scenario subsystem.

  • VisionRecvData.RecvData — Receives vision detections from the Simulation 3D Scenario subsystem.

  • RadarRecvData.RecvData — Receives radar detections from the Simulation 3D Scenario subsystem.

  • TracksSendData.SendData — Sends confirmed tracks detected by this component to the Lane Following Decision Logic component.

You can also use this process to verify the message classes for the Lane Following Decision Logic and Lane Following Controller components from their generated code.

For information about how to integrate the generated code with external message protocols, see Generate C++ Messages to Communicate Data Between Simulink and an Operating System or Middleware (Embedded Coder) and Model Message-Based Communication Integrated with POSIX Message Queues (Embedded Coder).

Related Topics