Sunday, July 29, 2012

NMEA Station Calibration

We intend here to show the importance and the impact of an accurate calibration and tuning of your NMEA station, in order to correctly evaluate the parameters to calculate, namely the current direction and speed. The impact of an incorrect tuning leads to completely useless computation, and wrong evaluation of the expected parameters.
For a better understanding of the mutual impact of all those parameters, we've illustrated this document with several interactive applets, which you can play with or interact with the different parameters for yourself.
Values in fields can be changed (hit the [Enter] key for that, after modifying the value in the field), sliders are draggable with the mouse, as well as the compasses that figure in the applets, to change the various headings.

Steps

In order to log and visualize data efficiently, you need to complete several steps, in a specific order:
  1. Instruments Calibration
    You need to make sure the values read by your instruments are accurate
  2. Polars Elaboration
    You need to know what your speed should be in the condition you sail in
  3. Data Logging
    You need to log the right data
  4. Data Visualization
    You need to render the logged data appropriately, rate your tacks and gybes, visualize laylines and frames, etc.

Instruments Calibration

Most of the in-board NMEA stations provide access to calibration parameters that will lead to an accurate data logging and display. The goal of this process is to evaluate the parameters we will need to feed the NMEA station with.
You need to simulate the values of the parameters to enter in the NMEA station. This process follows several steps:
  1. Log data on the boat
  2. Display the data in some graphical dashboard
  3. Elaborate the calibration parameters until the display looks good
  4. Set the calibration parameters in the NMEA station
  5. Log again, to make sure your evaluation of the tuning parameters was right

Polars Elaboration

Polars are a mathematic and theoric model that will tell you what BSP you should theorically reach for a given TWA and TWS.
Polars can be used to predict your potential track (routing), or to rank your boat handling.
There are two main ways to get the polars of your boat:
  • VPP (Velocity Prediction Programs)
    Those data are (or should be) provided by the designer of your boat.
  • Logging
    In case your designer did not provide them, or if the VPP is wrong...

Data Logging

For an appropriate rendering of your performances, you need to log the right set of data. The format of the data logged by your navigation station is NMEA.
Depending of the data your station is able to produce, you will have to choose the right ones.

Data Visualization

The main question to address is "What do you want to see?". And there is no ready-made answer to that question.

To summarize

  1. Appropriate Calibration leads to the right evaluation of the True Wind (Angle, Speed and Direction) and of the Current (Speed and Direction)
  2. With the right evaluation of the True Wind, you can refer to your polars, so you know what your speed should be
  3. Having logged the right data, comparing them to what the polars tell you, you can evaluate your performances
  4. Based on the evaluation of your performances, you can render your data appropriately, see where you did good, and where there is room for improvement


Instruments Calibration

Calibration impacts the data read on the boat through the devices attached to the NMEA station, like the boat speed transducer, the compass, the wind vane, and the anemometer.
We want here to
  1. show how the different data interact with each other
  2. see how to apply calibration factors (coefficients and offsets) to the values read from the station

The data are logged on the boat, that carries the devices (speedometer, compass, wind vane, anemometer).
It is far from unusual to have to tweak or tune those devices.
The anemometer is usually the most reliable one, as it is running away from most of the interferences that make the other devices in need for calibration.
For example, the compass and the wind vane could have been installed not exactly in line with the boat. This means that an offset is to be applied to the data they read.
Depending on the location of the boat speed transducer, the speed of the molecules of water does not necessary directly reflect the speed of the boat. A difference can even be seen from one tack to the other. A coefficient might then be required.
Many data can be recorded, we're only - in this document - going to talk about the data we need to evaluate the performances of the boat.
For example, DBT (Depth Below Transducer) is useless for us, in the framework on this document.
The main data recorded by the instruments are:
  • Boat Speed (BSP), sometimes aka STW (Speed Through Water)
  • Heading (HDG, HDM, HDT)
  • Apparent Wind Speed (AWS)
  • Apparent Wind Angle (AWA)
  • Boat Position (from the GPS)
  • Speed Over Ground (SOG)
  • Course Over Ground (COG)
One data is to be estimated:
  • Leeway (see about that the section about Damping)
    Mostly depends on AWA, AWS, and sea state (that involves waves, swell direction... pretty tricky).
The main data computed, based on the data above, are:
  • True Wind Speed (TWS)
    Depends on COG & SOG, AWA, AWS.
    Not on BSP & HDG, as usually admitted.
  • True Wind Angle (TWA)
    Depends on COG & SOG, AWA, AWS.
    Not on BSP & HDG, as usually admitted.
  • True Wind Direction (TWD)
    Depends on TWA, HDG
  • Current Speed
    Depends on BSP, HDG, SOG, COG, Leeway.
  • Current Direction
    Depends on BSP, HDG, SOG, COG, Leeway.
Note: The tuple (SOG, COG) is semantically (in this case) equivalent to the Boat Position. Both (SOG, COG) and Boat Position come from the GPS.
A note about BSP calibration:
This one can be very tricky, specially if the transducer is not exactly set in the axis of the boat, as it is usually the case.
When you're sailing upwind, depending on the tack, the reading may substancially vary, as for a given speed, the pressure of the water molecules on the transducer is definitely not the same on both tacks, the difference of reading between tacks being more or less proportional to the heel.
To address that issue, most of the NMEA Stations provide a way to set the boat speed calibration for each tacks.
Unfortunatelly, this is not good enough, the Apparent Wind Angle should be taken in account as well. You certainly do not want the same coefficient to be applied on the boat speed when you are heading close hauled or running downwind.

Calibrating the Boat Speed and Heading

Here is an interactive applet:

This browser does not support Applets.
This applet shows how to evaluate/compute the current. It provides the possibility to interact with the calibration parameters and see how they impact the final resiult.
Use the sliders in the applet on the left to modify the values of Boat Speed (BSP) and Leeway.
To change the Heading (HDG) value, drag the mouse over the compass.
Course Over Ground is fixed, set to 80°.
Speed Over Ground is fixed, set to 5.5 knots.
Both COG and SOG come from the GPS.
Current Speed & Direction are computed based on the five values above.
In green, data read from the NMEA Station
In red, parameters used for computation
In blue, computed data

At the bottom, are two calibration parameters.
The BSP Coefficient is applied to the Boat Speed.
The HDG Offset is added to the Heading.
To modify a parameter, change its value, and hit the [Enter] key.
The display on the right side render the value read by the station. The pane on the left displays the corrected values, used for the computing of the current.

Something to say about leeway:
Leeway - mentionned above, and used below - is a dimension proportional (among others) to the Apparent Wind Angle (AWA), and not the True Wind Angle (TWA).
The Apparent Wind is the wind moving the boat.
Sailing on a very fast boat (like a racing multihull, an ice-boat, etc), it is not unusual to fell the wind on the nose, and see the wind-generated waves (not on an ice-boat, I know) coming from the quarter. The sails are trimmed according to the Apparent Wind, and the force they generate is expressed accordingly.
If your sails are trimmed as if you're going upwind (i.e. up the Apparent Wind), then you make leeway accordingly.
Picture this:
Sailing in the same external conditions (TWD, TWS), we have two boats, well trimmed, sailing at about 135° of the True Wind (TWA=135°):
  • A cruising monohull, sailing between 6 and 8 knots
  • A racing multihull, sailing above 25 knots
The first one will be sailing with the spinnaker up.
The second will have - in the best case scenario - a closed hauled gennaker.

Obiously, their leeway will not depend on the same parameters.
The fast boat will make more leeway than the cruising one, because of his close hauled sails.
For now, in the Dashboard Preferences, you have a value named "Max Leeway". This value will be used in conjunction with the Apparent Wind Angle, when it is between 0°and 90°, as follow:
Leeway = MaxLeeway × cos(awa)
This browser does not support Applets.
The True Heading, corrected with the Leeway is called Course Made Good (CMG).

Calibration of the Compass

Usually under-estimated! You think that because you sail on a plastic boat, your compass does not suffer any deviation... Think again!
Unless you have a gyroscope, you will need a compass to know what your heading is. Your heading is the base of many calculations, see above.
The first parameter to take in account id the magnetic declination, noted D. This Declination depends on your location, and the time. It varies with time, because the magnetic pole navigates around the geographical one. Any nautical chart will tell you what the declination is in the region and at the time your sail. You can get its value from several web-sites, including the NOAA's one. The RMC sentence also returns this data. Some computer algorythms are also available to calculate this important datum. Declination is the same for everyone sailing the same waters at the same time.
This is not the case of the deviation. The deviation is a parameter depending on the boat you sail. It is generated by the magnetic masses around the compas. As such, it depends:
  • On the boat (holding those magnetic masses)
  • The heading, as those masses "move" around the compass.
Steel boats have a big one, ferro-cement ones have a huge one (50° is not absurd for them...). Plastic boats, you never know! A loudspeaker close to a compass will have quite an impact on its reading... An engine (or a generator), same. When the engine is running, it might even be different... There is a lot of litterature about this topic, go check for yourself if you are interested.

This browser does not support Applets.
The generic shape of a deviation curve is
d = A + (B.sin(Z)) + (C.cos(Z)) + (D.sin(2.Z)) + (E.cos(2.Z))
where Z is the magnetic heading. The deviation curve represented on the left is following this equation.

This interactive applet shows the 3 different headings: True, Magnetic, and Compass.
The Compass is the displayed (and recorded) one.
You can modify the value of the Magnetic Declination.
Plus (+) is East, minus (-) is West, for Declination and deviation.
The algebric sum of the Declination and of the deviation is called Variation, noted W.

The true heading is the one to be plotted on the chart, as the chart too refers to the true North (a.k.a. Geographical North).
The compass calibration is crucial. The data it provides is a parameter of all the computations we are interested in. If the deviation is not taken in account, its value will be put on the current's account, and that would be a big mistake.

Calibration of the Apparent Wind Speed and Direction


Here is another interactive applet. Like before, you can use the sliders, modify the values in the fields (hit the [Enter] key in the field to apply your changes), and drag the compass' rose left or right.

This browser does not support Applets.
This one shows how the calibration of the station interacts with the computation of the True Wind, which is the key to access the polars.
The displays (on the right) are the one you would see on the boat when sailing, the data displayed on the main pane, on the left, are the (ideally) "real" data, taking the calibration parameters in account.

Warning:
This vector combination is the usually admitted one, but this is a simplified one!
The real one - closer to the truth - will be exposed next.

Let's now go closer to the truth...
Unlike what's commonly admitted, the True Wind should be calculated with the Speed Over Ground and the Course Over Ground, instead of respectively the Boat Speed and the Heading.
Imagine that: you are "sailing" in absolutely NO wind, but you have a strong current, about 6 knots. Well, in that case, you feel an apparent wind of about 6 knots. If you do the calculation of the True Wind with the Boat Speed, the calculation will return a True Wind of 6 knots, in the direction opposite to the current.
But if you do it with the Course Over Ground and Speed Over Ground, then it will return a True Wind Speed of zero knot, which is right.
If the GPS data are available, they should be preferred for this computation.


This browser does not support Applets.
This one contains all the possible parameters (for now...), and computes the True Wind with the GPS Data (SOG & COG).

For the clarity of the figure, Compass calibration parameters (deviation curve) are not represented.

All the values are modifiable like previously. Heading and Course Over Ground have their own compass' rose, which is dragable on both cases.

As you can tell, the figure is quite complex. And it becomes even more complex when you modify the data and parameters.
Again, it is very difficult to isolate the parameters from each other, modifying one value impacts mostly all of the others...

As a matter of fact this reflects the reality of an NMEA Station calibration. It is a long and precise process, which should not be under-estimated.

Ultimately, what we look for here is the direction and the speed of the current, represented in green on the applet on the left, as this is what we will compute the route to give to the driver with, decide when to tack, etc.
All the parameters we mentionned so far have a direct impact on this evaluation. If one of them is wrong, then the evaluation of the current is impacted.


Full validation: Stability of True Wind Direction and Current Direction

Now, let's put all the parameters together, as in the real world. The main difficulty is precisely due to this fact, there is no clear way to isolate them...
Below is the display of some data logging, the logging is done with a non-well calibrated NMEA station.
It displays two legs upwind, and two legs downwind.
The True Wind Direction is displayed in blue, the Current Direction is displayed in red,
The vertical panes on the left display the True Wind Direction (TWD), and the Current Direction (CDR).
The horizontal panes display the Boat Speed (BSP), True Wind Speed (TWS) and Current Speed (CSP).
TWD, CDR, TWS, TWA and CSP are calculated, based on the data logged on board. Any error in the data read from the devices (BSP, HDG, AWA, AWS) will deeply impact this calculation.
You can impact the parameters to apply on the data read from the station by modifying their values on the right pane of the applet.
See how the current direction varies everytime the boat heading is changing... The TWD is less impacted, but it is not steady either.
This browser does not support Applets.
This interactive applet represents data logged with a non properly calibrated NMEA Station.

Play with the parameters, to see how they impact the rendering of the track. To modify a value, change the number in the field and press [Enter].

There is a slider you can use, just above the BSP Panel at the bottom.
To display the right data, you must enter the following parameters:
  • Multiply BSP by 1.1
  • HDG Offset 5°
  • Multiply AWS by 1.01
  • AWA Offset 2°
  • Max Leeway 10°
Those paratemers should be used later on to calibrate your NMEA Station.

Ideally, when the parameters are set correctly, the graphs rendering TWD, CDR, TWS & CSP should display a straight line. (Assuming of course that the wind and current conditions were stable during this logging session)
For now, the leeway is calculated as a function of the Cosinus of the AWA, from 0 to 90 degrees only (we assume no leeway beyond 90° of Apparent Wind Angle).
This is likely to be improved.


Data Logging

Logging everything the station produces is a possibility, but it can be a lot, and saturate the recording device.
For the best rendering, you need to log at least:
  • The Boat Speed (BSP)
  • The Boat Heading (HDG, HDM, or HDT)
  • The Apparent Wind Speed (AWS)
  • The Apparent Wind Angle (AWA)
  • The Boat Position
  • The Course Over Ground (COG)
  • The Speed Over Ground (SOG)
Those data can be found - for example - in the following sentences:
Required DataAvailable in NMEA Sentences
Boat Speed VHW
Boat Heading VHW, HDG, HDM, HDT
Apparent Wind Speed MWV, VWR
Apparent Wind Angle MWV, VWR
Boat Position RMC, GLL
Speed Over Ground RMC, GLL, VTG
Course Over Ground RMC, GLL, VTG
The NMEA sentences mentionned in the table above have the following meaning:
VHW Water Speed and Heading (Velocity Heading Water)
HDG Heading, Deviation & Variation
HDM Heading, Magnetic
HDT Heading, True
MWV Wind Speed and Angle
VWR Relative wind direction and speed (Velocity Wind Relative)
RMC Recommended Minimum Specific GPS/TRANSIT Data
GLL Geographic Position, Latitude/Longitude
VTG Track Made Good and Ground Speed
Note: RMC gives the boat position just like GLL, but also returns the Magnetic Declination.


Data Visualization


Damping

The damping is the kind of smoothing that will eliminate the aberrations. This is specially usefull when the data are logged in tough conditions. For example, when you are sailing upwind in choppy seas, the wind vane being set at the top of the mast will be shaked substancially. This will generate some data that will not reflect the reality.
The damping is taking for any given logged point X points before,and X points after, and calculates the average.

This browser does not support Applets.
Use the slider to change the damping factor.
Several panels of the Dashboard provide access to a damping factor.

A note about current evaluation

The way we've calculated the current so far is based on the values read and calculated at a given moment in time (BSP, TWS, TWD, COG, SOG).
Some of those values are themsleves based on others (TWS & TWA are based on BSP, CMG - based on HDG, leeway, Declination and Deviation -, SOG, COG.
The current calculation we've shown so far is a triangulation based on instant values.
Basing the calculation on damped values does not really help, but there is another way to smooth those values. We have seen that the current is the vector that sits between the tuple (CMG, BSP) and the tuple (COG, SOG).
The idea here is to evaluate over a period of time this difference between the position where the boat is, and the position where it should be with no current.
We can even simultaneously evaluate the current with different period of time, like 1 minute and 10 minutes, for example. This would be usefull when the boat heading is changing, for example when tacking or rounding a mark.
after one tack
After one tack. See the different values in the three panels
after two tacks
After two tacks. See the different values in the three panels
after two tacks, motoring head to wind
After two tacks, motoring head to wind. See the different values in the three panels
Notice in each case the differences between the current speeds, and current directions.

Evaluate and rate your tacks and gybes

We'll be talking here of the method well-known under the name of "Tack Loss".
Its principle is simple, and it is the same for tacks and gybes; we'll expose it for a tack, you'll be after that able to transpose it to a gybe.
  • You're sailing upwind at a constant speed
  • You evaulate you VMG (Velocity Made Good)
  • The tack begins
  • After the tack, and after a given amount of time, you're sailing on the other tack, and you've recovered your best speed
  • This is when the tack is being rated:
    • You calculate, based on the VMG before the tack, how far upwind you would have been if you had not tacked
    • You see how far upwind you actually are
    • You compare the two (the difference is evaluated in meters)
The tack loss is not - as one could expect - always negative. If you appropriately tack in a wind shift, you might have very good ratings!
The opposite can be true as well...
The tack loss is usually evaluated as a distance, measured - even on American and English boats - in meters.
It can also be rendered as a percentage, as we're going to explain.
A tack can be decomposed is three main steps.
  1. You're heading full speed, and you begin the tack. Your VMG increases, due to the momentum of the boat
  2. The boat not being anymore powered by the wind, and having the wind on the nose, the boat (and the VMG) slows down as the wind is crossed
  3. The boat bears away, about to re-catch the wind, the sails will soon be trimmed on the other tack, the boat is recovering its speed
The steps described above correspond to this figure:
Rating the tack as a percentage corresponds to the comparison of those two areas (in grey):

this area in grey...

... with this one.


Next time, we'll talk about the data rendering.
It's also a pretty vast topic.

Friday, July 20, 2012

Smoothing a color chart in Java

The goal here is to smooth a colored drawing, to avoid the tile effect.
Before
After
Although they look similar, the path for the two images above is pretty different.
The regular path to draw on a javax.swing.JPanel is to override the method
  public void paintComponent(Graphics gr)
We have defined an array of colors, for the example
  private final static int[][] COLOR_VALUES =
  {
   {255, 255, 255 },
   {208, 244, 250 },
   {161, 233, 246 },
   {115, 222, 241 },
   {68, 211, 237 },
   {21, 200, 232 },
   {21, 207, 223 },
   {20, 214, 214 },
  ...
   {59, 2, 64 },
   {30, 1, 32 },
   {0, 0, 0 }
  };

The tile panel

The method used to the tile (left) approach would look like this:
  private static JPanel colorPane = new JPanel()
    {
      public void paintComponent(Graphics gr)
      {
        ((Graphics2D)gr).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                                          RenderingHints.VALUE_TEXT_ANTIALIAS_ON);      
        ((Graphics2D)gr).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                          RenderingHints.VALUE_ANTIALIAS_ON);      
        int w = this.getWidth();
        int h = this.getHeight();
        
        paintColors(gr, w, h);

        gr.setColor(Color.black);
        gr.setFont(gr.getFont().deriveFont(40f));
        
        String str = "Some text on top";
        int strWidth  = gr.getFontMetrics(gr.getFont()).stringWidth(str);        
        gr.drawString(str, (w / 2) - (strWidth / 2), (h / 2) + (40 / 2));
      }
      
      private void paintColors(Graphics gr, int w, int h)
      {
        // Draw 7x7
        int wStep = (int)((float)w / 7f);
        int hStep = (int)((float)h / 7f);
        for (int hor=0; hor<7; hor++)
        {
          for (int vert=0; vert<7; vert++)
          {
            Color c = new Color(COLOR_VALUES[(hor * 7) + vert][0],
                                COLOR_VALUES[(hor * 7) + vert][1],
                                COLOR_VALUES[(hor * 7) + vert][2]);
            gr.setColor(c);
            gr.fillRect(hor * wStep, vert * hStep, wStep, hStep);
          }
        }        
      }
    };

The smoothed panel

The other approach is a bit less straightforward.
The way to proceed is to
  • Generate an Image
  • Apply a blur filter on it
  • Display the image
The blur filter could look like this:
  public static BufferedImage blur(BufferedImage bimg, int matrixDim)
  {
    float blurMatrix[] = new float[matrixDim * matrixDim];
    for (int i=0; i< blurMatrix.length; i++)
      blurMatrix[i] = 1f / (float)(matrixDim * matrixDim);

    Kernel kernel = new Kernel(matrixDim, matrixDim, blurMatrix);
    BufferedImageOp blurFilter = new ConvolveOp(kernel, 
                                                ConvolveOp.EDGE_NO_OP,
                                                null);
    bimg = blurFilter.filter(bimg, null);
    return bimg;
  }
And it can be used as follow in the paintComponent method:
      public void paintComponent(Graphics gr)
      {
        ((Graphics2D)gr).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                                          RenderingHints.VALUE_TEXT_ANTIALIAS_ON);      
        ((Graphics2D)gr).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                          RenderingHints.VALUE_ANTIALIAS_ON);      
        int w = this.getWidth();
        int h = this.getHeight();
        
        // Create the image
        BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);       
        // Create a graphics contents on the buffered image
        Graphics2D g2d = bufferedImage.createGraphics();

        this.paintColors((Graphics)g2d, w, h);
        // Graphics context no longer needed so dispose it
        g2d.dispose();
        // Blur it
        bufferedImage = blur(bufferedImage, w / 7);
        // Display it
        gr.drawImage(bufferedImage, 0, 0, null);

        gr.setColor(Color.black);
        gr.setFont(gr.getFont().deriveFont(40f));
        
        String str = "Some text on top";
        int strWidth  = gr.getFontMetrics(gr.getFont()).stringWidth(str);        
        gr.drawString(str, (w / 2) - (strWidth / 2), (h / 2) + (40 / 2));
      }
And that's it!
It's fully compatible with transparency,
  g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));

But beware, depending on the size of the Kernel matrix, the blur operation can be pretty demanding.