VehicleIO functionality when using a custom vio plug-in

Please provide the following info (check/uncheck the boxes after creating this topic):
Software Version
DRIVE OS Linux 5.2.6
DRIVE OS Linux 5.2.6 and DriveWorks 4.0
DRIVE OS Linux 5.2.0
DRIVE OS Linux 5.2.0 and DriveWorks 3.5
[*] NVIDIA DRIVE™ Software 10.0 (Linux)
NVIDIA DRIVE™ Software 9.0 (Linux)
other DRIVE OS version

Target Operating System
[*] Linux

Hardware Platform
[*] NVIDIA DRIVE™ AGX Xavier DevKit (E3550)
NVIDIA DRIVE™ AGX Pegasus DevKit (E3550)

SDK Manager Version

Host Machine Version

Hi everyone,
We are currently implementing a custom vio plug-in to send commands to our DBW module. Maybe you can help us with the following questions.

  1. When using a custom plug-in, we need to re-write the VIO back-end via implementing the pre-defined functions that are declared on `dw/control/vehicleio/plugins/VehicleIODriver.h’. In this case, I cannot see if there is any scope for functions “dwVehicleIO_selectDriverOverrides()” or “dwVehicleIO_setDrivingMode()”.
    In other words “DrivingMode” and “DriverOverrides” does not appear to have any effect when using a custom plug-in. Should we implement back end utility for those functions and how?

  2. When using a VIO plug-in back end, what level of functionality is maintained from the original VIO? For example, check documentation here (DriveWorks SDK Reference: VehicleIO Workflow). Some automatic engagement/disengagement conditions are described, along with additional functionality that from what I understand is not available or needs to be implemented from scratch on a VIO plug-in. What is in the end maintained and can be used from all those conditions described at section “VehicleIO Workflow” ?

  3. Usage of final .so library file.
    Is it possible to send user data to the VIO plug-in back end, ex some customer related data that is not abstracted in your dwVehicleIO_sendCommand() and dwVehicleIOCommand interface? I have found a work-around of opening and writing on the .so library using “dlopen” but maybe you have some more appropriate suggestion. It would be really helpful to expand the VIO plug-in prefixed interface to include random or customer data that are not included on the pre-defined plugin interface.

In general, I do not see much gain in using VIO plug-in backend vs writing new interface, custom structs, etc and then to communicate with the vehicle at SensorAbstructionLayer. Is there any particular argumentation or long term benefit into using the VIO plugin that I am missing?

Many thanks in advance

Dear @aathanas1,
Please confirm if you need to use DRIVE SW 10.0 for your development?

Hi, we will probably use Drive SW 10.0 although we are also at the moment evaluating upgrating to DW 3.5 or 4.0. There are a few differences into the VIO module in between versions but I believe the main benefits / options are more or less the same.

May I know what point did you notice? The two functions should be still related to dwVehicleIOState even if run with a custom VehicleIO backend.

Hi @VickNV

Let me give an example.

I have implemented my own VIO backend in order to transmit steering/throttle commands to the vehicle, via implementing “_dwVehicleIODriver_sendCommand” to send the specific CAN IDs. This function is passed a dwVehicleIOCommand type of variable, holding the related information from the rest of the program.

At first (initialization phase of the program) I successfully switch dwVehicleIODrivingMode to mode DW_VEHICLEIO_DRIVING_LIMITED which is supposed to clamp unsafe limits.
On top of that, see below, I expect that when I send “enable”, “throttleValid”, “steeringValid”, etc at False, vehicle actuation shouldnt happen.

I then pass a dwVehicleIOCommandthat holds these flags at False and tries to steer the car heavily, ex via holding very high rates at steeringValue / throttleValue.

Subsequently I observe that the commands are correctly passed to the CAN bus and no message is dropped.

I find this behaviour expected, since my VIO backend does not hold any information about max/min limits, safe ranges etc and on top there is no information outside the plugin (to DW core modules for example) about which is my steering msg ID or signal.

I therefore supposed that “DriverOverrides”, “DrivingMode” etc are somehow irrelevant or are missing additional backend implementation. But maybe I am using something wrongly or am missing something. What should I expect as default behaviour?

Do you see the issue with our sample vehicle plugin?
Please share dwVehicleIOState passed to your _dwVehicleIODriver_clearFaults() and dwVehicleIOCommand to _dwVehicleIODriver_sendCommand().

I haven’t yet implemented _dwVehicleIODriver_clearFaults() this is set at return DW_NOT_IMPLEMENTED which is in fact what your sample has as well.
With respect to dwVehicleIOCommand, I just modify the angle on pressing Left/Right Arrow keys to change to a very high rate ( ex
cmd.steeringWheelAngle -= STEERING_RATE;
cmd.steeringValid = 0;

with STEERING_RATE at something large, ex 300-400 degrees per sample

I also constantly include dwVehicleIOCommand.enable at false.

I haven’t fully tested your sample “vehicleio-plugin” since when running it, default data are passed onto the sample.

Can you please explain a bit what the expected behavior is, or what is in fact the effect of those driver-overrides / Modes, so that I can understand a bit better what I am missing.

For example, is it the case that if DW Vehicle IO gets a dwVehicleIOCommand with “enable” == 0 && throttleValue != 0, then vehicleio plugin backend will be terminated or skipped, resulting into dropping messages on the CAN bus?? What does the SW actually check or what is the functionality provided?

Many thanks for your support.

Are you referring to DRIVE Software 10? I can see below implementation.

dwStatus _dwVehicleIODriver_clearFaults(dwSensorHandle_t sensor, const dwVehicleIOState* state)
dwCANMessage msgCAN;
dwStatus status;

if (state->overrides & DW_VEHICLEIO_OVERRIDE_STEERING) {
    status = dwCANInterpreter_createMessageFromName(&msgCAN, GENERIC_MSG_STEERING_CMD, gIntp);
    if (status != DW_SUCCESS)
        return status;

    status = dwCANInterpreter_encodei32(true,
                                        &msgCAN, gIntp);
    if (status != DW_SUCCESS)
        return status;

status = dwSensorCAN_sendMessage(&msgCAN, 1000000, sensor);
return status;


Why do you send a command with “enable == 0”? Please refer to “VehicleIO Sample” for your implementation.

        if (m_cmd.enable)
           dwVehicleIO_sendCommand(&m_cmd, m_vehicleIO);

Yes you are right _dwVehicleIODriver_clearFaults, is implemented, I was mistaken with _dwVehicleIODriver_reset.

When is _dwVehicleIODriver_clearFaults function called from the main program? Is it any time a dwVehicleIOCommand with cmd.clearFaults = True is send via _dwVehicleIODriver_sendCommand ?

In general, I see through the documentation that the VehicleIO module provides some functionality though Driver-overrides and VehicleIODrivingMode and It is not clear what level of this functionality is provided by-default when using a vehicleIO backend custom plugin/driver and what needs to be implemented.

For example, as stated on “VehicleIO Workflow” (I am linking DW 3.5 but on SW 10.0 it is identical DriveWorks SDK Reference: VehicleIO Workflow):

“”"Once engaged, both Drive-By-Wire hardware and/or VehicleIO might decide to disable vehicle actuation (i.e. disengage), there are a few cases when this might happen:

  • Application-requested disengagement: dwVehicleIOCommand::enable is set to false.

In order to enable vehicle actuation (i.e. engage), several conditions must be satisfied:

  • dwVehicleIOCommand::enable must be set to true. “”"

This does not happen on my tests, since regardless of the flag being at false or true, VehicleIO module itself is not disabled, this is what I tested with enable = False && throttle !=0.


“”"In order to enable vehicle actuation (i.e. engage), several conditions must be satisfied:

  • Desired dwVehicleIOCommand::*Valid flags must be set to true, for example dwVehicleIOCommand::brakeValid to actuate vehicle braking.
  • All bits in dwVehicleIOState::faults must be clear. Recoverable faults can be cleared by sending a command with dwVehicleIOCommand::clearFaults set to true.“”"

Regardless of the flags being set to False or True, VehicleIO module itself is not disabled and whatever messages I have defined on _dwVehicleIODriver_sendCommand are executed when calling dwVehicleIO_sendCommand.

In general, the default interface of VIO module is a bit limiting for us since we want to transmit more information that what is defined on dwVehicleIOCommand / MiscCommand and rest interface. If those (or some) conditions described on “VehicleIO Workflow” are NOT available by default, or no particular functionality is provided from VIO apart from some ready data structs/enums/functions when using a custom plugin and each invididual (dis)engagement condition or safety limit need to be implemented, then we can just skip the VIO component all together and work with a CAN interpreter at SensorAbstructionLayer in order to free the interface to whatever we want.

If on the other hand, safety functionalities are provided by default on VIO module when using a custom plugin, that for ex. will disengage the entire VIO component and IO backend on certain dangerous situations, then we want to consider keeping it.

In the end, I am guessing that all those engagement, disengagement,etc conditions described on the documentation are only available by-default on the supported VIO types, ex DATASPEED and are not available on CUSTOM DBW systems.

Hi, do you have any other input on my questions?

Both dwVehicleIO_sendCommand() and dwVehicleIO_sendMiscCommand() invoke _dwVehicleIODriver_clearFaults() prior to sending out a command no matter.

For enagement/disenagement behaviors, let me discuss them with our team and get back to you. Thanks.

In the meantime, please refer to the source code of VehicleIO Sample to understand how it works and you may try it with your plugin.


Hello @VickNV and thanks for your reply.
Yes, I have studied that sample, it turns out that the key press “E”, “D” modify the control message, which in turn is checked upon sending the messages.

This means that “enable” or “disable” modes are not natively performed from VIO module, that will not disengage by itself, but it is upon the application to provide the functionality and the related checks.

This is exactly what I am trying to figure out, what native safety functionality is provided from VIO module, in order to decide if we can skip it or not. This sort of functionality (checking a flag and stoping message transmission) is something we can easily mimic ourselves at SensorAbstructionLayer without being restrictive from the VIO interface.

So far, the only native VIO functionality I have come across is that if m_cmd.clearFaults is set to True, function _dwVehicleIODriver_clearFaults() will be automatically triggered prior to sending any messages with dwVehicleIO_sendCommand() and dwVehicleIO_sendMiscCommand(). Regardless of clearFaults flag though the message transmission will again happen since the VIO component will not generally disengage.

Please let me know once you have more feedback from your team for the native (dis)engagement conditions, behaviour and potential safety functionality provided from the VIO module.

For dwVehicleIOCommand.enable, the plugin you implement must check the flag and flow the document not send out the command. That’s also handled by other drivers (e.g. dataspeed, generic).

For passing custom data, the plugin interface cannot be extended on a per-user basis. You can of course add more functions in the plugin and load them manually during runtime, but the plugin backend will not use them. You would need to call them independently of the predefined plugin interface functions.

Also you may take a look at “Vehicle Dynamics Controller” and “Architecture” (DRIVE_Software/Roadrunner/arch_vehicleDynamicsController.html and DRIVE_Software/Roadrunner/rr_architecture.html in DRIVE Software 10.0 Documentation respectively) to understand how the VDC module in Roadrunner, reference application in DRIVE AV, leverage DriveWorks VehicleIO. VDC functionalities may be what you need to implement on your side.