VRU Awareness Service

The VRU Awareness Service protects Vulnerable Road Users — pedestrians, cyclists, and other unprotected road users — by broadcasting their presence to nearby vehicles using VRU Awareness Messages (VAMs).

Note

The VRU Awareness Service implements ETSI TS 103 300-3 V2.2.1. VAMs are similar to CAMs but specifically designed for VRUs who need extra protection on the road.

What Are VRUs?

Vulnerable Road Users include anyone not protected by a vehicle body:

Type

Station Type

Examples

🚶 Pedestrian

1

Walkers, joggers, people with mobility aids

🚴 Cyclist

2

Bicycles, e-bikes, cargo bikes

🛵 Moped

3

Scooters, mopeds (< 50cc)

🏍️ Motorcycle

4

Motorcycles, motorbikes

🛴 Other

Various

E-scooters, skateboards, wheelchairs

VAM vs CAM

Aspect

CAM

VAM

For

Vehicles

Vulnerable Road Users

Purpose

Vehicle awareness

VRU protection

BTP Port

2001

2004

Clustering

No

Yes (groups of VRUs)

Device

Vehicle OBU

Smartphone, wearable, bike computer

Architecture

The VRU Awareness Service consists of several components:

        flowchart TB
   subgraph APP["Application Layer"]
      EX["Application"]
   end
   subgraph "Facilities Layer"
      LDM[(Local Dynamic Map)]
      subgraph VRUAW["VRU Awareness Service"]
         direction LR
         RM[Reception<br/>Management] ~~~ TM[Transmission<br/>Management]
         TM ~~~ CM[Cluster Management<br/>⚠️ Not Implemented]
      end

   end

   subgraph "Location"
      LOC[Location Service]
   end

   subgraph "Transport"
      BTP[BTP Router<br/>Port 2018]
   end
   APP --- LDM
   LDM ---|"Store Received"| VRUAW
   LOC -->|"Position Updates"| VRUAW
   VRUAW <-->|"Facilities-BTP SAP"| BTP


   style VRUAW fill:#fff3e0,stroke:#f57c00
   style LDM fill:#e8f5e9
   style CM fill:#ffebee,stroke:#c62828,stroke-dasharray: 5 5
    

Components:

Component

Description

VRU Basic Service

Main service coordinating all VAM operations

VAM Transmission Management

Handles when and how VAMs are sent

VAM Reception Management

Processes incoming VAMs (automatic)

Cluster Management

Groups nearby VRUs (⚠️ not yet implemented)

VAM Coder

Encodes/decodes ASN.1 format

Device Data Provider

Provides VRU device information


Getting Started

Step 1: Configure Device Data Provider

Unlike vehicles (which use VehicleData), VRUs use a DeviceDataProvider:

from flexstack.facilities.vru_awareness_service.vam_transmission_management import (
    DeviceDataProvider,
)

# Configure VRU device
device_data = DeviceDataProvider(
    station_id=12345,      # Unique identifier
    station_type=2,        # 2 = Cyclist
)

Station Types for VRUs:

Value

Type

Description

1

Pedestrian

Person on foot

2

Cyclist

Bicycle rider

3

Moped

Light motorized two-wheeler

4

Motorcycle

Motorcycle rider

Step 2: Set Up Prerequisites

The VRU Awareness Service requires:

  • BTP Router — for transport (port 2004)

  • Location Service — for position updates

from flexstack.btp.router import Router as BTPRouter
from flexstack.geonet.router import Router as GNRouter
from flexstack.geonet.mib import MIB
from flexstack.geonet.gn_address import GNAddress, M, ST, MID
from flexstack.utils.static_location_service import ThreadStaticLocationService as LocationService
from flexstack.linklayer.raw_link_layer import RawLinkLayer

MAC_ADDRESS = b'\x00\x11\x22\x33\x44\x55'

# Location Service
location_service = LocationService()

# GeoNetworking + BTP
mib = MIB(
    itsGnLocalGnAddr=GNAddress(
        m=M.GN_MULTICAST,
        st=ST.CYCLIST,  # VRU type
        mid=MID(MAC_ADDRESS),
    ),
)
gn_router = GNRouter(mib=mib, sign_service=None)
ll = RawLinkLayer(iface="lo", mac_address=MAC_ADDRESS, receive_callback=gn_router.gn_data_indicate)
gn_router.link_layer = ll
btp_router = BTPRouter(gn_router)
gn_router.register_indication_callback(btp_router.btp_data_indication)
location_service.add_callback(gn_router.refresh_ego_position_vector)

Step 3: Create VRU Awareness Service

from flexstack.facilities.vru_awareness_service.vru_awareness_service import (
    VRUAwarenessService,
)

# Create the VRU Awareness Service
vru_service = VRUAwarenessService(
    btp_router=btp_router,
    device_data_provider=device_data,
)

# Connect location updates to trigger VAM transmission
location_service.add_callback(
    vru_service.vam_transmission_management.location_service_callback
)

That’s it! The service will now:

  • Automatically send VAMs when location updates arrive

  • Automatically receive VAMs from other VRUs


VAM Generation Rules

VAMs are generated when any of these conditions are met:

Trigger

Condition

⏱️ Time elapsed

Time since last VAM exceeds T_GenVamMax

📍 Position change

Distance moved exceeds minReferencePointPositionChangeThreshold

🏃 Speed change

Speed difference exceeds minGroundSpeedChangeThreshold

🧭 Direction change

Heading change exceeds minGroundVelocityOrientationChangeThreshold

This ensures VAMs are sent when relevant changes occur, not just periodically.


VAM Message Structure

A VAM contains information specific to VRUs:

        flowchart LR
   subgraph CAM["Vulnerable Road User (VRU) Awareness Message (VAM)"]
   direction LR
   header["ITS PDU Header"]
   basic["Basic Container"]
   HF["High Frequency Container"]
   LF["Low Frequency Container (optional)"]
   CL["Cluster Information Container (optional)"]
   CLOP["Cluster Operation Container (optional)"]
   MOT["Motion Prediction Container (optional)"]
   header ~~~ basic
   basic ~~~ HF
   HF ~~~ LF
   LF ~~~ CL
   CL ~~~ CLOP
   CLOP ~~~ MOT
   end
    

Container

Contents

Basic

VRU type, reference position

High Frequency

Speed, heading, acceleration (sent often)

Low Frequency

Profile info, path history (sent less often)

Cluster

Info about grouped VRUs (when clustering is active)


VRU Clustering

Warning

VRU Clustering is not yet implemented in FlexStack.

Clustering allows multiple VRUs traveling together (e.g., a group of cyclists) to be represented by a single VAM, reducing network load while maintaining awareness.

        flowchart LR
    subgraph "Without Clustering"
        V1[VAM 1]
        V2[VAM 2]
        V3[VAM 3]
        V4[VAM 4]
    end

    subgraph "With Clustering"
        VC[Cluster VAM<br/>4 VRUs]
    end

    V1 & V2 & V3 & V4 -.->|"Future"| VC
    

Complete Example

Here’s a complete script for a cyclist broadcasting VAMs:

 1#!/usr/bin/env python3
 2"""
 3VRU Awareness Service Example
 4
 5Broadcasts VAMs for a cyclist to alert nearby vehicles.
 6Run with: sudo python vru_example.py
 7"""
 8
 9import logging
10import random
11import time
12
13from flexstack.linklayer.raw_link_layer import RawLinkLayer
14from flexstack.geonet.router import Router as GNRouter
15from flexstack.geonet.mib import MIB
16from flexstack.geonet.gn_address import GNAddress, M, ST, MID
17from flexstack.btp.router import Router as BTPRouter
18from flexstack.utils.static_location_service import ThreadStaticLocationService
19from flexstack.facilities.vru_awareness_service.vru_awareness_service import (
20    VRUAwarenessService,
21)
22from flexstack.facilities.vru_awareness_service.vam_transmission_management import (
23    DeviceDataProvider,
24)
25
26logging.basicConfig(level=logging.INFO)
27
28# Configuration
29POSITION = [41.386931, 2.112104]  # Barcelona
30MAC_ADDRESS = bytes([(random.randint(0, 255) & 0xFE) | 0x02] +
31                    [random.randint(0, 255) for _ in range(5)])
32STATION_ID = random.randint(1, 2147483647)
33
34
35def main():
36    # Location Service
37    location_service = ThreadStaticLocationService(
38        period=1000,
39        latitude=POSITION[0],
40        longitude=POSITION[1],
41    )
42
43    # GeoNetworking
44    mib = MIB(
45        itsGnLocalGnAddr=GNAddress(
46            m=M.GN_MULTICAST,
47            st=ST.CYCLIST,  # This is a cyclist
48            mid=MID(MAC_ADDRESS),
49        ),
50    )
51    gn_router = GNRouter(mib=mib, sign_service=None)
52    location_service.add_callback(gn_router.refresh_ego_position_vector)
53
54    # BTP
55    btp_router = BTPRouter(gn_router)
56    gn_router.register_indication_callback(btp_router.btp_data_indication)
57
58    # VRU Awareness Service
59    device_data = DeviceDataProvider(
60        station_id=STATION_ID,
61        station_type=2,  # Cyclist
62    )
63    vru_service = VRUAwarenessService(
64        btp_router=btp_router,
65        device_data_provider=device_data,
66    )
67    location_service.add_callback(
68        vru_service.vam_transmission_management.location_service_callback
69    )
70
71    # Link Layer
72    btp_router.freeze_callbacks()
73    link_layer = RawLinkLayer(
74        "lo",
75        MAC_ADDRESS,
76        receive_callback=gn_router.gn_data_indicate,
77    )
78    gn_router.link_layer = link_layer
79
80    print("✅ VRU Awareness Service running!")
81    print("🚴 Broadcasting VAMs as a cyclist...")
82    print("Press Ctrl+C to exit\n")
83
84    try:
85        while True:
86            time.sleep(1)
87    except KeyboardInterrupt:
88        print("\n👋 Shutting down...")
89
90    location_service.stop_event.set()
91    location_service.location_service_thread.join()
92    link_layer.sock.close()
93
94
95if __name__ == "__main__":
96    main()

Use Cases

🚴 Cyclist Safety

Cyclists broadcast their position to nearby vehicles, reducing collision risk at intersections and blind spots.

🚶 Pedestrian Crossing

Pedestrians with smartphones can alert approaching vehicles when crossing streets.

🛴 E-Scooter Awareness

Electric scooter riders share their presence with traffic, especially important in urban environments.

🏍️ Motorcycle Visibility

Motorcyclists increase their visibility to cars and trucks that might not see them.


See Also