Moved to https://git.opendlv.org.
OpenDLV is a modern open source software environment to support the development and testing of self-driving vehicles driven by the following design principles:
amd64
, armhf
, and aarch64
Applications based on OpenDLV are grouped in UDP multicast sessions
belonging to IPv4 address 225.0.0.X
, where X is from the within the range
[1,254]
. All microservices belonging to the same UDP multicast group are
able to communicate with each other; thus, two applications running in different
UDP multicast sessions do not see each other and are completely separated.
The actual UDP multicast session is selected using the commandline parameter
--cid=111
, where 111
would define the UDP multicast address 225.0.0.111
.
Microservices exchange data using the message Envelope
that contains besides the actual message to send further meta information
like sent and received timestamp and the point in time when the contained
message was actually sampled. All messages are encoded in
Google's Protobuf data
format (example) that has
been adjusted to preserve forwards and backwards compatibility using
libcluon's native implementation
of Protobuf.
An Envelope
contains in its field serializedData
the actually message
to be exchanged that is encoded in Protobuf. Furthermore, the Envelope
itself is also encoded in Protobuf but prepended with the byte sequence
0x0D 0xA4
as magic number, followed by three bytes 0xXX 0xYY 0xZZ
describing the length in bytes of the Protobuf-encoded Envelope
. The
sequence 0xA4 0xXX 0xYY 0xZZ
is encoded in little endian and 0xZZ
is usually 0 in practice.
As participants in a UDP multicast session automatically receive any exchanged
Envelope
s, a receiver can differentiate what message to expect by checking
Envelope
's field dataType,
which is referring to a message identifier (for instance, Envelope
's
message identifier
is 1).
OpenDLV's microservices conform to the OpenDLV Standard Message Set that enables exchangeability across
hardware/software interfaces to decouple high-level application logic from
low-level device drivers. For instance, OpenDLV's hardware/software interface to
access an Applanix GPS unit is called opendlv-device-gps-pos
according to Applanix' internal data format POS that is used across several
units in their product portfolio. The microservice opendlv-device-gps-pos
provides GPS information in messages GeodeticWgs84Reading
and GeodeticHeadingReading
.
As the microservices for the various GPS units (like, for instance Trimble and
Applanix) all broadcast the aforementioned messages, the hardware units can be
exchanged transparently for the high-level application logic. However, when
several GPS units shall be operated in parallel, it is necessary to distinguish
between them. Therefore, the commandline parameter --id=Y
can be provided,
where Y is a positive number to differentiate between messages of the
same type. At the receiving end, the value Y is made available in Envelope
's
field senderStamp
. As an example, when using an Applanix unit next to a
Trimble unit, the respective microservices could be supplied with the suffixes
--id=1
and --id=2
.
You need a C++14-compliant compiler to compile this project as it ships the following dependencies as part of the source distribution:
For building cluon-rec2fuse, libfuse is required.
We are providing the following microservices as multi-platform (amd64/x86_64, armhf, aarch64) Docker images:
Complete ArchLinux-based OpenDLV OS Operating System (start here if you want to initialize a blank computing unit - WARNING! All data will be erased!)
docker run --rm -ti --init --net=host --device /dev/input/js0 chalmersrevere/opendlv-device-gamepad-multi:v0.0.10 --device=/dev/input/js0 --axis_leftright=0 --axis_updown=3 --freq=100 --acc_min=0 --acc_max=50 --dec_min=0 --dec_max=-10 --steering_min=-10 --steering_max=10 --steering_max_rate=5.0 --cid=111 --verbose
docker run --rm -ti --init --net=host --device /dev/input/js0 chalmersrevere/opendlv-device-gamepad-multi:v0.0.10 --device=/dev/input/js0 --axis_leftright=0 --axis_updown=4 --freq=100 --acc_min=0 --acc_max=50 --dec_min=0 --dec_max=-10 --steering_min=-10 --steering_max=10 --steering_max_rate=5.0 --cid=111 --verbose
docker-compose.yml
for PS3 controllers:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-ps3controller:
container_name: dev-ps3controller
image: chalmersrevere/opendlv-device-gamepad-multi:v0.0.10
restart: on-failure
network_mode: "host"
devices:
- "/dev/input/js0:/dev/input/js0"
command: "--device=/dev/input/js0 --axis_leftright=0 --axis_updown=3 --freq=100 --acc_min=0 --acc_max=50 --dec_min=0 --dec_max=-10 --steering_min=-10 --steering_max=10 --steering_max_rate=5.0 --cid=111"
docker-compose.yml
for PS4 controllers:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-ps4controller:
container_name: dev-ps4controller
image: chalmersrevere/opendlv-device-gamepad-multi:v0.0.10
restart: on-failure
network_mode: "host"
devices:
- "/dev/input/js0:/dev/input/js0"
command: "--device=/dev/input/js0 --axis_leftright=0 --axis_updown=4 --freq=100 --acc_min=0 --acc_max=50 --dec_min=0 --dec_max=-10 --steering_min=-10 --steering_max=10 --steering_max_rate=5.0 --cid=111"
docker run --init --rm --net=host chalmersrevere/opendlv-device-gps-pos-multi:v0.0.11 --pos_ip=192.168.1.77 --pos_port=5602 --cid=111 --verbose
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-gps-pos:
container_name: dev-gps-pos
image: chalmersrevere/opendlv-device-gps-pos-multi:v0.0.11
restart: on-failure
network_mode: "host"
command: "--pos_ip=10.42.42.40 --pos_port=5602 --cid=111"
docker run --init --rm --net=host chalmersrevere/opendlv-device-gps-ncom-multi:v0.0.17 --ncom_ip=0.0.0.0 --ncom_port=3000 --cid=111 --verbose
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-gps-ncom:
container_name: dev-gps-ncom
image: chalmersrevere/opendlv-device-gps-ncom-multi:v0.0.17
restart: on-failure
network_mode: "host"
command: "--ncom_ip=0.0.0.0 --ncom_port=3000 --cid=111"
docker run --init --rm --net=host --privileged chalmersrevere/opendlv-device-gps-peak-multi:v0.0.8 --can=can0 --cid=111 --verbose
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-gps-peak:
container_name: dev-gps-peak
image: chalmersrevere/opendlv-device-gps-peak-multi:v0.0.8
restart: on-failure
network_mode: "host"
privileged: true
command: "--can=can0 --cid=111"
docker run --init --rm --net=host chalmersrevere/opendlv-device-gps-nmea-multi:v0.0.14 --nmea_ip=10.42.42.112 --nmea_port=9999 --cid=111 --verbose
docker run --init --rm --net=host chalmersrevere/opendlv-device-gps-nmea-multi:v0.0.14 --udp --nmea_ip=0.0.0.0 --nmea_port=9999 --cid=111 --verbose
docker-compose.yml
(to connect to a TCP server):
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-gps-nmea:
container_name: dev-gps-nmea
image: chalmersrevere/opendlv-device-gps-nmea-multi:v0.0.14
restart: on-failure
network_mode: "host"
command: "--nmea_ip=10.42.42.112 --nmea_port=9999 --cid=111"
docker-compose.yml
(to let this microservice listen for UDP packets):
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-gps-nmea:
container_name: dev-gps-nmea
image: chalmersrevere/opendlv-device-gps-nmea-multi:v0.0.14
restart: on-failure
network_mode: "host"
command: "--udp --nmea_ip=0.0.0.0 --nmea_port=9999 --cid=111"
docker run --init --rm --net=host chalmersrevere/opendlv-device-lidar-hdl32e-multi:v0.0.14 --hdl32e_ip=0.0.0.0 --hdl32e_port=2368 --cid=111 --verbose
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-lidar-hdl32e:
container_name: dev-lidar-hdl32e
image: chalmersrevere/opendlv-device-lidar-hdl32e-multi:v0.0.14
restart: on-failure
network_mode: "host"
command: "--hdl32e_ip=0.0.0.0 --hdl32e_port=2368 --nogpstime --cid=111"
docker run --init --rm --net=host chalmersrevere/opendlv-device-lidar-vlp32c-multi:v0.0.3 --vlp32c_ip=0.0.0.0 --vlp32c_port=2368 --cid=111 --verbose
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-lidar-vlp32c:
container_name: dev-lidar-vlp32c
image: chalmersrevere/opendlv-device-lidar-vlp32c-multi:v0.0.3
restart: on-failure
network_mode: "host"
command: "--vlp32c_ip=0.0.0.0 --vlp32c_port=2368 --cid=111"
docker run --init --rm --net=host chalmersrevere/opendlv-device-lidar-vlp16-multi:v0.0.10 --vlp16_ip=0.0.0.0 --vlp16_port=2368 --cid=111 --verbose
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-lidar-vlp16c:
container_name: dev-lidar-vlp16c
image: chalmersrevere/opendlv-device-lidar-vlp16-multi:v0.0.10
restart: on-failure
network_mode: "host"
command: "--vlp16_ip=0.0.0.0 --vlp16_port=2368 --cid=111"
docker run --init --rm --net=host chalmersrevere/opendlv-device-lidar-rplidar-multi:v0.0.4 --device=/dev/ttyUSB0 --cid=111 --verbose
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-lidar-rplidar:
container_name: dev-lidar-rplidar
image: chalmersrevere/opendlv-device-lidar-rplidar-multi:v0.0.4
restart: on-failure
network_mode: "host"
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
command: "--device=/dev/ttyUSB0 --cid=111"
docker run --rm -ti --net=host --privileged --device=/dev/i2c-1 chalmersrevere/opendlv-device-ultrasonic-srf08-multi:v0.0.10 opendlv-device-ultrasonic-srf08 --dev=/dev/i2c-1 --bus-address=112 --cid=111 --freq=5 --id=0
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-ultrasonic-srf08:
container_name: dev-ultrasonic-srf08
image: chalmersrevere/opendlv-device-ultrasonic-srf08-multi:v0.0.10
restart: on-failure
network_mode: "host"
privileged: true
devices:
- "/dev/i2c-1:/dev/i2c-1"
command: "opendlv-device-ultrasonic-srf08 --dev=/dev/i2c-1 --bus-address=112 --cid=111 --freq=5 --range=100 --gain=1 --id=0 --cid=111"
OpenDLV contains a highly modular and easy-to-use framework to grab video frames from various cameras, share them via shared memory, and encode/decode them into h264 frames to broadcast into an OD4Session for OpenDLV. The microservices are divided into video sources (e.g., opendlv-device-camera-v4l, opendlv-device-camera-opencv, opendlv-device-camera-ueye), or opendlv-device-camera-rpi) and video sinks (e.g., opendlv-video-h264-encoder) to process incoming video frames. Video sinks provide frames in two image formats: I420-encoded image and ARGB. The former format can be directly used for video compression (e.g., h264 encoding), while the latter can be directly used for image detection algorithms (opendlv-examples).
docker run --rm -ti --init --ipc=host -v /tmp:/tmp -e DISPLAY=$DISPLAY --device /dev/video0 chalmersrevere/opendlv-device-camera-v4l-multi:v0.0.8 --camera=/dev/video0 --width=640 --height=480 --freq=20 --verbose
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-camera-v4l:
container_name: dev-camera-v4l
image: chalmersrevere/opendlv-device-camera-v4l-multi:v0.0.8
restart: on-failure
ipc: "host"
volumes:
- /tmp:/tmp
devices:
- "/dev/video0:/dev/video0"
command: "--camera=/dev/video0 --width=640 --height=480 --freq=20"
docker run --rm -ti --init --ipc=host -e DISPLAY=$DISPLAY --device /dev/video0 -v /tmp:/tmp chalmersrevere/opendlv-device-camera-opencv-multi:v0.0.11 --camera=/dev/video0 --width=640 --height=480 --freq=20
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-camera-opencv:
container_name: dev-camera-opencv
image: chalmersrevere/opendlv-device-camera-opencv-multi:v0.0.11
restart: on-failure
ipc: "host"
volumes:
- /tmp:/tmp
devices:
- "/dev/video0:/dev/video0"
command: "--camera=/dev/video0 --width=640 --height=480 --freq=20"
docker run --rm -ti --init --ipc=host -e DISPLAY=$DISPLAY --device /dev/video0 -v /tmp:/tmp chalmersrevere/opendlv-device-camera-rpi-armhf:v0.0.6 --width=640 --height=480 --freq=20
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-camera-rpi:
container_name: dev-camera-rpi
image: chalmersrevere/opendlv-device-camera-rpi-armhf:v0.0.6
restart: on-failure
ipc: "host"
volumes:
- /tmp:/tmp
command: "--width=640 --height=480 --freq=20"
docker run --rm -ti --init --ipc=host -v /tmp:/tmp --pid=host -v /var/run:/var/run -e DISPLAY=$DISPLAY chalmersrevere/opendlv-device-camera-ueye-multi:v0.0.5 --width=752 --height=480 --pixel_clock=10 --freq=20
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
dev-camera-ueye:
container_name: dev-camera-ueye
image: chalmersrevere/opendlv-device-camera-ueye-multi:v0.0.5
restart: on-failure
ipc: "host"
pid: "host"
volumes:
- /tmp:/tmp
- /var/run:/var/run
command: "--width=752 --height=480 --pixel_clock=10 --freq=20"
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
device-camera-pylon-amd64:
build:
context: https://github.com/chalmers-revere/opendlv-device-camera-pylon.git
dockerfile: Dockerfile.amd64
restart: on-failure
ipc: "host"
volumes:
- /tmp:/tmp
command: "--camera=0 --width=640 --height=480"
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
video-h264-encoder-amd64:
build:
context: https://github.com/chalmers-revere/opendlv-video-h264-encoder.git
dockerfile: Dockerfile.amd64
restart: on-failure
network_mode: "host"
ipc: "host"
volumes:
- /tmp:/tmp
command: "--cid=111 --name=video0.i420 --width=640 --height=480"
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
video-h264-decoder-amd64:
container_name: video-h264-decoder-amd64
build:
context: https://github.com/chalmers-revere/opendlv-video-h264-decoder.git
dockerfile: Dockerfile.amd64
restart: on-failure
network_mode: "host"
ipc: "host"
volumes:
- /tmp:/tmp
environment:
- DISPLAY=${DISPLAY}
command: "--cid=111 --name=imageData"
docker-compose.yml
file.docker-compose.yml
to build for amd64
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
video-x264-encoder-amd64:
container_name: video-x264-encoder-amd64
build:
context: https://github.com/chalmers-revere/opendlv-video-x264-encoder.git
dockerfile: Dockerfile.amd64
restart: on-failure
network_mode: "host"
ipc: "host"
volumes:
- /tmp:/tmp
command: "--cid=111 --name=video0.i420 --width=640 --height=480"
docker-compose.yml
to build for armhf
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
video-x264-encoder-armhf:
container_name: video-x264-encoder-armhf
build:
context: https://github.com/chalmers-revere/opendlv-video-x264-encoder.git
dockerfile: Dockerfile.armhf
restart: on-failure
network_mode: "host"
ipc: "host"
volumes:
- /tmp:/tmp
command: "--cid=111 --name=video0.i420 --width=640 --height=480"
docker-compose.yml
to build for aarch64
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
video-x264-encoder-aarch64:
container_name: video-x264-encoder-aarch64
build:
context: https://github.com/chalmers-revere/opendlv-video-x264-encoder.git
dockerfile: Dockerfile.aarch64
restart: on-failure
network_mode: "host"
ipc: "host"
volumes:
- /tmp:/tmp
command: "--cid=111 --name=video0.i420 --width=640 --height=480"
docker run --rm -ti --init --net=host --ipc=host -v /tmp:/tmp chalmersrevere/opendlv-video-vpx-encoder-multi:v0.0.7 --cid=111 --name=video0.i420 --width=640 --height=480 --vp8
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
video-vpx-encoder:
container_name: video-vpx-encoder
image: chalmersrevere/opendlv-video-vpx-encoder-multi:v0.0.7
restart: on-failure
network_mode: "host"
ipc: "host"
volumes:
- /tmp:/tmp
environment:
- DISPLAY=${DISPLAY}
command: "--cid=111 --name=video0.i420 --width=640 --height=480 --vp8"
docker run --rm -ti --init --net=host --ipc=host -v /tmp:/tmp -e DISPLAY=$DISPLAY chalmersrevere/opendlv-video-vpx-decoder-multi:v0.0.7 --cid=253 --name=video0.arg0 --verbose
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
video-vpx-decoder:
container_name: video-vpx-decoder
image: chalmersrevere/opendlv-video-vpx-decoder-multi:v0.0.7
restart: on-failure
network_mode: "host"
ipc: "host"
volumes:
- /tmp:/tmp
environment:
- DISPLAY=${DISPLAY}
command: "--cid=111 --name=imageData"
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
cluon-record:
container_name: cluon-record
image: chrberger/cluon-record-multi:v0.0.1
restart: on-failure
network_mode: "host"
volumes:
- ~/recordings:/recordings
working_dir: /recordings
command: "--cid=111 --remote"
docker-compose.yml
:
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
rec2csv_png:
container_name: rec2csv_png
build:
context: https://github.com/chalmers-revere/rec2csv-png.git
dockerfile: Dockerfile.amd64
restart: on-failure
volumes:
- .:/opt/data
working_dir: /opt/data
command: "--rec=YourRecording.rec --odvd=YourMessageSpec.odvd"
docker run --rm -ti -v $PWD/myrecording.rec:/opt/input.rec \
-v $PWD/opendlv.odvd:/opt/odvd \
-v $PWD/mnt:/opt/output:shared \
--cap-add SYS_ADMIN \
--cap-add MKNOD \
--security-opt apparmor:unconfined \
--device=/dev/fuse \
-v /etc/passwd:/etc/passwd:ro \
-v /etc/group:/etc/group \
chrberger/cluon-rec2fuse-amd64:v0.0.104 \
/bin/sh -c "chown $UID:$UID /opt/output && \
su -s /bin/sh $USER -c 'cluon-rec2fuse --rec=/opt/input.rec --odvd=/opt/odvd -f /opt/output' \
&& tail -f /dev/null"
docker run --rm -ti --init --net=host chrberger/cluon-livefeed-multi:v0.0.122 --cid=111
docker run --rm --net=host -p 8080:8080 chalmersrevere/opendlv-signal-viewer-multi:v0.0.8 --cid=111
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
signal-viewer:
container_name: signal-viewer
image: chalmersrevere/opendlv-signal-viewer-multi:v0.0.8
restart: on-failure
network_mode: "host"
ports:
- "8080:8080"
command: "--cid=111"
docker run --rm --net=host --name=opendlv-vehicle-view -v ~/recordings:/opt/vehicle-view/recordings -v /var/run/docker.sock:/var/run/docker.sock -p 8081:8081 chalmersrevere/opendlv-vehicle-view-multi:v0.0.60
version: '2' # Must be present exactly once at the beginning of the docker-compose.yml file
services: # Must be present exactly once at the beginning of the docker-compose.yml file
vehicle-view:
container_name: opendlv-vehicle-view
image: chalmersrevere/opendlv-vehicle-view-multi:v0.0.60
restart: on-failure
network_mode: "host"
volumes:
- ~/recordings:/opt/vehicle-view/recordings
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "8081:8081"
To build this software, you need cmake, C++14 or newer, and make. Having these preconditions, update the contained submodules first.
git submodule update --init --recursive
git submodule update --remote --merge
git submodule status
Now, you can change into the various sub-folders and run cmake
and make
as follows:
mkdir build && cd build
cmake -D CMAKE_BUILD_TYPE=Release ..
make && make test && make install
The following list contains publications related to the OpenDLV Software Ecosystem: