A Vehicle Model makes it possible to easily get vehicle data from the KUKSA Databroker and to execute remote procedure calls over gRPC against Vehicle Services and other Vehicle Apps. It is generated from the underlying semantic models based e.g. on the
COVESA Vehicle Signal Specification (VSS)
. The model is generated for a concrete programming language as a graph-based, strongly-typed, intellisense-enabled library providing vehicle abstraction “on code level”.
By default our app templates now generate the vehicle model during the devContainer initialization - managed by the Velocitas life cycle management. The respective VSS-based model source is referenced in the app manifest allowing to freely choose the model being used in your project. You will find more details about this in section
Automated Model Lifecycle
.
The previous approach, using pre-generated model repositories, is deprecated as of now. But is still available and is described in section
Manual Vehicle Model Creation
. Please be aware, that you would either have to use template versions before the above mentioned release, or you need to adapt the newer versions of the template using the old approach.
1 - Automated Vehicle Model Lifecycle
Learn how to refer a model source and how the automated model lifecycle is working.
Info
This article describes our new model lifecycle approach released on Friday, 2023-03-03. With that, the model is now automatically generated with the instantiation of the devContainer. It is generated from the vehicle model source file referenced in the AppManifest.
For the time being, the integration of services is not supported by the new approach.
The previous approach, using pre-generated model repositories, is now deprecated. But it is still available and
the vehicle API used as the source to generate the model is referenced in the app manifest,
the automatic generation of the model works,
you can trigger manual recreation of the model (after adding extensions to the API required by your project)
How to Reference a Model Specification
The model specification defines the vehicle API to be used by your project. It is referenced in the AppManifest.json via a URI or local file path like this:
The reference must point to a JSON file containing the model specification as VSS vspec. References to a VSS .vspec file hierarchy are not supported as of now.
when you trigger the VS Code task (Re-)generate vehicle model explicitly.
The model generation is a three step process:
The model generator is installed as a Python package (if not already present)
The referenced model specification is downloaded (if no local reference)
The model code is generated and installed.
The model is generated using our
Velocitas vehicle-model-generator
.
The used version and also the repository of the generator can be altered via the variables section of the project configuration in the .velocitas.json.
The default values for those are defined in the
manifest.json
of the
devContainer setup package
.
Also, the target folder for the generated model source code is specified here:
In Python template based projects the generated model is finally installed in the site-packages folder, while in C++ projects it is made available as a CMake include folder.
Learn how to manually create a vehicle model to access vehicle data or execute remote procedure calls.
Info
With the release of our new
model lifecycle approach
on Friday, 2023-03-03, the model is now automatically generated with the instantiation of the devContainer from a model source referenced in the app manifest.
The approach described here, using pre-generated model repositories, is deprecated as of now. But it is still available and must be used if you need access to vehicle services. Please be aware, that you would either have to use template versions before the above mentioned release, or you need to adapt the newer versions of the template using the old approach.
This tutorial will show you how to:
Create a Vehicle Model
Add a Vehicle Service to the Vehicle Model
Distribute your Python Vehicle Model
Note
A Vehicle Model should be defined in its own package. This makes it possible to distribute the Vehicle Model later as a standalone package and to use it in different Vehicle App projects.
The creation of a new vehicle model is only required if the vehicle signals (like sensors and actuators) defined in the current version of the
COVESA Vehicle Signal Specification
(VSS) is not sufficient for the definition of your vehicle API. Otherwise you could use the default vehicle model we already generated for you, see
A Vehicle Model can be generated from a
COVESA Vehicle Signal Specification
(VSS). VSS introduces a domain taxonomy for vehicle signals, in the sense of classical attributes, sensors and actuators with the raw data communicated over vehicle buses and data. The Velocitas
vehicle-model-generator
creates a Vehicle Model from the given specification and generates a package for use in Vehicle App projects.
Depending on the value of lang, which can assume the values python and cpp, this creates a sdv_model directory in the root of repository along with all generated source files for the given programming language.
Here is an overview of what is generated for every available value of lang:
lang
output
python
Python sources and a setup.py ready to be used as Python package
cpp
C++ sources, headers and a CMakeLists.txt ready to be used as a CMake project
Alternative to the generation from a VSS specification you could create the Vehicle Model manually. The following sections describing the required steps.
Once you have created your Vehicle Model either manually or via the Vehicle Model Generator, you need to distribute your model to use it in an application. Follow the links below for language specific tutorials on how to distribute your freshly created Vehicle Model.
Learn how to create a Vehicle Model manually for C++
Not yet done for C++
2.2 - Python Manual Vehicle Model Creation
Learn how to create a Vehicle Model manually for Python
Setup a Python Package manually
A Vehicle Model should be defined in its own Python Package. This allows to distribute the Vehicle Model later as a standalone package and to use it in different Vehicle App projects.
The name of the Vehicle Model package will be my_vehicle_model for this walkthrough.
Start Visual Studio Code
Select File > Open Folder (File > Open… on macOS) from the main menu.
In the Open Folder dialog, create a my_vehicle_model folder and select it. Then click Select Folder (Open on macOS).
Create a new file setup.py under my_vehicle_model:
To verify that the package is created correctly, install it locally:
pip3 install .
The output of the above command should look like this:
Defaulting to user installation because normal site-packages is not writeable
Processing /home/user/projects/my-vehicle-model
Preparing metadata (setup.py) ... done
Building wheels for collected packages: my-vehicle-model
Building wheel for my-vehicle-model (setup.py) ... done
Created wheel for my-vehicle-model: filename=my_vehicle_model-0.1-py3-none-any.whl size=1238 sha256=a619bc9fbea21d587f9f0b1c1c1134ca07e1d9d1fdc1a451da93d918723ce2a2
Stored in directory: /home/user/.cache/pip/wheels/95/c8/a8/80545fb4ff73c974ac1716a7bff6f7f753f92022c41c2e376f
Successfully built my-vehicle-model
Installing collected packages: my-vehicle-model
Successfully installed my-vehicle-model-0.1
Now it is time to add some Vehicle Models to the Python package. At the end of this section you will have a Vehicle Model, that contains a Cabin model, a Seatmodel and has the following tree structure:
Vehicle
└── Cabin
└── Seat (Row, Pos)
Create a new file Seat.py under my_vehicle_model/my_vehicle_model:
This creates the Seat model with a single data point of type float named Position.
Create a new file Cabin.py under my_vehicle_model/my_vehicle_model:
fromsdv.modelimportModelclassCabin(Model):def__init__(self,parent):super().__init__(parent)self.Seat=SeatCollection("Seat",self)classSeatCollection(Model):def__init__(self,name,parent):super().__init__(parent)self.name=nameself.Row1=self.RowType("Row1",self)self.Row2=self.RowType("Row2",self)defRow(self,index:int):ifindex<1orindex>2:raiseIndexError(f"Index {index} is out of range")_options={1:self.Row1,2:self.Row2,}return_options.get(index)classRowType(Model):def__init__(self,name,parent):super().__init__(parent)self.name=nameself.Pos1=Seat("Pos1",self)self.Pos2=Seat("Pos2",self)self.Pos3=Seat("Pos3",self)defPos(self,index:int):ifindex<1orindex>3:raiseIndexError(f"Index {index} is out of range")_options={1:self.Pos1,2:self.Pos2,3:self.Pos3,}return_options.get(index)
This creates the Cabin model, which contains a set of six Seat models, referenced by their names or by rows and positions:
row=1, pos=1
row=1, pos=2
row=1, pos=3
row=2, pos=1
row=2, pos=2
row=2, pos=3
Create a new file vehicle.py under my_vehicle_model/my_vehicle_model:
The root model of the Vehicle Model tree should be called Vehicle by convention and is specified, by setting parent to None. For all other models a parent model must be specified as the 2nd argument of the Model constructor, as can be seen by the Cabin and the Seat models above.
A singleton instance of the Vehicle Model called vehicle is created at the end of the file. This instance is supposed to be used in the Vehicle Apps. Creating multiple instances of the Vehicle Model should be avoided for performance reasons.
Add a Vehicle Service
Vehicle Services provide service interfaces to control actuators or to trigger (complex) actions. E.g. they communicate with the vehicle internal networks like CAN or Ethernet, which are connected to actuators, electronic control units (ECUs) and other vehicle computers (VCs). They may provide a simulation mode to run without a network interface. Vehicle Services may feed data to the Databroker and may expose gRPC endpoints, which can be invoked by Vehicle Apps over a Vehicle Model.
In this section, we add a Vehicle Service to the Vehicle Model.
Create a new folder proto under my_vehicle_model/my_vehicle_model.
Copy your proto file under my_vehicle_model/my_vehicle_model/proto
As example you could use the protocol buffers message definition
seats.proto
provided by the KUKSA services which describes a
seat control service
.
Install the grpcio tools including mypy types to generate the Python classes out of the proto-file:
pip3 install grpcio-tools mypy_protobuf
Generate Python classes from the SeatService message definition:
Some important remarks about the wrapping SeatService class
shown above:
The SeatService class must derive from the Service class provided by the Python SDK.
The SeatService class must use the gRPC channel from the Service base class and provide it to the _stub in the __init__ method. This allows the SDK to manage the physical connection to the gRPC service and use service discovery of the middleware.
Every method needs to pass the metadata from the Service base class to the gRPC call. This is done by passing the self.metadata argument to the metadata of the gRPC call.
2.3 - Vehicle Model Distribution
Learn how to distribute a Vehicle Model.
2.3.1 - C++ Vehicle Model Distribution
Learn how to distribute a Vehicle Model written in C++.
Now that you have created your own Vehicle Model, we can distribute it to make use of it in Vehicle Apps.
Copying the folder to your Vehicle App repo
The easiest way to get started quickly is to copy the created model, presumably stored in vehicle_model into your Vehicle App repository to use it. To do so, simply copy and paste the directory into the <sdk_root>/app directory and replace the existing model.
Using a git submodule
A similar approach to the one above but a bit more difficult to set up is to create a git repository for the created model. The advantage of this approach is that you can share the same model between multiple Vehicle Apps without any manual effort.
Clone it locally, add the created vehicle_model folder to the git repository
Commit everything and push the branch
In your Vehicle App repo, add a new git submodule via
git submodule add <checkout URL of your new repo> app/vehicle_model
git submodule init
Now you are ready to develop new Vehicle Apps with your custom Vehicle Model!
2.3.2 - Python Vehicle Model Distribution
Learn how to distribute a Vehicle Model written in Python.
Now you a have a Python package containing your first Python Vehicle Model and it is time to distribute it. There is nothing special about the distribution of this package, since it is just an ordinary Python package. Check out the
Python Packaging User Guide
to learn more about packaging and package distribution in Python.
Distribute to single Vehicle App
If you want to distribute your Python Vehicle Model to a single Vehicle App, you can do so by copying the entire folder my_vehicle_model under the /app/src folder of your Vehicle App repository and treat it as a sub-package of the Vehicle App.
Create a new folder my_vehicle_model under /app/src in your Vehicle App repository.
Copy the my_vehicle_model folder to the /app/src folder of your Vehicle App repository.
Import the package my_vehicle_model in your Vehicle App:
If you want to distribute your Python Vehicle Model inside an organization and use it to develop multiple Vehicle Apps, you can do so by creating a dedicated Git repository and copying the files there.
Create new Git repository called my_vehicle_model
Copy the content under my_vehicle_model to the repository.
Release the Vehicle Model by creating a version tag (e.g., v1.0.0).
Install the Vehicle Model package to your Vehicle App:
Import the package my_vehicle_model in your Vehicle App and use it as shown in the previous section.
Distribute publicly as open source
If you want to distribute your Python Vehicle Model publicly, you can do so by creating a Python package and distributing it on the
Python Package Index (PyPI)
. PyPi is a repository of software for the Python programming language and helps you find and install software developed and shared by the Python community. If you use the pip command, you are already using PyPI.
Detailed instructions on how to make a Python package available on PyPI can be found
here
.