GVA Vehicle Simulator

![Vehicle Simulator Third Person View](../images/vehicle-sim/vehicle-sim-third-person.png) **OpenDRIVE 3D Vehicle Simulator with J1939 CAN Integration** *Real-time vehicle dynamics simulation for GVA testing and development* [Get Started](#quick-start) | [Features](#key-features) | [Controls](#vehicle-controls) | [Documentation](#detailed-documentation)

Hardware-in-the-Loop Testing Without the Hardware

The GVA Vehicle Simulator (gva-qt6-vehicle-sim) is a comprehensive 3D vehicle simulation platform designed specifically for military vehicle systems testing and development. Built with Qt6, Qt3D, and C++17, it provides realistic vehicle dynamics, J1939 CAN bus message generation, and DDS integration for the full GVA ecosystem.

Why Vehicle Simulator?

Challenge Simulator Solution
💰 Expensive Physical Testing Virtual testing on standard workstations
Long Development Cycles Instant feedback without vehicle setup
🔄 Limited Test Scenarios Infinite reproducible test conditions
📊 Integration Validation End-to-end CAN → DDS → Application testing
🎮 Realistic Operator Training Safe training environment with actual controls

Key Features

🚗 Realistic Vehicle Dynamics

  • Physics-Based Simulation - Acceleration, braking, steering with realistic constraints
  • Manual 6-Speed Transmission - Full clutch and gear shift simulation
  • Automatic Transmission Mode - Optional automatic gear changes
  • 4x4 Transfer Case - High/Low range selection
  • Logitech G29 Support - Force feedback racing wheel integration

🗺️ OpenDRIVE Road Networks

Load and navigate real-world proving grounds with ASAM OpenDRIVE 1.8.1 support:

Vehicle Simulator Top-Down View

  • ZalaZONE Proving Ground (Hungary) - 579 roads, 76 junctions
  • Lane-accurate positioning - Follow realistic road geometry
  • Traffic signs & signals - Speed limits, stop signs, direction indicators
  • Road markings - Solid/dashed lines, crosswalks, stop lines
  • Junction navigation - Priority signs, turn arrows, yield markings

📡 J1939 CAN Bus Generation

Generates authentic SAE J1939 messages over SocketCAN for hardware integration:

Supported PGNs (15 Active)

PGN Name Rate Key Parameters
61444 EEC1 - Engine Controller 100ms Engine speed (RPM), torque
65265 CCVS - Vehicle Speed 100ms Wheel speed, brake/clutch switches
61445 ETC2 - Transmission 100ms Current/selected gear, clutch position
65267 VP - Vehicle Position 250ms GPS latitude/longitude
65256 VDS - Direction/Speed 250ms Heading, speed over ground
65262 ET1 - Engine Temperature 1s Coolant, fuel, oil temperature
65263 EFLP - Fluid Levels 500ms Fuel level, oil pressure
61449 VDC2 - Vehicle Dynamics 100ms Steering angle, yaw rate
65271 VEP1 - Electrical Power 1s Battery/alternator voltage
65269 AMB - Ambient Conditions 1s Air temperature, barometric pressure

Total: 33 SPNs (Suspect Parameter Numbers) actively simulated

🔊 FM Synthesis Engine Sound

  • Real-time audio - FM synthesis engine sounds based on RPM
  • Dynamic mixing - Engine load and throttle position affect sound
  • Gear transitions - Audio feedback for shifts

🎥 Multiple Camera Modes

Cycle through different perspectives with C key:

Vehicle Simulator Drive Along View

  1. Third-Person Chase Cam - Follow vehicle from behind
  2. Top-Down Strategic View - Overhead tactical perspective
  3. Drive-Along Side View - Parallel tracking camera
  4. First-Person Driver View - Cockpit perspective (planned)

🌐 DDS Integration

Publishes vehicle parameters to GVA DDS topics on J1939_Automotive domain:

  • J1939_Automotive__Parameter - Real-time SPN values
  • J1939_Automotive__Parameter_Group_Definition - PGN metadata
  • J1939_Automotive__Data_Source - Simulator status

Quick Start

1. Build the Simulator

cd /home/newman/repos/ldm/build
cmake ..
make gva-qt6-vehicle-sim -j $(nproc)

2. Setup Virtual CAN Interface

# Load kernel module
sudo modprobe vcan

# Create vcan0 interface
sudo ip link add dev vcan0 type vcan
sudo ip link set vcan0 up

# Verify interface
ip link show vcan0

Or use the provided script:

sudo scripts/test/j1939/setup-vcan.sh

3. Launch with OpenDRIVE Map

./build/bin/gva-qt6-vehicle-sim \
  --domain=0 \
  --map=data/opendrive/ZalaZONE_full.xodr \
  --fullscreen

4. (Optional) Start J1939 Gateway

Bridge CAN to DDS for monitoring in LDMX or GVA HMI:

./build/bin/gva-j1939-gateway \
  --domain=0 \
  --interface=vcan0 \
  --config=/etc/gva/j1939-config.json

5. Monitor with LDMX

./build/bin/ldmx
# Navigate to J1939 tab to see live parameters

Vehicle Controls

Keyboard (Default - No G29)

Key Function Notes
W / Throttle Increase engine power
S / Brake Apply brakes
A / Steer Left Turn left
D / Steer Right Turn right
Space Clutch Hold for gear changes
Q Shift Down Requires clutch
E Shift Up Requires clutch
I Toggle Ignition Start/stop engine
P Parking Brake Lock rear wheels
T Transfer Case Toggle 4H/4L
C Cycle Camera Switch view modes
R Reset Position Return to spawn point
F11 Toggle Fullscreen Maximize window
Esc Exit Close simulator

Logitech G29 Racing Wheel

When detected, G29 automatically overrides keyboard controls:

Control Function
Steering Wheel Vehicle steering with force feedback
Gas Pedal Throttle input (0-100%)
Brake Pedal Brake pressure (0-100%)
Clutch Pedal Clutch engagement
Paddle Shifters Quick up/down shift
Gear Shifter Direct gear selection (if H-pattern)
Action Key Description
Toggle Sim I (in menu) Start/pause simulation
Reset Sim R (in menu) Reset to start position
Exit FileExit Close application

Command Line Options

gva-qt6-vehicle-sim [OPTIONS]

Options:
  -h, --help               Display help information
  --version                Display version information
  -d, --domain <id>        DDS domain ID (default: 0)
  -m, --map <filepath>     OpenDRIVE (.xodr) map file to load
  -f, --fullscreen         Start in fullscreen mode
  --device <path>          G29 input device path (default: auto-detect)

Examples

# Launch with ZalaZONE map on DDS domain 0
./gva-qt6-vehicle-sim --domain=0 --map=data/opendrive/ZalaZONE_full.xodr

# Fullscreen mode with custom G29 device
./gva-qt6-vehicle-sim --fullscreen --device=/dev/input/event5

# Headless mode for CI testing (no GUI)
./gva-qt6-vehicle-sim --domain=0 --headless

Configuration

Vehicle Parameters

The simulator uses realistic military vehicle characteristics:

{
  "vehicle": {
    "type": "8x8 Military Transport",
    "mass_kg": 24000,
    "wheelbase_m": 6.5,
    "max_speed_kmh": 120,
    "max_rpm": 2800,
    "idle_rpm": 800,
    "gear_ratios": [4.71, 2.84, 1.87, 1.38, 1.00, 0.76],
    "reverse_ratio": -5.10,
    "final_drive": 4.88,
    "transfer_case": {
      "high_ratio": 1.00,
      "low_ratio": 2.64
    },
    "max_steering_angle_deg": 45,
    "brake_force_N": 120000,
    "engine_max_torque_Nm": 2300
  }
}

J1939 Configuration

Modify J1939 output parameters:

{
  "j1939": {
    "enabled": true,
    "can_interface": "vcan0",
    "source_address": 0,
    "gateway_resource_id": 1000,
    "update_rates": {
      "engine_hz": 10,
      "vehicle_speed_hz": 10,
      "transmission_hz": 10,
      "position_hz": 4,
      "temperature_hz": 1
    }
  }
}

GPS Origin (ZalaZONE)

Default GPS coordinates:

  • Latitude: 46.8780°N
  • Longitude: 16.8439°E
  • Altitude: 175m above sea level

All vehicle positions are calculated relative to this origin.


Architecture

Data Flow

graph LR A[Physics Engine] -->|Vehicle State| B[J1939 Encoder] B -->|CAN Frames| C[SocketCAN vcan0] C -->|Read| D[J1939 Gateway] D -->|DDS Topics| E[LDMX/HMI] A -->|Position/Speed| F[3D Renderer] F -->|Qt3D| G[Display] H[Keyboard/G29] -->|Input Events| A style A fill:#012141,stroke:#0072FF,color:#00FFFF style B fill:#0a3a5c,stroke:#0072FF,color:#00FFFF style D fill:#0a3a5c,stroke:#0072FF,color:#00FFFF

Component Architecture

classDiagram class VehicleSimulator { +double m_speed +double m_rpm +int m_gear +QVector3D m_position +updatePhysics(dt) +publishJ1939Parameters() } class J1939CanSender { +QString m_interface +int m_socket +sendEEC1(rpm, torque) +sendCCVS(speed, brake) +sendVP(lat, lon) } class CircuitView3D { +Qt3DCore::QEntity* m_rootEntity +QCamera* m_camera +loadOpenDrive(path) +updateVehiclePosition(pos) } class OpenDriveLoader { +odr::OpenDriveMap m_map +loadFile(path) +generateRoadMesh() +generateLaneMarkings() } class SimulationWindow { +QTimer* m_updateTimer +setupUi() +onUpdateTimerTick() } VehicleSimulator --> J1939CanSender : uses VehicleSimulator --> CircuitView3D : updates SimulationWindow --> VehicleSimulator : owns CircuitView3D --> OpenDriveLoader : uses

Integration Examples

1. HMI Dashboard Development

Test vehicle instrument cluster without physical vehicle:

// Subscribe to vehicle speed in your HMI
auto subscriber = std::make_unique<QtDdsSubscriberCParameter>(
    domainId, "J1939_Automotive__Parameter");

connect(subscriber.get(), &QtDdsSubscriberCParameter::OnSampleReceived,
    [](const P_J1939_Automotive_PSM::C_Parameter& param) {
        if (param.A_suspectParameterNumber() == 84) {  // SPN 84 = Vehicle Speed
            double speedKmh = param.A_value();
            updateSpeedometer(speedKmh);
        }
    });

2. CAN Bus Testing

Monitor raw CAN frames with candump:

# Terminal 1: Run simulator
./gva-qt6-vehicle-sim --domain=0

# Terminal 2: Monitor CAN traffic
candump vcan0 -t A

# Output example:
#  (000.123456)  vcan0  18F00400   [8]  00 7D 7D 20 19 FF FF FF  # EEC1: 800 RPM
#  (000.223456)  vcan0  18FEF100   [8]  FF 00 00 C0 FF FF FF FF  # CCVS: 0 km/h

3. Automated Testing

Scripted test scenarios for CI/CD:

#!/bin/bash
# Start simulator in background
./gva-qt6-vehicle-sim --domain=0 --headless &
SIM_PID=$!

# Wait for initialization
sleep 2

# Start gateway
./gva-j1939-gateway --domain=0 --interface=vcan0 &
GW_PID=$!

# Run test suite
python3 scripts/test/validate_j1939_output.py

# Cleanup
kill $SIM_PID $GW_PID

Performance Characteristics

Metric Value Notes
Frame Rate 60 FPS Locked to 60Hz update loop
Physics Update 60 Hz Fixed timestep simulation
CAN Frame Rate 10-100 Hz Per PGN (configurable)
DDS Latency < 5 ms Local publish/subscribe
CPU Usage < 10% 4-core Intel i7, single vehicle
Memory ~200 MB With ZalaZONE map loaded
GPU Integrated OK OpenGL 3.3+ required

Supported J1939 Messages

✅ Implemented (15 PGNs, 33 SPNs)

Fully simulated with realistic values:

  • Engine: RPM, torque, load, coolant/oil/fuel temps, hours
  • Transmission: Gear selection, clutch position
  • Vehicle Speed: Wheel-based, speed over ground
  • Position: GPS lat/lon, altitude, heading, course
  • Dynamics: Steering angle, yaw rate
  • Electrical: Battery/alternator voltage
  • Ambient: Air temperature, barometric pressure
  • Fuel: Level, rate, economy

🔲 Not Implemented (22 PGNs)

Future enhancements:

  • ABS/Brakes: Individual wheel control (EBC1/2/3)
  • TPMS: Tire pressure monitoring
  • Emissions: DPF, NOx sensors (AT1I/O)
  • Advanced Trans: ETC1 shift-in-progress
  • Odometer: High-resolution distance (VDIST)

Troubleshooting

Common Issues

Simulator Won't Start

# Check Qt6 installation
pkg-config --modversion Qt6Core

# Verify OpenGL support
glxinfo | grep "OpenGL version"

# Check for missing libraries
ldd ./build/bin/gva-qt6-vehicle-sim

No CAN Output

# Verify vcan0 exists
ip link show vcan0

# Check for SocketCAN errors in logs
journalctl -xe | grep socketcan

# Recreate vcan0
sudo ip link delete vcan0
sudo ip link add dev vcan0 type vcan
sudo ip link set vcan0 up

G29 Not Detected

# List input devices
ls -l /dev/input/by-id/ | grep Logitech

# Check permissions
sudo chmod 666 /dev/input/event*

# Test with evtest
sudo evtest /dev/input/event5

Low Frame Rate

  • Reduce map complexity: Use smaller OpenDRIVE files
  • Disable advanced features: Turn off shadows, reflections
  • Lower resolution: Run in windowed mode at 1280x720
  • Update graphics drivers: Ensure OpenGL 4.x support

Development

Building from Source

# Install dependencies (Ubuntu 22.04)
sudo apt install qt6-base-dev qt6-3d-dev libqt6opengl6-dev

# Configure build
cd /home/newman/repos/ldm
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..

# Build simulator
make gva-qt6-vehicle-sim -j $(nproc)

Adding New PGNs

  1. Define PGN constant in J1939CanSender.h:
static constexpr uint32_t PGN_NEW_MESSAGE = 65280;
  1. Implement encoder in J1939CanSender.cpp:
bool J1939CanSender::sendNewMessage(double param1, double param2) {
    uint8_t data[8] = {0};
    // Encode according to J1939 spec
    uint16_t scaled = static_cast<uint16_t>(param1 * 256);
    data[0] = scaled & 0xFF;
    data[1] = (scaled >> 8) & 0xFF;
    return sendPgn(PGN_NEW_MESSAGE, data, 8, 6);
}
  1. Call from VehicleSimulator::publishJ1939Parameters():
m_j1939Sender->sendNewMessage(m_customParam1, m_customParam2);

Comparison: Physical vs. Simulated

Aspect Physical Vehicle Simulator
Cost $50,000+ $0 (software)
Setup Time Hours Minutes
Safety Risk High None
Reproducibility Poor Perfect
Scenario Control Limited Complete
Parallel Testing 1 vehicle Unlimited instances
Weather/Terrain Real-world limits Any condition
Data Logging Requires equipment Built-in

Use Cases

🎯 HMI Development

  • Test speedometer, tachometer, gear indicators
  • Validate warning lights and alarms
  • Prototype new dashboard layouts

🔬 Algorithm Testing

  • Eco-driving algorithms (fuel economy optimization)
  • Predictive maintenance (engine hours, oil pressure)
  • Autonomous navigation (GPS waypoint following)

📊 Integration Validation

  • End-to-end CAN → DDS → Application flow
  • Multi-subsystem synchronization
  • Gateway performance under load

🎓 Training & Education

  • Operator training in safe environment
  • Customer demonstrations without vehicle
  • Teaching tool for GVA architecture

🚀 CI/CD Automation

  • Automated regression testing
  • Continuous integration builds
  • Performance benchmarking

References


Future Enhancements

  • [ ] Multiplayer Support - Network simulation with multiple vehicles
  • [ ] Physics Improvements - Advanced suspension, tire slip, terrain deformation
  • [ ] Weather System - Rain, fog, snow affecting handling
  • [ ] Traffic Simulation - AI-controlled civilian vehicles
  • [ ] Mission Scripting - Automated test scenarios
  • [ ] VR Support - Virtual reality cockpit view
  • [ ] Hardware CAN - Real CAN interface (can0) support
  • [ ] Record/Replay - Save and replay driving sessions
  • [ ] CARLA Integration - Import CARLA maps and sensors

Last Updated: January 31, 2026
GVA LDM SDK Version: 10.0.0
Author: Astute Systems PTY LTD