mavlink-log 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/lib/mavlink/log.rb +5 -1
  4. data/lib/mavlink/log/entry.rb +34 -0
  5. data/lib/mavlink/log/file.rb +16 -41
  6. data/lib/mavlink/log/header.rb +20 -0
  7. data/lib/mavlink/log/message.rb +83 -0
  8. data/lib/mavlink/log/messages/attitude.rb +37 -0
  9. data/lib/mavlink/log/messages/factory.rb +37 -0
  10. data/lib/mavlink/log/messages/global_position_int.rb +47 -0
  11. data/lib/mavlink/log/messages/gps_raw_int.rb +51 -0
  12. data/lib/mavlink/log/messages/heart_beat.rb +31 -0
  13. data/lib/mavlink/log/messages/messages.rb +15 -0
  14. data/lib/mavlink/log/messages/mission_current.rb +11 -0
  15. data/lib/mavlink/log/messages/nav_controller_output.rb +39 -0
  16. data/lib/mavlink/log/messages/param_request_list.rb +15 -0
  17. data/lib/mavlink/log/messages/param_value.rb +27 -0
  18. data/lib/mavlink/log/messages/raw_imu.rb +43 -0
  19. data/lib/mavlink/log/messages/rc_channels_raw.rb +47 -0
  20. data/lib/mavlink/log/messages/request_data_stream.rb +27 -0
  21. data/lib/mavlink/log/messages/scaled_pressure.rb +19 -0
  22. data/lib/mavlink/log/messages/servo_output_raw.rb +43 -0
  23. data/lib/mavlink/log/messages/sys_status.rb +64 -0
  24. data/lib/mavlink/log/messages/vfr_hud.rb +37 -0
  25. data/lib/mavlink/log/version.rb +1 -1
  26. data/spec/file_spec.rb +11 -1
  27. data/spec/messages/attitude_spec.rb +34 -0
  28. data/spec/messages/global_position_int_spec.rb +38 -0
  29. data/spec/messages/gps_raw_int_spec.rb +40 -0
  30. data/spec/messages/heart_beat_spec.rb +32 -0
  31. data/spec/messages/param_value_spec.rb +30 -0
  32. data/spec/messages/raw_imu_spec.rb +40 -0
  33. data/spec/messages/rc_channels_raw_spec.rb +42 -0
  34. data/spec/messages/sys_status_spec.rb +46 -0
  35. data/spec/messages/vfr_hud_spec.rb +32 -0
  36. data/spec/spec_helper.rb +2 -0
  37. data/spec/support/shared_examples_for_message.rb +13 -0
  38. data/spec/support/shared_examples_for_timed_message_micro.rb +9 -0
  39. data/spec/support/shared_examples_for_timed_message_milli.rb +9 -0
  40. data/spec/sys_status_spec.rb +0 -0
  41. metadata +48 -3
  42. data/lib/mavlink/log/messages.rb +0 -138
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 51dc07848518c662316fb0655bcc8dc6f7bf584e
4
- data.tar.gz: 0f254b7f8f4621d34d4e1f78407fd5b1eb930d40
3
+ metadata.gz: 2aa7c3553fcad5fa98c61094e850ed0b23e9e28a
4
+ data.tar.gz: 95db6b58d4f7c4bf4af1ca0d5c97218dcf385d01
5
5
  SHA512:
6
- metadata.gz: 6321f5e5a88846fc4e5c9773972adb8a04dc7c66ee0604ea93277b1b61c572bb3750be827058da316904ba2ca722e61ed8e31ae26ad558b283079d73c23b52b9
7
- data.tar.gz: 885eabbb7e06f53342f55d810e9cd0d6bd142aa15102e31217bce0561619895488861d05e99c9466eb4c9d37c2b6e05500b9552bd5aff7d899bf094f4e3f83eb
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/messages"
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
@@ -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
- attr_accessor :entries, :messages
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
- time = to_time(raw_time)
33
- header = to_header(file.read(6))
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
- crc = file.read(2).unpack('S>')[0]
36
- @entries << Entry.new(time, header, payload, crc)
37
- @messages << MessageFactory.build(@entries.last)
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
- #@messages.each do |e|
41
- # puts e.inspect
42
- #end
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) / USEC_PER_SEC
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 / USEC_PER_SEC)
54
+ Time.at(@entries.first.time / 1000000.0)
57
55
  end
58
56
 
59
57
  def ended_at
60
- Time.at(@entries.last.time / USEC_PER_SEC)
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