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
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. ++
432 433 434 435 436 437 438 439 440 441 442 443 444 |
# File 'lib/kamelopard/helpers.rb', line 432 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
416 417 418 419 420 |
# File 'lib/kamelopard/helpers.rb', line 416 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
377 378 379 |
# File 'lib/kamelopard/helpers.rb', line 377 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
381 382 383 |
# File 'lib/kamelopard/helpers.rb', line 381 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
369 370 371 372 373 374 375 |
# File 'lib/kamelopard/helpers.rb', line 369 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 / Math::PI h = h + 180.0 if y2 < y1 h end |
.get_roll(p) ⇒ Object
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
# File 'lib/kamelopard/helpers.rb', line 396 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 / Math::PI @@options[:exaggerate] * (angle - 180) end |
.get_tilt(p) ⇒ Object
385 386 387 388 389 390 391 392 393 394 |
# File 'lib/kamelopard/helpers.rb', line 385 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 / Math::PI / @@options[:exaggerate] # the / 2.0 is just because it looked nicer that way 90.0 + t end |
.normalize_points(p) ⇒ Object
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 |
# File 'lib/kamelopard/helpers.rb', line 450 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
446 447 448 |
# File 'lib/kamelopard/helpers.rb', line 446 def TelemetryProcessor.(a) @@options = a end |