Module: TelemetryProcessor
- Defined in:
- lib/kamelopard/helpers.rb
Overview
Given telemetry data, such as from an aircraft, including latitude, longitude, and altitude, this will figure out realistic-looking tilt, heading, and roll values and create a series of FlyTo objects to follow the extrapolated flight path
Constant Summary collapse
- Pi =
3.1415926535
Class Method Summary collapse
-
.add_flyto(p) ⇒ Object
This is the only function in the module that users are expected to call, and even then users should probably use the tour_from_points function.
- .fix_coord(a) ⇒ Object
- .get_dist2(x1, y1, x2, y2) ⇒ Object
- .get_dist3(x1, y1, z1, x2, y2, z2) ⇒ Object
- .get_heading(p) ⇒ Object
- .get_roll(p) ⇒ Object
- .get_tilt(p) ⇒ Object
- .normalize_points(p) ⇒ Object
- .options=(a) ⇒ Object
Class Method Details
.add_flyto(p) ⇒ Object
This is the only function in the module that users are expected to call, and even then users should probably use the tour_from_points function. The p argument contains an ordered array of points, where each point is represented as an array consisting of longitude, latitude, and altitude, in that order. This will add a series of gx:FlyTo objects following the path determined by those points. – XXX Have some way to adjust FlyTo duration based on the distance between points, or based on user input. ++
334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'lib/kamelopard/helpers.rb', line 334 def TelemetryProcessor.add_flyto(p) p2 = TelemetryProcessor::normalize_points p p = p2 heading = get_heading p tilt = get_tilt p # roll = get_roll(last_last_lon, last_last_lat, last_lon, last_lat, lon, lat) roll = get_roll p #p = Kamelopard::Point.new last_lon, last_lat, last_alt, { :altitudeMode => :absolute } point = Kamelopard::Point.new p[1][0], p[1][1], p[1][2], { :altitudeMode => :absolute } c = Kamelopard::Camera.new point, { :heading => heading, :tilt => tilt, :roll => roll, :altitudeMode => :absolute } f = Kamelopard::FlyTo.new c, { :duration => @@options[:pause], :mode => :smooth } f.comment = "#{p[1][0]} #{p[1][1]} #{p[1][2]} to #{p[2][0]} #{p[2][1]} #{p[2][2]}" end |
.fix_coord(a) ⇒ Object
318 319 320 321 322 |
# File 'lib/kamelopard/helpers.rb', line 318 def TelemetryProcessor.fix_coord(a) a = a - 360 if a > 180 a = a + 360 if a < -180 a end |
.get_dist2(x1, y1, x2, y2) ⇒ Object
279 280 281 |
# File 'lib/kamelopard/helpers.rb', line 279 def TelemetryProcessor.get_dist2(x1, y1, x2, y2) Math.sqrt( (x2 - x1)**2 + (y2 - y1)**2).abs end |
.get_dist3(x1, y1, z1, x2, y2, z2) ⇒ Object
283 284 285 |
# File 'lib/kamelopard/helpers.rb', line 283 def TelemetryProcessor.get_dist3(x1, y1, z1, x2, y2, z2) Math.sqrt( (x2 - x1)**2 + (y2 - y1)**2 + (z2 - z1)**2 ).abs end |
.get_heading(p) ⇒ Object
271 272 273 274 275 276 277 |
# File 'lib/kamelopard/helpers.rb', line 271 def TelemetryProcessor.get_heading(p) x1, y1, x2, y2 = [ p[1][0], p[1][1], p[2][0], p[2][1] ] h = Math.atan((x2-x1) / (y2-y1)) * 180 / Pi h = h + 180.0 if y2 < y1 h end |
.get_roll(p) ⇒ Object
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/kamelopard/helpers.rb', line 298 def TelemetryProcessor.get_roll(p) x1, y1, x2, y2, x3, y3 = [ p[0][0], p[0][1], p[1][0], p[1][1], p[2][0], p[2][1] ] return 0 if x1.nil? or x2.nil? # Measure roll based on angle between P1 -> P2 and P2 -> P3. To be really # exact I ought to take into account altitude as well, but ... I don't want # to # Set x2, y2 as the origin xn1 = x1 - x2 xn3 = x3 - x2 yn1 = y1 - y2 yn3 = y3 - y2 # Use dot product to get the angle between the two segments angle = Math.acos( ((xn1 * xn3) + (yn1 * yn3)) / (get_dist2(0, 0, xn1, yn1).abs * get_dist2(0, 0, xn3, yn3).abs) ) * 180 / Pi @@options[:exaggerate] * (angle - 180) end |
.get_tilt(p) ⇒ Object
287 288 289 290 291 292 293 294 295 296 |
# File 'lib/kamelopard/helpers.rb', line 287 def TelemetryProcessor.get_tilt(p) x1, y1, z1, x2, y2, z2 = [ p[1][0], p[1][1], p[1][2], p[2][0], p[2][1], p[2][2] ] smoothing_factor = 10.0 dist = get_dist3(x1, y1, z1, x2, y2, z2) dist = dist + 1 # + 1 to avoid setting dist to 0, and having div-by-0 errors later t = Math.atan((z2 - z1) / dist) * 180 / Pi / @@options[:exaggerate] # the / 2.0 is just because it looked nicer that way 90.0 + t end |
.normalize_points(p) ⇒ Object
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
# File 'lib/kamelopard/helpers.rb', line 352 def TelemetryProcessor.normalize_points(p) # The whole point here is to prevent problems when you cross the poles or the dateline # This could have serious problems if points are really far apart, like # hundreds of degrees. This seems unlikely. lons = ((0..2).collect { |i| p[i][0] }) lats = ((0..2).collect { |i| p[i][1] }) lon_min, lon_max = lons.minmax lat_min, lat_max = lats.minmax if (lon_max - lon_min).abs > 200 then (0..2).each do |i| lons[i] += 360.0 if p[i][0] < 0 end end if (lat_max - lat_min).abs > 200 then (0..2).each do |i| lats[i] += 360.0 if p[i][1] < 0 end end return [ [ lons[0], lats[0], p[0][2] ], [ lons[1], lats[1], p[1][2] ], [ lons[2], lats[2], p[2][2] ], ] end |
.options=(a) ⇒ Object
348 349 350 |
# File 'lib/kamelopard/helpers.rb', line 348 def TelemetryProcessor.(a) @@options = a end |