ITS
|
The ITS project is an open-source project implementing the ETSI ITS standards:
The project is omplemented using the framework Qt to be cross-platform, and to take advantage of signals and slots mechanisms.
We have a global project ITS, with several sub-projects: Application, CAN, Facilities, GeoNet, GPS, Hybrid, LibITS, Management, Network, Security and UpperTester. Some of them have other sub-projects: Facilities, Network and LibITS. The latter has another sub-project with sub-projects inside: LibASN. This division in many sub-projects permits to have a better view of the project in the editor and facilitates the versioning, because as SVN branches, sub-projects are sub-directories.
To encode and decode CAM and DENM payload, we need to use the ASN.1 UPER, and so we use the asn1c tool, which converts ASN.1 files into C structures with different codecs: XER, BER, DER and UPER. Since this tool converts ASN.1 files into C structures, we decided to create an ASN.1 file of the security header and trailer, that's why there is a security sub-project inside the LibASN, so we can manipulate security layers structures and if the standard changes, we change the ASN.1 file, not the structures themselves.
To implement the ETSI ITS stack, we decided to be as close as possible to the standards:
In all the following sub-sections, methods read() and readDebug() have the same behaviors: read() read the configuration associated to the module and set the module, readDebug() print the values. To read configuration files, we use the confuse
library.
For better understanding of the working of the different layers we will first see how we implemented the Management layer. The Manager is the Management layer class with all the possible sensors and modules parameters. These sensors and modules are pointers. The Manager puts all set pointers (i.e. used sensors and modules) into a HashMap with key string pointing to void pointer. With this implementation, modules and sensors get the Manager pointer in their constructor, get the pointer to the sensor or module parameter needed and if value change in them, they automatically get the new value. The Manager has a signal midToChange connected to its slot changeMID. This signal is used by the GeoNet layer when a duplicate address is detected to virtually change the MAC address.
We use sensors and application in the Manager. Actually, real GPS and CAN bus providers and application are classes, which inherit Fake sensors and application. By doing this, if the sensor or application is used, we put the real sensor / application into the Manager's HashMap, the Fake one otherwise. Parameters are used to initialize different modules and the GnAddr is the GeoNetworking Address of the ITS-S.
For GPS and CAN bus, the implementation is quite similar. They inherit of a Fake CAN and GPS provider used if we do not have / need the real sensor. They both have a Parameter with all values: heading, position speed and timestamp for GPS, and acceleration control (gas pedal, brake pedal cruise control etc.), curvature, curvature calculation mode, drive direction, exterior lights state, external temperature, lateral acceleration, light bar and siren state, longitudinal acceleration, number of occupants, positioning solution type (GNSS, dead reckoning, both), position of occupants, speed (used if we do not have GPS), steering wheel angle, vertical acceleration and yaw rate for CAN bus. All these values are the ones used by CAM and DENM. If we need more values, we need to add them. Fake classes have functions to change values used by the UpperTester. Since we only have a real GPS sensor, only GPS has a real class GPSProvider with a function to get the GPS position every 100 ms (minimum frequency of CAM generation). When a value from a sensor is changed, a positionChanged() or canChanged() signal is emitted.
As for sensors, there are two types of Application layer: the real one (the ApplicationManagement) and the fake one for the UpperTester. The difference with sensors, is that the real Application does not inherit from the Fake one. They do not have the same job. The Fake one set different parameters and the real one triggers events (automatic or manual). The FakeApplicationProvider is composed by a ParameterApplication; the ParameterApplication by the different type of static value that can be changed on time by an external application; and the ApplicationManagement by the connection to the CAN bus and GPS sensor, the UpperTester if there are tests with CAM (notification of CAM reception) or DENM (generation and notification of DENM reception), and all the necessary for a good Bluetooth communication with the HMI. Functions from the FakeApplicationProvider will be used by the UpperTester to set some values: station type, vehicle role, embarkation status, priority (on road: with traffic light, cross etc.), type of dangerous goods transported and the station ID. The ApplicationManagement works as follow: if there is the application needed for triggering event, it connects the CAN and GPS signals to its slot situationChanged(), if there is Bluetooth, it turns the server on to communicate with the HMI, initializes UDP sockets with the Facilities layer and if there is an UpperTester, sets the UDP socket to communicate with the UpperTester. When a client is connected to the Bluetooth server, the server adds it to its client list. When it receives a message from the HMI (or the UpperTester), it sends it to the Facilities, and when it receives a message from the Facilities, it sends the message to the clients and to the UpperTester if needed.
The Facilities layer is composed by three sub-layers: Facilities, CA and DEN. The Facilities sub-layer executes the CA and DEN if needed. The CA is composed by the CA Basic Service to generate CAM and the CA Reception Management to receive CAM. The DEN is composed by the DEN Basic Service, the DEN Triggering Management, the DEN Reception Management and the DEN KAF Management.
The DEN Basic Service set the different modules and forward requests to the appropriate DEN module and returns the result to the Application. The DEN Triggering Management manages the triggering, updating and termination of DENM; the DEN Reception Management the DENM reception and executes the KAF if activated; and the DEN KAF Management the KAF procedures. Besides the three modules, the DEN Basic Service is composed by the Application parameters, DENM parameters, a UDP socket to communicate with the Application layer, and a function AppDENM_terminate to call the good module to terminate the DENM (DEN Triggering Management if it is my event, Reception Management otherwise). The DEN Triggering Management has some parameters to set DENM and a vector of denMessageTableSource to store triggered DENMs. The DEN Reception Management has also some parameters and a vector of denMessageTableReception to store received DENMs and a UDP socket to notify the Application. Both DEN Triggering and Reception Management have a sequence number to be coherent with the identification of DENMs. The DEN KAF Management has parameters and a vector of denMessageTableForwarding to store DENMs to repeat. These vectors have the same working template: they set the different timers and start them.
It is easier for the CA: the CA Basic Service wait for a timer or a signal reception that position or CAN bus changed. It then looks if it can generate a CAM, generates and send it; and the CA Reception Management, receives the CAM, decode it and notify the Application.
The DEN Reception and CA Reception Management listen to a UDP socket on the Localhost and the port corresponding to the destination port from the BTP standard. With this mechanism, we do not need to specify an ad-hoc port, and if there is no Reception Management, the GeoNetworking layer will not be disturbed. If there is a destination port info in the BTP layer, it is managed by the Reception Management.
The GeoNetworking layer has only two working classes: GeoNet and ReceivePackets. That GeoNet class is responsible for the Beacon generation and sending (if no source position vector is sent), and has a function used by it and by the Facilities layer to send data. The GeoNet class manages also the processing of received packet by the ReceivePackets class. To send packets, GeoNet create a raw packet to send in the interface from configuration file. It permits to not have an ITS-G5 interface to send packet: we can use all kind of interface (Wi-Fi, Ethernet, Localhost etc.). If the hybridization is turned on, a TCP socket is created to send the same packet as for ITS-G5 interface (except for the Ethernet layer). By doing this, when we receive packet through the ITS-G5 interface or hybridization, it is the same function to call to process it, and so the same behavior. To know how to send data, the sending function needs a gnDataRequest_t structure: typedef struct gnDataRequest_s { CommonHeader::e_upperProtocolEntity upperProtocolEntity; CommonHeader::e_headerType packetTransportType; quint8 packetTransportSubType; quint16 destinationPort; quint16 destinationPortInfo; destinationAddress_t destinationAddress; e_gnCommunicationProfile gnCommunicationProfile; LifeTime* maximumPacketLifeTime; quint16* repetitionInterval; quint16* maximumRepetitionTime; quint8* maximumHopLimit; TrafficClass trafficClass; QByteArray payload; }gnDataRequest_t; with CommonHeader::e_upperProtocolEntity an enum with possibles values {ANY, BTP A, BTP B, IPv6}; CommonHeader::e_headerType and packetTransportSubType the values of the HeaderType and HeaderSubType from the CommonHeader; destinationAddress_t a union between a GeoNetworking address or a destination area, e_gnCommunicationProfile an enum with values {Unspecified, ITS G5A}. Each "person" who wants to send data needs to fill in a gnDataRequest_t structure.
To be able to use the different routing algorithms, the GeoNet class is composed by different packet buffer and each kind of packet has a class to be put in HashMaps (we need comparison functions, and only classes can do it easily). By making classes of each packet type, we can fill them faster and easier than with structures.
The ReceivePackets class has only the configuration parameter to know which interface to listen, and which MAC address to not listen (our MAC address) and a signal connected to the GeoNet packet processing slot. In terms of algorithm, using the pcap library, look up for ITS-G5 interface, open it on live mode, handle it and listen to it with the filter Ethernet with a protocol number 0x8947 and the Ethernet source different of the ITS MAC address. When the MAC address changes for different reason, the ReceivePackets class change the filter and listen again.
For the security layer, we have a SecurityManager class which knows the different profiles and stores the received payload and receives certificates. With this, it can adapt the profiles to send and can retrieve if a sender has the right SSPs to send packets. To encode or decode the security layer of a packet, the GeoNet use the SecurityManager's functions. That's why it has a SecurityManager attribute.
The UpperTester is an emulation of received signals of the tested ITS-S, and so, it should not change the behavior by itself, but make the ITS-S change its behavior. That's why in our implementation, the UpperTester use the functions of Fake GPS, CAN and Applications, and that's why these Fake modules have attributes corresponding to the UpperTester primitives. To encode primitives, the UpperTester has a table of 256 possible primitives (the primitive identifier is encoded in one byte). These primitives are function pointer to the primitive itself. Using a table of function pointer is more efficient than a vector or an HashMap, because we call the m_req[request[0]] (assuming that our table is called m_req, and the payload request). If the request number does not exist, we respond to the tester with a failure response. When the UpperTester needs to send a GeoNetworking packet, it calls the GeoNet send function with a filled gnDataRequest_t as if it is the Facilities layer. If it is a DENM test, it creates an AppDENM request as if it is the Application layer. If it has to change a parameter, it uses the parameter's function dedicated to.
As mentioned before, configuration files are managed with the
confuse
library. All the configuration files are placed in the /etc/its/config directory. We have 8 files:
All these files permits to set the ITS default configuration and all parameters need for laboratory testing.: appli.conf for the ParameterApplication attributes, btp.conf for the BTP ports number, can.conf for the ParameterCAN, denm.conf for the KAF and values of request and result identifiers, gps.conf for the static position and the address of the GPS deamon, security.conf for the localization of the private key and certificate, system.conf for the networking configuration and static values like vehicle length, and the upperTester.conf for the ports used by the UpperTester and the destination area to use for DENM triggering.
Once the configuration made, to execute the ITS stack, we call the geonet program:
Usage: geonet <abcfCDgHnuh>
-a --application: Activate the ApplicationManager
-b --bluetooth: Activate the Bluetooth
-c --can: Activate the CANProvider
-f --facilities: Activate the facilities layer
-C --cam: Activate CAM only
-D --denm: Activate DENM only
-g --gps: Activate the GPSProvider
-H --hybrid: Activate the hybridization
-n --geonet: Activate the ITS-G5 interface
-u --upperTester: Activate the UpperTester
-h --help: Print this help and quit