gpsd-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [gpsd-dev] [PATCH 2/2] Adds skyview rotation support to xgps and xgp


From: Gary E. Miller
Subject: Re: [gpsd-dev] [PATCH 2/2] Adds skyview rotation support to xgps and xgpsspeed.
Date: Thu, 22 Sep 2016 18:30:41 -0700

Yo Fred!

Pulled.  I'll push after a few more pulls.

On Thu, 22 Sep 2016 16:28:36 -0700
Fred Wright <address@hidden> wrote:

> This adds an optional argument to rotate the skyview display, making
> it possible to orient it correctly based on the direction one is
> actually facing.  The specified heading is positioned at the top.
> 
> This edit does not update contrib/webgps.py, which is somewhat
> more complicated to fix due to the Javascript involvement (not to
> mention the rather crude argument parsing).
> 
> TESTED:
> Ran both programs with and without the -r or --rotate option.
> ---
>  xgps      | 37 +++++++++++++++++++------------
>  xgpsspeed | 75
> +++++++++++++++++++++++++++++++++++++-------------------------- 2
> files changed, 67 insertions(+), 45 deletions(-)
> 
> diff --git a/xgps b/xgps
> index 066401f..44ea062 100755
> --- a/xgps
> +++ b/xgps
> @@ -3,7 +3,7 @@
>  '''
>  xgps -- test client for gpsd
>  
> -usage: xgps [-D level] [-hV?] [-l degmfmt] [-u units]
> [server[:port[:device]]] +usage: xgps [-D level] [-hV?] [-l degmfmt]
> [-u units] [-r rotation] [server[:port[:device]]] '''
>  
>  # This code runs compatibly under Python 2 and 3.x for x >= 2.
> @@ -95,7 +95,7 @@ class SkyView(Gtk.DrawingArea):
>      HORIZON_PAD = 40    # How much whitespace to leave around horizon
>      SAT_RADIUS = 5      # Diameter of satellite circle
>  
> -    def __init__(self):
> +    def __init__(self, rotate=0.0):
>          GObject.GObject.__init__(self)
>          self.set_size_request(400, 400)
>          self.cr = None   # New cairo context for each expose event
> @@ -104,6 +104,7 @@ class SkyView(Gtk.DrawingArea):
>          self.connect('draw', self.on_draw)
>          self.satellites = []
>          self.center_x = self.center_y = self.radius = None
> +        self.rotate = rotate
>  
>      def on_size_allocate(self, _unused, allocation):
>          width = allocation.width
> @@ -181,6 +182,7 @@ class SkyView(Gtk.DrawingArea):
>  
>      def pol2cart(self, az, el):
>          "Polar to Cartesian coordinates within the horizon circle."
> +        az = (az - self.rotate) % 360.0
>          az *= (math.pi / 180)  # Degrees to radians
>          # Exact spherical projection would be like this:
>          # el = sin((90.0 - el) * DEG_2_RAD);
> @@ -223,14 +225,14 @@ class SkyView(Gtk.DrawingArea):
>          self.draw_line(x1, y1, x2, y2)
>  
>          # The compass-point letters
> -        (x, y) = self.pol2cart(0, 0)
> -        self.draw_string(x, y - 10, "N")
> -        (x, y) = self.pol2cart(90, 0)
> -        self.draw_string(x + 10, y, "E")
> -        (x, y) = self.pol2cart(180, 0)
> -        self.draw_string(x, y + 10, "S")
> -        (x, y) = self.pol2cart(270, 0)
> -        self.draw_string(x - 10, y, "W")
> +        (x, y) = self.pol2cart(0, -5)
> +        self.draw_string(x, y, "N")
> +        (x, y) = self.pol2cart(90, -5)
> +        self.draw_string(x, y, "E")
> +        (x, y) = self.pol2cart(180, -5)
> +        self.draw_string(x, y, "S")
> +        (x, y) = self.pol2cart(270, -5)
> +        self.draw_string(x, y, "W")
>  
>          # The satellites
>          self.cr.set_line_width(2)
> @@ -460,8 +462,9 @@ class Base(object):
>          ("EPD", lambda s, r: s.update_err_degrees(r, "epd")),
>      )
>  
> -    def __init__(self, deg_type):
> +    def __init__(self, deg_type, rotate=0.0):
>          self.deg_type = deg_type
> +        self.rotate = rotate
>          self.conversions = unit_adjustments()
>          self.saved_mode = -1
>          self.ais_latch = False
> @@ -579,7 +582,7 @@ class Base(object):
>  
>          viewframe = Gtk.Frame(label="Skyview")
>          self.satbox.add(viewframe)
> -        self.skyview = SkyView()
> +        self.skyview = SkyView(self.rotate)
>          viewframe.add(self.skyview)
>  
>          self.rawdisplay = Gtk.Entry()
> @@ -869,11 +872,12 @@ class Base(object):
>  if __name__ == "__main__":
>      try:
>          import getopt
> -        (options, arguments) = getopt.getopt(sys.argv[1:],
> "D:hl:u:V?",
> +        (options, arguments) = getopt.getopt(sys.argv[1:],
> "D:hl:u:r:V?", ['verbose'])
>          debug = 0
>          degreefmt = 'd'
>          unit_system = None
> +        rotate = 0.0
>          for (opt, val) in options:
>              if opt in '-D':
>                  debug = int(val)
> @@ -881,6 +885,11 @@ if __name__ == "__main__":
>                  degreeformat = val
>              elif opt == '-u':
>                  unit_system = val
> +            elif opt == '-r':
> +                try:
> +                    rotate = float(val)
> +                except ValueError:
> +                    rotate = 0.0
>              elif opt in ('-?', '-h', '--help'):
>                  print(__doc__)
>                  sys.exit(0)
> @@ -902,7 +911,7 @@ if __name__ == "__main__":
>              if len(args) >= 3:
>                  device = args[2]
>  
> -        base = Base(deg_type=degreefmt)
> +        base = Base(deg_type=degreefmt, rotate=rotate)
>          base.set_units(unit_system)
>          try:
>              daemon = gps.gps(host=host,
> diff --git a/xgpsspeed b/xgpsspeed
> index 277b575..29a6fc7 100755
> --- a/xgpsspeed
> +++ b/xgpsspeed
> @@ -228,7 +228,7 @@ class NauticalSpeedometer(Speedometer):
>      HEADING_SAT_GAP = 0.8
>      SAT_SIZE = 10  # radius of the satellite circle in skyview
>  
> -    def __init__(self, speed_unit=None, maxspeed=100):
> +    def __init__(self, speed_unit=None, maxspeed=100, rotate=0.0):
>          Speedometer.__init__(self, speed_unit)
>          self.connect('size-allocate', self.on_size_allocate)
>          self.width = self.height = 0
> @@ -240,9 +240,9 @@ class NauticalSpeedometer(Speedometer):
>          self.satellites = []
>          self.last_heading = 0
>          self.maxspeed = int(maxspeed)
> +        self.rotate = radians(rotate)
>  
> -    @staticmethod
> -    def polar2xy(radius, angle, polex, poley):
> +    def polar2xy(self, radius, angle, polex, poley):
>          '''convert Polar coordinate to Cartesian coordinate system
>          the y axis in pygtk points downward
>          Args:
> @@ -250,6 +250,7 @@ class NauticalSpeedometer(Speedometer):
>             angle: azimuth from from Polar coordinate system, in
> radian polex and poley are the Cartesian coordinate of the pole
>          return a tuple contains (x, y)'''
> +        angle = (angle + self.rotate) % (pi * 2)  # Note reversed
> sense return (polex + cos(angle) * radius, poley - sin(angle) *
> radius) 
>      def on_size_allocate(self, _unused, allocation):
> @@ -306,12 +307,12 @@ class NauticalSpeedometer(Speedometer):
>          for i in range(11):
>              # draw the large ticks
>              alpha = (8 - i) * pi / 6
> -            self.cr.move_to(*NauticalSpeedometer.polar2xy(rspeed,
> alpha, x, y))
> +            self.cr.move_to(*self.polar2xy(rspeed, alpha, x, y))
>              self.cr.set_line_width(radius / 100)
> -            self.cr.line_to(*NauticalSpeedometer.polar2xy(rspeed -
> s_long, alpha, x, y))
> +            self.cr.line_to(*self.polar2xy(rspeed - s_long, alpha,
> x, y)) self.cr.stroke()
>              self.cr.set_line_width(radius / 200)
> -            xf, yf = NauticalSpeedometer.polar2xy(rspeed + 10,
> alpha, x, y)
> +            xf, yf = self.polar2xy(rspeed + 10, alpha, x, y)
>              stxt = (self.maxspeed // 10) * i
>              self.draw_text(xf, yf, stxt, fontsize=radius / 15)
>  
> @@ -319,14 +320,14 @@ class NauticalSpeedometer(Speedometer):
>              # middle tick
>              alpha = (8 - i) * pi / 6
>              beta = (17 - 2 * i) * pi / 12
> -            self.cr.move_to(*NauticalSpeedometer.polar2xy(rspeed,
> beta, x, y))
> -            self.cr.line_to(*NauticalSpeedometer.polar2xy(rspeed -
> s_middle, beta, x, y))
> +            self.cr.move_to(*self.polar2xy(rspeed, beta, x, y))
> +            self.cr.line_to(*self.polar2xy(rspeed - s_middle, beta,
> x, y)) 
>              #  short tick
>              for n in range(10):
>                  gamma = alpha + n * pi / 60
> -
> self.cr.move_to(*NauticalSpeedometer.polar2xy(rspeed, gamma, x, y))
> -                self.cr.line_to(*NauticalSpeedometer.polar2xy(rspeed
> - s_short, gamma, x, y))
> +                self.cr.move_to(*self.polar2xy(rspeed, gamma, x, y))
> +                self.cr.line_to(*self.polar2xy(rspeed - s_short,
> gamma, x, y)) 
>          # draw the heading arc
>          self.cr.new_sub_path()
> @@ -342,7 +343,7 @@ class NauticalSpeedometer(Speedometer):
>              label = str(n * 90)
>              # self.cr.set_source_rgba(0, 1, 0)
>              # radius * (1 + NauticalSpeedometer.HEADING_SAT_GAP),
> -            tbox_x, tbox_y = NauticalSpeedometer.polar2xy(
> +            tbox_x, tbox_y = self.polar2xy(
>                  radius * 0.88,
>                  (1 - n) * pi / 2,
>                  x, y)
> @@ -359,13 +360,14 @@ class NauticalSpeedometer(Speedometer):
>          self.cr.set_source_rgba(0, 0, 0)
>  
>          self.cr.arc(x, y, skyradius * 2 / 3, 0, 2 * pi)
> +        self.cr.move_to(x + skyradius / 3, y)  # Avoid line
> connecting circles self.cr.arc(x, y, skyradius / 3, 0, 2 * pi)
>  
>          # draw the cross hair
> -        self.cr.move_to(x - skyradius, y)
> -        self.cr.line_to(x + skyradius, y)
> -        self.cr.move_to(x, y - skyradius)
> -        self.cr.line_to(x, y + skyradius)
> +        self.cr.move_to(*self.polar2xy(skyradius, 1.5 * pi, x, y))
> +        self.cr.line_to(*self.polar2xy(skyradius, 0.5 * pi, x, y))
> +        self.cr.move_to(*self.polar2xy(skyradius, 0.0, x, y))
> +        self.cr.line_to(*self.polar2xy(skyradius, pi, x, y))
>          self.cr.set_line_width(radius / 200)
>          self.cr.stroke()
>  
> @@ -376,22 +378,22 @@ class NauticalSpeedometer(Speedometer):
>          # draw the large ticks
>          for i in range(12):
>              agllong = i * pi / 6
> -            self.cr.move_to(*NauticalSpeedometer.polar2xy(radius -
> long_inset, agllong, x, y))
> -            self.cr.line_to(*NauticalSpeedometer.polar2xy(radius,
> agllong, x, y))
> +            self.cr.move_to(*self.polar2xy(radius - long_inset,
> agllong, x, y))
> +            self.cr.line_to(*self.polar2xy(radius, agllong, x, y))
>              self.cr.set_line_width(radius / 100)
>              self.cr.stroke()
>              self.cr.set_line_width(radius / 200)
>  
>              # middle tick
>              aglmid = (i + 0.5) * pi / 6
> -            self.cr.move_to(*NauticalSpeedometer.polar2xy(radius -
> mid_inset, aglmid, x, y))
> -            self.cr.line_to(*NauticalSpeedometer.polar2xy(radius,
> aglmid, x, y))
> +            self.cr.move_to(*self.polar2xy(radius - mid_inset,
> aglmid, x, y))
> +            self.cr.line_to(*self.polar2xy(radius, aglmid, x, y))
>  
>              #  short tick
>              for n in range(1, 10):
>                  aglshrt = agllong + n * pi / 60
> -                self.cr.move_to(*NauticalSpeedometer.polar2xy(radius
> - short_inset, aglshrt, x, y))
> -
> self.cr.line_to(*NauticalSpeedometer.polar2xy(radius, aglshrt, x, y))
> +                self.cr.move_to(*self.polar2xy(radius - short_inset,
> aglshrt, x, y))
> +                self.cr.line_to(*self.polar2xy(radius, aglshrt, x,
> y)) self.cr.stroke()
>  
>      def draw_heading(self, trig_height, heading, radius, x, y):
> @@ -419,16 +421,16 @@ class NauticalSpeedometer(Speedometer):
>          self.cr.stroke()
>  
>          # heading text
> -        (tbox_x, tbox_y) = NauticalSpeedometer.polar2xy(radius *
> 1.1, h, x, y)
> +        (tbox_x, tbox_y) = self.polar2xy(radius * 1.1, h, x, y)
>          self.draw_text(tbox_x, tbox_y, int(heading),
> fontsize=radius / 15) 
>          # the ship shape, based on test and try
>          shiplen = radius * NauticalSpeedometer.HEADING_SAT_GAP / 4
> -        xh, yh = NauticalSpeedometer.polar2xy(shiplen * 2.3, h, x, y)
> -        xa, ya = NauticalSpeedometer.polar2xy(shiplen * 2.2, h + pi
> - 0.3, x, y)
> -        xb, yb = NauticalSpeedometer.polar2xy(shiplen * 2.2, h + pi
> + 0.3, x, y)
> -        xc, yc = NauticalSpeedometer.polar2xy(shiplen * 1.4, h -
> pi / 5, x, y)
> -        xd, yd = NauticalSpeedometer.polar2xy(shiplen * 1.4, h +
> pi / 5, x, y)
> +        xh, yh = self.polar2xy(shiplen * 2.3, h, x, y)
> +        xa, ya = self.polar2xy(shiplen * 2.2, h + pi - 0.3, x, y)
> +        xb, yb = self.polar2xy(shiplen * 2.2, h + pi + 0.3, x, y)
> +        xc, yc = self.polar2xy(shiplen * 1.4, h - pi / 5, x, y)
> +        xd, yd = self.polar2xy(shiplen * 1.4, h + pi / 5, x, y)
>  
>          self.cr.set_source_rgba(0, 0.3, 0.2, 0.5)
>          self.cr.move_to(xa, ya)
> @@ -460,7 +462,7 @@ class NauticalSpeedometer(Speedometer):
>          self.cr.set_line_width(2)
>          self.cr.set_source_rgb(0, 0, 0)
>  
> -        x0, y0 = NauticalSpeedometer.polar2xy(radius * (90 - el) //
> 90, h, x, y)
> +        x0, y0 = self.polar2xy(radius * (90 - el) // 90, h, x, y)
>  
>          self.cr.new_sub_path()
>          if gps.is_sbas(satsoup['PRN']):
> @@ -515,7 +517,7 @@ class NauticalSpeedometer(Speedometer):
>  
>  class Main(object):
>      def __init__(self, host='localhost', port='2947', device=None,
> debug=0,
> -                 speed_unit=None, maxspeed=0, nautical=False):
> +                 speed_unit=None, maxspeed=0, nautical=False,
> rotate=0.0): self.host = host
>          self.port = port
>          self.device = device
> @@ -523,6 +525,7 @@ class Main(object):
>          self.speed_unit = speed_unit
>          self.maxspeed = maxspeed
>          self.nautical = nautical
> +        self.rotate = rotate
>          self.window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
>          if not self.window.get_display():
>              raise Exception("Can't open display")
> @@ -531,7 +534,8 @@ class Main(object):
>              self.window.set_size_request(500, 550)
>              self.widget = NauticalSpeedometer(
>                  speed_unit=self.speed_unit,
> -                maxspeed=self.maxspeed)
> +                maxspeed=self.maxspeed,
> +                rotate=self.rotate)
>          else:
>              self.widget = LandSpeedometer(speed_unit=self.speed_unit)
>          self.window.connect('delete_event', self.delete_event)
> @@ -735,6 +739,14 @@ if __name__ == '__main__':
>          type='int',
>          help='Set level of debug. Must be integer. [Default 0]'
>      )
> +    parser.add_option(
> +        '--rotate',
> +        dest='rotate',
> +        default=0,
> +        action='store',
> +        type='float',
> +        help='Rotation of skyview ("up" direction) in degrees.
> [Default 0]'
> +    )
>      (options, args) = parser.parse_args()
>      if args:
>          arg = args[0].split(':')
> @@ -755,5 +767,6 @@ if __name__ == '__main__':
>          speed_unit=options.speedunits,
>          maxspeed=options.maxspeed,
>          nautical=options.nautical,
> -        debug=options.debug
> +        debug=options.debug,
> +        rotate=options.rotate,
>      ).run()




RGDS
GARY
---------------------------------------------------------------------------
Gary E. Miller Rellim 109 NW Wilmington Ave., Suite E, Bend, OR 97703
        address@hidden  Tel:+1 541 382 8588

Attachment: pgpn3qgjqH0jh.pgp
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]