Skip to content

Commit f31d12d

Browse files
author
Martin
committed
Updated MATLAB scripts: Added new examples for how to load MF4 (unfinalized, finalized, DBC decoded) via the Vehicle Network Toolbox, including via single files, datastores and tall arrays. Also added example on loading MAT files. Added Python script for automating the export of MF4 files to DBC decoded MF4 and MAT.
1 parent 4683d75 commit f31d12d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+490
-67
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ output/
1111
LOG2/
1212
*LIN.dbc
1313
*NMEA-2000-CSS-Electronics-v*
14-
*find_data_event.py
14+
*find_data_event.py
15+
*CSS-Electronics-J1939-2021-08_v1.0.dbc
16+
logging.py
17+
*matlab_raw_to_tallarray.m
Binary file not shown.
-1 MB
Binary file not shown.
-969 KB
Binary file not shown.
Binary file not shown.
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
VERSION ""
2+
3+
4+
NS_ :
5+
NS_DESC_
6+
CM_
7+
BA_DEF_
8+
BA_
9+
VAL_
10+
CAT_DEF_
11+
CAT_
12+
FILTER
13+
BA_DEF_DEF_
14+
EV_DATA_
15+
ENVVAR_DATA_
16+
SGTYPE_
17+
SGTYPE_VAL_
18+
BA_DEF_SGTYPE_
19+
BA_SGTYPE_
20+
SIG_TYPE_REF_
21+
VAL_TABLE_
22+
SIG_GROUP_
23+
SIG_VALTYPE_
24+
SIGTYPE_VALTYPE_
25+
BO_TX_BU_
26+
BA_DEF_REL_
27+
BA_REL_
28+
BA_DEF_DEF_REL_
29+
BU_SG_REL_
30+
BU_EV_REL_
31+
BU_BO_REL_
32+
SG_MUL_VAL_
33+
34+
BS_:
35+
36+
BU_:
37+
38+
39+
BO_ 2364540158 EEC1: 8 Vector__XXX
40+
SG_ EngineSpeed : 24|16@1+ (0.125,0) [0|8031.875] "rpm" Vector__XXX
41+
42+
BO_ 2566844926 CCVS1: 8 Vector__XXX
43+
SG_ WheelBasedVehicleSpeed : 8|16@1+ (0.00390625,0) [0|250.996] "km/h" Vector__XXX
44+
45+
46+
CM_ BO_ 2364540158 "Electronic Engine Controller 1";
47+
CM_ SG_ 2364540158 EngineSpeed "Actual engine speed which is calculated over a minimum crankshaft angle of 720 degrees divided by the number of cylinders.…";
48+
CM_ BO_ 2566844926 "Cruise Control/Vehicle Speed 1";
49+
CM_ SG_ 2566844926 WheelBasedVehicleSpeed "Wheel-Based Vehicle Speed: Speed of the vehicle as calculated from wheel or tailshaft speed.";
50+
BA_DEF_ SG_ "SPN" INT 0 524287;
51+
BA_DEF_ BO_ "VFrameFormat" ENUM "StandardCAN","ExtendedCAN","reserved","J1939PG";
52+
BA_DEF_ "DatabaseVersion" STRING ;
53+
BA_DEF_ "BusType" STRING ;
54+
BA_DEF_ "ProtocolType" STRING ;
55+
BA_DEF_ "DatabaseCompiler" STRING ;
56+
BA_DEF_DEF_ "SPN" 0;
57+
BA_DEF_DEF_ "VFrameFormat" "J1939PG";
58+
BA_DEF_DEF_ "DatabaseVersion" "";
59+
BA_DEF_DEF_ "BusType" "";
60+
BA_DEF_DEF_ "ProtocolType" "";
61+
BA_DEF_DEF_ "DatabaseCompiler" "";
62+
BA_ "ProtocolType" "J1939";
63+
BA_ "BusType" "CAN";
64+
BA_ "DatabaseCompiler" "CSS ELECTRONICS (WWW.CSSELECTRONICS.COM)";
65+
BA_ "DatabaseVersion" "1.0.0";
66+
BA_ "VFrameFormat" BO_ 2364540158 3;
67+
BA_ "SPN" SG_ 2364540158 EngineSpeed 190;
68+
BA_ "SPN" SG_ 2566844926 WheelBasedVehicleSpeed 84;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
VERSION ""
2+
3+
4+
NS_ :
5+
NS_DESC_
6+
CM_
7+
BA_DEF_
8+
BA_
9+
VAL_
10+
CAT_DEF_
11+
CAT_
12+
FILTER
13+
BA_DEF_DEF_
14+
EV_DATA_
15+
ENVVAR_DATA_
16+
SGTYPE_
17+
SGTYPE_VAL_
18+
BA_DEF_SGTYPE_
19+
BA_SGTYPE_
20+
SIG_TYPE_REF_
21+
VAL_TABLE_
22+
SIG_GROUP_
23+
SIG_VALTYPE_
24+
SIGTYPE_VALTYPE_
25+
BO_TX_BU_
26+
BA_DEF_REL_
27+
BA_REL_
28+
BA_DEF_DEF_REL_
29+
BU_SG_REL_
30+
BU_EV_REL_
31+
BU_BO_REL_
32+
SG_MUL_VAL_
33+
34+
BS_:
35+
36+
BU_:
37+
38+
39+
BO_ 3 gnss_pos: 8 Vector__XXX
40+
SG_ PositionAccuracy : 58|6@1+ (1,0) [0|63] "m" Vector__XXX
41+
SG_ Latitude : 1|28@1+ (1e-06,-90) [-90|90] "deg" Vector__XXX
42+
SG_ Longitude : 29|29@1+ (1e-06,-180) [-180|180] "deg" Vector__XXX
43+
SG_ PositionValid : 0|1@1+ (1,0) [0|1] "" Vector__XXX
44+
45+
BO_ 2 gnss_time: 6 Vector__XXX
46+
SG_ TimeValid : 0|1@1+ (1,0) [0|1] "" Vector__XXX
47+
SG_ TimeConfirmed : 1|1@1+ (1,0) [0|1] "" Vector__XXX
48+
SG_ Epoch : 8|40@1+ (0.001,1577840400) [1577840400|2677352027] "sec" Vector__XXX
49+
50+
BO_ 5 gnss_attitude: 8 Vector__XXX
51+
SG_ AttitudeValid : 0|1@1+ (1,0) [0|1] "" Vector__XXX
52+
SG_ Roll : 1|12@1+ (0.1,-180) [-180|180] "deg" Vector__XXX
53+
SG_ Pitch : 22|12@1+ (0.1,-90) [-90|90] "deg" Vector__XXX
54+
SG_ Heading : 43|12@1+ (0.1,0) [0|360] "deg" Vector__XXX
55+
SG_ RollAccuracy : 13|9@1+ (0.1,0) [0|50] "deg" Vector__XXX
56+
SG_ PitchAccuracy : 34|9@1+ (0.1,0) [0|50] "deg" Vector__XXX
57+
SG_ HeadingAccuracy : 55|9@1+ (0.1,0) [0|50] "deg" Vector__XXX
58+
59+
BO_ 6 gnss_odo: 8 Vector__XXX
60+
SG_ DistanceTrip : 1|22@1+ (1,0) [0|4194303] "m" Vector__XXX
61+
SG_ DistanceAccuracy : 23|19@1+ (1,0) [0|524287] "m" Vector__XXX
62+
SG_ DistanceValid : 0|1@1+ (1,0) [0|1] "" Vector__XXX
63+
SG_ DistanceTotal : 42|22@1+ (1,0) [0|4194303] "km" Vector__XXX
64+
65+
BO_ 1 gnss_status: 1 Vector__XXX
66+
SG_ FixType : 0|3@1+ (1,0) [0|5] "" Vector__XXX
67+
SG_ Satellites : 3|5@1+ (1,0) [0|31] "" Vector__XXX
68+
69+
BO_ 4 gnss_altitude: 4 Vector__XXX
70+
SG_ AltitudeValid : 0|1@1+ (1,0) [0|1] "" Vector__XXX
71+
SG_ Altitude : 1|18@1+ (0.1,-6000) [-6000|20000] "m" Vector__XXX
72+
SG_ AltitudeAccuracy : 19|13@1+ (1,0) [0|8000] "m" Vector__XXX
73+
74+
BO_ 8 gnss_geofence: 2 Vector__XXX
75+
SG_ FenceValid : 0|1@1+ (1,0) [0|1] "" Vector__XXX
76+
SG_ FenceCombined : 1|2@1+ (1,0) [0|1] "" Vector__XXX
77+
SG_ Fence1 : 8|2@1+ (1,0) [0|1] "" Vector__XXX
78+
SG_ Fence2 : 10|2@1+ (1,0) [0|1] "" Vector__XXX
79+
SG_ Fence3 : 12|2@1+ (1,0) [0|1] "" Vector__XXX
80+
SG_ Fence4 : 14|2@1+ (1,0) [0|1] "" Vector__XXX
81+
82+
BO_ 7 gnss_speed: 5 Vector__XXX
83+
SG_ Speed : 1|20@1+ (0.001,0) [0|1048.575] "m/s" Vector__XXX
84+
SG_ SpeedAccuracy : 21|19@1+ (0.001,0) [0|524.287] "m/s" Vector__XXX
85+
SG_ SpeedValid : 0|1@1+ (1,0) [0|1] "" Vector__XXX
86+
87+
BO_ 9 gnss_imu: 8 Vector__XXX
88+
SG_ AccelerationX : 1|10@1+ (0.125,-64) [-64|63.875] "m/s^2" Vector__XXX
89+
SG_ AccelerationY : 11|10@1+ (0.125,-64) [-64|63.875] "m/s^2" Vector__XXX
90+
SG_ AccelerationZ : 21|10@1+ (0.125,-64) [-64|63.875] "m/s^2" Vector__XXX
91+
SG_ AngularRateX : 31|11@1+ (0.25,-256) [-256|255.75] "deg/s" Vector__XXX
92+
SG_ AngularRateY : 42|11@1+ (0.25,-256) [-256|255.75] "deg/s" Vector__XXX
93+
SG_ AngularRateZ : 53|11@1+ (0.25,-256) [-256|255.75] "deg/s" Vector__XXX
94+
SG_ ImuValid : 0|1@1+ (1,0) [0|1] "" Vector__XXX
95+
96+
97+
98+
CM_ BO_ 3 "GNSS position";
99+
CM_ SG_ 3 PositionAccuracy "Accuracy of position";
100+
CM_ SG_ 3 Latitude "Latitude";
101+
CM_ SG_ 3 Longitude "Longitude";
102+
CM_ SG_ 3 PositionValid "Position validity";
103+
CM_ BO_ 2 "GNSS time";
104+
CM_ SG_ 2 TimeValid "Time validity";
105+
CM_ SG_ 2 TimeConfirmed "Time confirmed";
106+
CM_ SG_ 2 Epoch "Epoch time";
107+
CM_ BO_ 5 "GNSS attitude";
108+
CM_ SG_ 5 AttitudeValid "Attitude validity";
109+
CM_ SG_ 5 Roll "Vehicle roll";
110+
CM_ SG_ 5 Pitch "Vehicle pitch";
111+
CM_ SG_ 5 Heading "Vehicle heading";
112+
CM_ SG_ 5 RollAccuracy "Vehicle roll accuracy";
113+
CM_ SG_ 5 PitchAccuracy "Vehicle pitch accuracy";
114+
CM_ SG_ 5 HeadingAccuracy "Vehicle heading accuracy";
115+
CM_ BO_ 6 "GNSS odometer";
116+
CM_ SG_ 6 DistanceTrip "Distance traveled since last reset";
117+
CM_ SG_ 6 DistanceAccuracy "Distance accuracy (1-sigma)";
118+
CM_ SG_ 6 DistanceTotal "Distance traveled in total";
119+
CM_ BO_ 1 "GNSS information";
120+
CM_ SG_ 1 FixType "Fix type";
121+
CM_ SG_ 1 Satellites "Number of satellites used";
122+
CM_ BO_ 4 "GNSS altitude";
123+
CM_ SG_ 4 AltitudeValid "Altitude validity";
124+
CM_ SG_ 4 Altitude "Altitude";
125+
CM_ SG_ 4 AltitudeAccuracy "Accuracy of altitude";
126+
CM_ BO_ 8 "GNSS geofence(s)";
127+
CM_ SG_ 8 FenceValid "Geofencing status";
128+
CM_ SG_ 8 FenceCombined "Combined (logical OR) state of all geofences";
129+
CM_ SG_ 8 Fence1 "Geofence 1 state";
130+
CM_ SG_ 8 Fence2 "Geofence 2 state";
131+
CM_ SG_ 8 Fence3 "Geofence 3 state";
132+
CM_ SG_ 8 Fence4 "Geofence 4 state";
133+
CM_ BO_ 7 "GNSS speed";
134+
CM_ SG_ 7 Speed "Speed";
135+
CM_ SG_ 7 SpeedAccuracy "Speed accuracy";
136+
CM_ BO_ 9 "GNSS IMU";
137+
CM_ SG_ 9 AccelerationX "X acceleration with a resolution of 0.125 m/s^2";
138+
CM_ SG_ 9 AccelerationY "Y acceleration with a resolution of 0.125 m/s^2";
139+
CM_ SG_ 9 AccelerationZ "Z acceleration with a resolution of 0.125 m/s^2";
140+
CM_ SG_ 9 AngularRateX "X angular rate with a resolution of 0.25 deg/s";
141+
CM_ SG_ 9 AngularRateY "Y angular rate with a resolution of 0.25 deg/s";
142+
CM_ SG_ 9 AngularRateZ "Z angular rate with a resolution of 0.25 deg/s";
143+
VAL_ 3 PositionValid 0 "Invalid" 1 "Valid" ;
144+
VAL_ 2 TimeValid 0 "Invalid" 1 "Valid" ;
145+
VAL_ 2 TimeConfirmed 0 "Unconfirmed" 1 "Confirmed" ;
146+
VAL_ 5 AttitudeValid 0 "Invalid" 1 "Valid" ;
147+
VAL_ 6 DistanceValid 0 "Invalid" 1 "Valid" ;
148+
VAL_ 1 FixType 0 "No fix" 1 "Dead reckoning only" 2 "2D-fix" 3 "3D-fix" 4 "GNSS + dead reckoning combined" 5 "Time only fix" ;
149+
VAL_ 4 AltitudeValid 0 "Invalid" 1 "Valid" ;
150+
VAL_ 8 FenceValid 0 "Invalid" 1 "Valid" ;
151+
VAL_ 8 FenceCombined 0 "Unknown" 1 "Inside" 2 "Outside" ;
152+
VAL_ 8 Fence1 0 "Unknown" 1 "Inside" 2 "Outside" ;
153+
VAL_ 8 Fence2 0 "Unknown" 1 "Inside" 2 "Outside" ;
154+
VAL_ 8 Fence3 0 "Unknown" 1 "Inside" 2 "Outside" ;
155+
VAL_ 8 Fence4 0 "Unknown" 1 "Inside" 2 "Outside" ;
156+
VAL_ 7 SpeedValid 0 "Invalid" 1 "Valid" ;
157+
VAL_ 9 ImuValid 0 "Invalid" 1 "Valid" ;
158+
+41-22
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,48 @@
1-
% This script uses the MATLAB Vehicle Network Toolbox to load
2-
% finalized & sorted MF4 files from the CANedge (Firmware 01.04.01+)
3-
% See also below links:
4-
% - https://www.mathworks.com/help/vnt/mdf-files.html
5-
% - https://www.mathworks.com/help/vnt/ug/work-with-unfinalized-and-unsorted-mdf-files.html
6-
% - https://se.mathworks.com/help/vnt/ug/reading-data-from-mdf-files.html
7-
% - https://se.mathworks.com/help/vnt/ug/using-mdf-files-via-mdf-datastore.html
8-
% - https://se.mathworks.com/help/vnt/ug/decoding-can-data-from-mdf-files.html
1+
clear, clc, close all
92

10-
% load a 'sorted & finalized' MF4 file (via the mdf2finalized converter)
11-
m = mdf('00000014_fin.MF4')
3+
% set index of CAN channel (MATLAB finalization: 8 | mdf2finalized: 1)
4+
can_idx = 8;
125

13-
% or, finalize an unfinalized file via MATLAB and load it (support in MATLAB 2021b+)
14-
finalizedPath = mdfFinalize("00000014.MF4");
15-
m = mdf(finalizedPath);
6+
% ------------------------------------------------------------------------
7+
% finalize & load MF4 "in place" (overwrites original file)
8+
% m = mdf(mdfFinalize("LOG/11111111/00000012/00000001.MF4"));
169

17-
% extract 5 rows into a timetable
18-
rawTimeTable = read(m, 1, m.ChannelNames{1}, 1, 5)
10+
% finalize & load MF4 "out of place" (makes a copy of original file)
11+
try
12+
finalizedPath2 = mdfFinalize("LOG/11111111/00000012/00000001.MF4", "LOG/11111111/00000012/00000001_fin.MF4");
13+
m = mdf(finalizedPath2);
14+
catch ME
15+
disp(ME.message)
16+
end
1917

20-
% extract data using DBC file (note: MATLAB sees the CANedge data as CAN FD
21-
% regardless of whether it's Classical CAN or CAN FD)
22-
db = canDatabase('my_dbc.dbc');
23-
msgTimetable = canFDMessageTimetable(rawTimeTable, db)
18+
% load an MF4 which has already been 'finalized' via MATLAB or mdf2finalized
19+
m = mdf("LOG/11111111/00000012/00000001_fin.MF4");
2420

25-
% create a signal time table for a specific CAN message and create a plot
26-
signalTimetable1 = canSignalTimetable(msgTimetable, "Message1")
27-
plot(signalTimetable1.Time, signalTimetable1.Signal1)
21+
% extract CAN data into timetable
22+
rawTimeTable = read(m,can_idx,m.ChannelNames{can_idx});
2823

2924

25+
26+
% ------------------------------------------------------------------------
27+
% decode CAN data using DBC, use absolute date & time and extract a specific message
28+
canDB = canDatabase('dbc_files/canmod-gps.dbc');
29+
msgTimetableGPS = canFDMessageTimetable(rawTimeTable, canDB);
30+
msgTimetableGPS.Time = msgTimetableGPS.Time + m.InitialTimestamp;
31+
msgSpeed = canSignalTimetable(msgTimetableGPS, "gnss_speed");
32+
33+
% decode J1939 data (first convert data to 'Classical' CAN by removing EDL)
34+
rawTimeTable = removevars(rawTimeTable, "CAN_DataFrame_EDL");
35+
36+
canDB = canDatabase('dbc_files/CSS-Electronics-SAE-J1939-DEMO.dbc');
37+
msgTimetableJ1939 = j1939ParameterGroupTimetable(rawTimeTable, canDB);
38+
msgTimetableJ1939.Time = msgTimetableJ1939.Time + m.InitialTimestamp;
39+
msgEEC1 = j1939SignalTimetable(msgTimetableJ1939, "ParameterGroups","EEC1");
40+
41+
% plot select decoded signals
42+
ax1 = subplot(2, 1, 1);
43+
plot(msgSpeed.Time, msgSpeed.Speed)
44+
ylabel("Speed (m/s)")
45+
ax2 = subplot(2, 1, 2);
46+
plot(msgEEC1.Time, msgEEC1.EngineSpeed)
47+
ylabel("Engine Speed (rpm)")
48+
linkaxes([ax1,ax2],'x');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
clear, clc, close all
2+
3+
% load database
4+
canDB = canDatabase("dbc_files/canmod-gps.dbc");
5+
6+
% create datastore of finalized MF4 files from local disk
7+
mds = mdfDatastore("LOG_datastore/3BA199E2/00000164", "IncludeSubfolders", true);
8+
9+
% same principle can be used to load MF4 files from mounted S3 drive
10+
% mds = mdfDatastore("Z:\3BA199E2","IncludeSubfolders", true);
11+
12+
% preview datastore
13+
preview(mds);
14+
15+
% ------------------------------------------------------------------------
16+
% if datastore fits into memory you can simply read all data into timetable
17+
rawTimeTable = readall(mds);
18+
msgTimetable = canFDMessageTimetable(rawTimeTable, canDB);
19+
msgSpeed = canSignalTimetable(msgTimetable, "gnss_speed");
20+
subplot(2, 1, 1);
21+
plot(msgSpeed.Time, msgSpeed.Speed)
22+
ylabel("Speed (m/s) via readall")
23+
24+
% ------------------------------------------------------------------------
25+
% if datastore is larger than memory, use in-memory chunks
26+
mds.ReadSize = seconds(300);
27+
msgSpeed = [];
28+
i = 1;
29+
30+
while hasdata(mds)
31+
% read a chunk, decode it and extract data to separate table
32+
rawTimeTable = read(mds);
33+
msgTimeTable = canFDMessageTimetable(rawTimeTable, canDB);
34+
msgSpeedChunk = canSignalTimetable(msgTimetable, "gnss_speed");
35+
msgSpeed = vertcat(msgSpeed,msgSpeedChunk);
36+
fprintf("\nreading chunk %i",i)
37+
i = i + 1;
38+
end
39+
40+
subplot(2, 1, 2);
41+
plot(msgSpeed.Time, msgSpeed.Speed)
42+
ylabel("Speed (m/s) via chunks")

0 commit comments

Comments
 (0)