mavlink-log 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/lib/mavlink/log.rb +5 -1
- data/lib/mavlink/log/entry.rb +34 -0
- data/lib/mavlink/log/file.rb +16 -41
- data/lib/mavlink/log/header.rb +20 -0
- data/lib/mavlink/log/message.rb +83 -0
- data/lib/mavlink/log/messages/attitude.rb +37 -0
- data/lib/mavlink/log/messages/factory.rb +37 -0
- data/lib/mavlink/log/messages/global_position_int.rb +47 -0
- data/lib/mavlink/log/messages/gps_raw_int.rb +51 -0
- data/lib/mavlink/log/messages/heart_beat.rb +31 -0
- data/lib/mavlink/log/messages/messages.rb +15 -0
- data/lib/mavlink/log/messages/mission_current.rb +11 -0
- data/lib/mavlink/log/messages/nav_controller_output.rb +39 -0
- data/lib/mavlink/log/messages/param_request_list.rb +15 -0
- data/lib/mavlink/log/messages/param_value.rb +27 -0
- data/lib/mavlink/log/messages/raw_imu.rb +43 -0
- data/lib/mavlink/log/messages/rc_channels_raw.rb +47 -0
- data/lib/mavlink/log/messages/request_data_stream.rb +27 -0
- data/lib/mavlink/log/messages/scaled_pressure.rb +19 -0
- data/lib/mavlink/log/messages/servo_output_raw.rb +43 -0
- data/lib/mavlink/log/messages/sys_status.rb +64 -0
- data/lib/mavlink/log/messages/vfr_hud.rb +37 -0
- data/lib/mavlink/log/version.rb +1 -1
- data/spec/file_spec.rb +11 -1
- data/spec/messages/attitude_spec.rb +34 -0
- data/spec/messages/global_position_int_spec.rb +38 -0
- data/spec/messages/gps_raw_int_spec.rb +40 -0
- data/spec/messages/heart_beat_spec.rb +32 -0
- data/spec/messages/param_value_spec.rb +30 -0
- data/spec/messages/raw_imu_spec.rb +40 -0
- data/spec/messages/rc_channels_raw_spec.rb +42 -0
- data/spec/messages/sys_status_spec.rb +46 -0
- data/spec/messages/vfr_hud_spec.rb +32 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/shared_examples_for_message.rb +13 -0
- data/spec/support/shared_examples_for_timed_message_micro.rb +9 -0
- data/spec/support/shared_examples_for_timed_message_milli.rb +9 -0
- data/spec/sys_status_spec.rb +0 -0
- metadata +48 -3
- data/lib/mavlink/log/messages.rb +0 -138
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2aa7c3553fcad5fa98c61094e850ed0b23e9e28a
|
4
|
+
data.tar.gz: 95db6b58d4f7c4bf4af1ca0d5c97218dcf385d01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2f934aed5b2e6c68f31cec773efe744ded1bf7d0b21497e3e3ddf57a236ad1bacccc86b16e8541a0146050716bd883e8ea14fba02651dcdeebb1fa7c5319896
|
7
|
+
data.tar.gz: dc241610e2b09e2dc5e32e1d90898ec026dd0986034a3326097d482ece1ebf1b6dd924865f676c5f5aea13be6e3b220b25f0e6b6a5a9583a58332c9ccafc55b5
|
data/README.md
CHANGED
@@ -7,6 +7,7 @@ Information:
|
|
7
7
|
* mavlink github: https://github.com/mavlink/mavlink
|
8
8
|
* Spec: https://pixhawk.ethz.ch/mavlink
|
9
9
|
* Common message definitions: https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/common.xml
|
10
|
+
* Packet Decoding: http://eastbay-rc.blogspot.com/2013/04/mavlink-protocol-notes-packet-decoding.html
|
10
11
|
|
11
12
|
## Installation
|
12
13
|
|
data/lib/mavlink/log.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
require "mavlink/log/entry"
|
1
2
|
require "mavlink/log/file"
|
2
|
-
require "mavlink/log/
|
3
|
+
require "mavlink/log/header"
|
4
|
+
require "mavlink/log/message"
|
5
|
+
require "mavlink/log/messages/factory"
|
6
|
+
require "mavlink/log/messages/messages"
|
3
7
|
require "mavlink/log/version"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module MAVLink
|
2
|
+
module Log
|
3
|
+
|
4
|
+
class Entry
|
5
|
+
|
6
|
+
attr_reader :time, :header, :payload, :crc
|
7
|
+
|
8
|
+
def initialize(raw_time, header, payload, raw_crc)
|
9
|
+
@time = to_time(raw_time)
|
10
|
+
@header = header
|
11
|
+
@payload = payload
|
12
|
+
@crc = to_crc(raw_crc)
|
13
|
+
|
14
|
+
if false && header.id==22
|
15
|
+
puts raw_time.unpack('H*')
|
16
|
+
puts payload.unpack("H*")
|
17
|
+
puts raw_crc.unpack('H*')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def to_time(raw)
|
24
|
+
(raw[0..3].unpack('L>')[0] << 32) | raw[4..7].unpack('L>')[0]
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_crc(raw)
|
28
|
+
raw.unpack('S>')[0]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/mavlink/log/file.rb
CHANGED
@@ -3,15 +3,9 @@ require 'open-uri'
|
|
3
3
|
module MAVLink
|
4
4
|
module Log
|
5
5
|
|
6
|
-
USEC_PER_SEC = 1000000.0
|
7
|
-
|
8
|
-
Header = Struct.new(:magic, :length, :sequence, :system, :component, :id)
|
9
|
-
|
10
|
-
Entry = Struct.new(:time, :header, :payload, :crc)
|
11
|
-
|
12
6
|
class File
|
13
7
|
|
14
|
-
|
8
|
+
attr_reader :entries, :messages
|
15
9
|
|
16
10
|
# Determines if the file at the given URI is a MAVLink telemetry log file.
|
17
11
|
#
|
@@ -29,17 +23,21 @@ module MAVLink
|
|
29
23
|
raw_time = file.read(8)
|
30
24
|
break if raw_time.nil?
|
31
25
|
|
32
|
-
|
33
|
-
|
26
|
+
header = Header.new(file.read(6))
|
27
|
+
raise "Unexpected magic number (#{header.magic})" unless header.magic == 0xFE
|
28
|
+
|
34
29
|
payload = file.read(header.length)
|
35
|
-
|
36
|
-
@entries << Entry.new(
|
37
|
-
@messages <<
|
30
|
+
raw_crc = file.read(2)
|
31
|
+
@entries << Entry.new(raw_time, header, payload, raw_crc)
|
32
|
+
@messages << Messages::Factory.build(@entries.last)
|
38
33
|
end
|
39
34
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
|
36
|
+
if @entries.empty?
|
37
|
+
raise 'No entries found in file'
|
38
|
+
end
|
39
|
+
|
40
|
+
#puts @messages.inspect
|
43
41
|
rescue => e
|
44
42
|
raise ArgumentError, "File does not appear to be an MAVLink log (#{e})"
|
45
43
|
end
|
@@ -49,38 +47,15 @@ module MAVLink
|
|
49
47
|
# @return [Float] duration of the session, in seconds
|
50
48
|
def duration
|
51
49
|
return 0 if @entries.empty?
|
52
|
-
(@entries.last.time - @entries.first.time) /
|
50
|
+
(@entries.last.time - @entries.first.time) / 1000000.0
|
53
51
|
end
|
54
52
|
|
55
53
|
def started_at
|
56
|
-
Time.at(@entries.first.time /
|
54
|
+
Time.at(@entries.first.time / 1000000.0)
|
57
55
|
end
|
58
56
|
|
59
57
|
def ended_at
|
60
|
-
Time.at(@entries.last.time /
|
61
|
-
end
|
62
|
-
|
63
|
-
# Determines if KML methods can be called for this file.
|
64
|
-
#
|
65
|
-
# @return [Boolean] true if KML can be generated for this file, false otherwise
|
66
|
-
def to_kml?
|
67
|
-
@entries.any? { |e| e.header.id == GlobalPositionInt::ID }
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def to_time(raw_time)
|
73
|
-
(raw_time[0..3].unpack('L>')[0] << 32) | raw_time[4..7].unpack('L>')[0]
|
74
|
-
end
|
75
|
-
|
76
|
-
def to_header(raw_header)
|
77
|
-
magic = raw_header[0].unpack('C')[0]
|
78
|
-
length = raw_header[1].unpack('C')[0]
|
79
|
-
sequence = raw_header[2].unpack('C')[0]
|
80
|
-
system = raw_header[3].unpack('C')[0]
|
81
|
-
component = raw_header[4].unpack('C')[0]
|
82
|
-
id = raw_header[5].unpack('C')[0]
|
83
|
-
Header.new(magic, length, sequence, system, component, id)
|
58
|
+
Time.at(@entries.last.time / 1000000.0)
|
84
59
|
end
|
85
60
|
|
86
61
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module MAVLink
|
2
|
+
module Log
|
3
|
+
|
4
|
+
class Header
|
5
|
+
|
6
|
+
attr_reader :magic, :length, :sequence, :system, :component, :id
|
7
|
+
|
8
|
+
def initialize(raw_header)
|
9
|
+
@magic = raw_header[0].unpack('C')[0]
|
10
|
+
@length = raw_header[1].unpack('C')[0]
|
11
|
+
@sequence = raw_header[2].unpack('C')[0]
|
12
|
+
@system = raw_header[3].unpack('C')[0]
|
13
|
+
@component = raw_header[4].unpack('C')[0]
|
14
|
+
@id = raw_header[5].unpack('C')[0]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module MAVLink; module Log
|
2
|
+
|
3
|
+
class Message
|
4
|
+
|
5
|
+
def initialize(entry)
|
6
|
+
@entry = entry
|
7
|
+
end
|
8
|
+
|
9
|
+
def id
|
10
|
+
@entry.header.id
|
11
|
+
end
|
12
|
+
|
13
|
+
def crc
|
14
|
+
@entry.crc
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def float(range)
|
20
|
+
unpack(range, 'e')
|
21
|
+
end
|
22
|
+
|
23
|
+
def int8_t(range)
|
24
|
+
unpack(range, 'c')
|
25
|
+
end
|
26
|
+
|
27
|
+
def uint8_t(range)
|
28
|
+
unpack(range, 'C')
|
29
|
+
end
|
30
|
+
|
31
|
+
def int16_t(range)
|
32
|
+
unpack(range, 's<')
|
33
|
+
end
|
34
|
+
|
35
|
+
def uint16_t(range)
|
36
|
+
unpack(range, 'S<')
|
37
|
+
end
|
38
|
+
|
39
|
+
def int32_t(range)
|
40
|
+
unpack(range, 'l<')
|
41
|
+
end
|
42
|
+
|
43
|
+
def uint32_t(range)
|
44
|
+
unpack(range, 'L<')
|
45
|
+
end
|
46
|
+
|
47
|
+
def uint64_t(range)
|
48
|
+
unpack(range, 'Q<')
|
49
|
+
end
|
50
|
+
|
51
|
+
def string(range)
|
52
|
+
unpack(range, 'Z*')
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def payload
|
58
|
+
@entry.payload
|
59
|
+
end
|
60
|
+
|
61
|
+
def unpack(range, format, index = 0)
|
62
|
+
payload[range].unpack(format)[index]
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
class TimedMessageMilli < Message
|
68
|
+
|
69
|
+
def time_boot_ms
|
70
|
+
@time_boot_ms ||= uint32_t(0..3)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
class TimedMessageMicro < Message
|
76
|
+
|
77
|
+
def time_usec
|
78
|
+
@time_usec ||= uint64_t(0..7)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end; end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module MAVLink; module Log; module Messages
|
2
|
+
|
3
|
+
class Attitude < TimedMessageMilli
|
4
|
+
|
5
|
+
# radians (-pi..pi)
|
6
|
+
def roll
|
7
|
+
@roll ||= float(0..3)
|
8
|
+
end
|
9
|
+
|
10
|
+
# radians (-pi..pi)
|
11
|
+
def pitch
|
12
|
+
@pitch ||= float(4..7)
|
13
|
+
end
|
14
|
+
|
15
|
+
# radians (-pi..pi)
|
16
|
+
def yaw
|
17
|
+
@yaw ||= float(8..11)
|
18
|
+
end
|
19
|
+
|
20
|
+
# rad/s
|
21
|
+
def rollspeed
|
22
|
+
@rollspeed ||= float(12..15)
|
23
|
+
end
|
24
|
+
|
25
|
+
# rad/s
|
26
|
+
def pitchspeed
|
27
|
+
@pitchspeed ||= float(16..19)
|
28
|
+
end
|
29
|
+
|
30
|
+
# rad/s
|
31
|
+
def yawspeed
|
32
|
+
@yawspeed ||= float(20..23)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end; end; end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module MAVLink; module Log; module Messages
|
2
|
+
|
3
|
+
class Dummy
|
4
|
+
def initialize(entry)
|
5
|
+
#puts entry.header.inspect
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Factory
|
10
|
+
|
11
|
+
def self.build(entry)
|
12
|
+
case(entry.header.id)
|
13
|
+
when 0; HeartBeat.new(entry)
|
14
|
+
when 1; SysStatus.new(entry)
|
15
|
+
when 21; ParamRequestList.new(entry)
|
16
|
+
when 22; ParamValue.new(entry)
|
17
|
+
when 24; GpsRawInt.new(entry)
|
18
|
+
when 27; RawImu.new(entry)
|
19
|
+
when 29; ScaledPressure.new(entry)
|
20
|
+
when 30; Attitude.new(entry)
|
21
|
+
when 33; GlobalPositionInt.new(entry)
|
22
|
+
when 35; RcChannelsRaw.new(entry)
|
23
|
+
when 36; ServoOutputRaw.new(entry)
|
24
|
+
when 42; MissionCurrent.new(entry)
|
25
|
+
when 62; NavControllerOutput.new(entry)
|
26
|
+
when 66; RequestDataStream.new(entry)
|
27
|
+
when 74; VfrHud.new(entry)
|
28
|
+
when 150..240; Dummy.new(entry)
|
29
|
+
else
|
30
|
+
puts entry.header.inspect
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end; end; end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module MAVLink; module Log; module Messages
|
2
|
+
|
3
|
+
class GlobalPositionInt < TimedMessageMilli
|
4
|
+
|
5
|
+
# dec. degrees
|
6
|
+
def lat
|
7
|
+
@lat ||= (int32_t(4..7) / 10000000.0)
|
8
|
+
end
|
9
|
+
|
10
|
+
# dec. degrees
|
11
|
+
def lon
|
12
|
+
@lon ||= (int32_t(8..11) / 10000000.0)
|
13
|
+
end
|
14
|
+
|
15
|
+
# meters
|
16
|
+
def alt
|
17
|
+
@alt ||= (int32_t(12..15) / 1000.0)
|
18
|
+
end
|
19
|
+
|
20
|
+
# meters
|
21
|
+
def relative_alt
|
22
|
+
@relative_alt ||= (int32_t(16..19) / 1000.0)
|
23
|
+
end
|
24
|
+
|
25
|
+
# m/s
|
26
|
+
def vx
|
27
|
+
@vx ||= (int16_t(20..21) / 100.0)
|
28
|
+
end
|
29
|
+
|
30
|
+
# m/s
|
31
|
+
def vy
|
32
|
+
@vy ||= (int16_t(22..23) / 100.0)
|
33
|
+
end
|
34
|
+
|
35
|
+
# m/s
|
36
|
+
def vz
|
37
|
+
@vz ||= (int16_t(24..25) / 100.0)
|
38
|
+
end
|
39
|
+
|
40
|
+
# degrees (0.0..359.99) (0xFFFF if unknown)
|
41
|
+
def hdg
|
42
|
+
@hdg ||= (uint16_t(26..27) / 100.0)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end; end; end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module MAVLink; module Log; module Messages
|
2
|
+
|
3
|
+
class GpsRawInt < TimedMessageMicro
|
4
|
+
|
5
|
+
# WGS84 dec. degrees
|
6
|
+
def lat
|
7
|
+
@lat ||= (int32_t(8..11) / 10000000.0)
|
8
|
+
end
|
9
|
+
|
10
|
+
# WGS84 dec. degrees
|
11
|
+
def lon
|
12
|
+
@lon ||= (int32_t(12..15) / 10000000.0)
|
13
|
+
end
|
14
|
+
|
15
|
+
# meters
|
16
|
+
def alt
|
17
|
+
@alt ||= (int32_t(16..19) / 1000.0)
|
18
|
+
end
|
19
|
+
|
20
|
+
# meters
|
21
|
+
def eph
|
22
|
+
@eph ||= (uint16_t(20..21) / 100.0)
|
23
|
+
end
|
24
|
+
|
25
|
+
# meters
|
26
|
+
def epv
|
27
|
+
@epv ||= (uint16_t(22..23) / 100.0)
|
28
|
+
end
|
29
|
+
|
30
|
+
# m/s
|
31
|
+
def vel
|
32
|
+
@vel ||= (uint16_t(24..25) / 100.0)
|
33
|
+
end
|
34
|
+
|
35
|
+
# degrees 0..359.99
|
36
|
+
def cog
|
37
|
+
@cog ||= (uint16_t(26..27) / 100.0)
|
38
|
+
end
|
39
|
+
|
40
|
+
# 0-1: no fix, 2: 2D fix, 3: 3D fix
|
41
|
+
def fix_type
|
42
|
+
@fix_type ||= uint8_t(28)
|
43
|
+
end
|
44
|
+
|
45
|
+
def satellites_visible
|
46
|
+
@satellites_visible ||= uint8_t(29)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end; end; end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module MAVLink; module Log; module Messages
|
2
|
+
|
3
|
+
class HeartBeat < Message
|
4
|
+
|
5
|
+
def type
|
6
|
+
@type ||= uint8_t(0)
|
7
|
+
end
|
8
|
+
|
9
|
+
def autopilot
|
10
|
+
@autopilot ||= uint8_t(1)
|
11
|
+
end
|
12
|
+
|
13
|
+
def base_mode
|
14
|
+
@base_mode ||= uint8_t(2)
|
15
|
+
end
|
16
|
+
|
17
|
+
def custom_mode
|
18
|
+
@custom_mode ||= uint32_t(3..6)
|
19
|
+
end
|
20
|
+
|
21
|
+
def system_status
|
22
|
+
@system_status ||= uint8_t(7)
|
23
|
+
end
|
24
|
+
|
25
|
+
def mavlink_version
|
26
|
+
@mavlink_version ||= uint8_t(8)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end; end; end
|