tom-r / tactics_pi

a performance enhancement of dashboard_pi for OpenCPN
16 stars 14 forks source link

JW's suggested CalculateCurrent() mods #16

Closed ghost closed 7 years ago

ghost commented 7 years ago

Hi, Thomas, by no means this is to suggest that you take this code submitted by Johnny Walker in http://www.cruisersforum.com/forums/f134/tactics-plugin-166909-22.html#post2428026 - but since I typed it in to try it, that would save you the trouble in case you want to try it... :)

tom-r commented 7 years ago

I'll try it out. This will need thorough testing and take a couple of days...

ghost commented 7 years ago

Let me know if I can help. I have not managed to make a Debug version on Windows. If there's no wind maybe I'll drop down this branch on my Linux machine this weekend and try with gdb - verify the smoothing function would be difficult still - in a test with my data I got only 3% difference in smoothed values and I wonder is it worthwhile to do use three extra trigonometric operations to obtain that...

tom-r commented 7 years ago

Petri,

thanks for your help, I had a quick check and it does not really work as expected. I'm in the comfortable situation that I can do a live comparison, as the NKE Multigraphic instrument does an internal current calculation as well :-) I'm not sure if he really understood the purpose of the sin / cos splitting of currdir. We do already have a valid vector for the current (direction + speed) right in top of the code as output of

"DistanceBearingMercator_Plugin(COGlat, COGlon, CRSlat, CRSlon, &currdir, &currspd);"

So I see no need to recalculate especially currspd with this trigonometric function. We can simply smooth it right away as done.

The tricky job is to smoothen this really noisy currdir data where we face the challenge to avoid the 0 - 360° problem (350° + 10° + 30° should be an average of 10° and not 390/3 = 130°).

So I'm simply split and summing up the x and y components (sin/cos) of the direction separately and later on recombine it with atan2

I did a short test yesterday and the currspd calculation is way off from NKE's internal calculation (whereas mine was close, within +- 0.02 kts)

What I will investigate again is, if we really need the currspd in the sin / cos calculation. When I designed this, I did some manual calculations with the code and the result was OK then.

PS : I took this somehere from the internet, I think it was on the codeproject site, where someone was dicussing different ways to get around the 0 - 360 problem. The links are on my old laptop at home, it'll take a week until I get there ...

Thomas

ghost commented 7 years ago

Hi Thomas,

I agree that you can quite safely ignore this pull "request" (i.e. made for discussion) - I realized also that there cannot be a massive error in the calculations since I got difference in an order of 3%. When I saw how wildly the currdir was jumping in my data (including back and forth over the north which you have handled nicely), I understood that the core of this method is the smoothing algorithm. Good that you have a commercial reference to compare; I don't, but the results have been consistent with the very stable and well known current we have got here.

For my own interest I will run the code with the same data on my Linux machine, I get easily into the variables with ddd/gdb. I'll report back, of course, if I discover something.

Meanwhile, have you thought about JW's use case, "I've got current when mooring"? That cannot work, right? I presume that one has a few very tiny values in some vectors, but really, how can one calculate the current from those if the boat is not moving, maybe just drifting side to side? Maybe you can improve the documentation on this regard; personally I don't look at the calculated current unless the boat is moving, and fast! If the boat is not moving, or I think so, then I would look at the GPS speed and direction and I've got my current! :)

Keep us posted here for your findings. And, especially, keep up the good job!

Petri

ghost commented 7 years ago

Hi Thomas,

I made some tests... to learn! :) From sources I deduced that you are referring to algorithm http://dx.doi.org/10.2312/EGVE/IPT_EGVE2003/199-206 as per "Therefore, substituting q for ~p, equations 1, 2, and 6 are applied to each of the four quaternion components and an explicit renormalization is done to make sure the predicted quaternion is on the unit sphere.". Therefore, your radian based calculations and renormalization to keep it in 0...360 makes a lot of sense to me. In fact, I think you have made a pretty clever adaptation of it. Interestingly, when one applies J.W.'s patch, the algorithm returns values quite close to your values (see attached screenshots) but it quickly was shooting over +5 degrees (with my test data). You can definitely ignore this pull request, I will close with this message.

tactics_p7_w_jw_patch_dbg_calculatecurrent tactics_p7_dbg_calculatecurrent

Therefore, J.W. in cruisers forum had some other problem and he certainly did not considered the aforementioned details... I can confirm: I am moored right now, and I don't get any current values even if all my instruments are on. I let you to explain this in the forum, I reckon that I would not be able to... :)

Best regards,

Petri

P.S. I attach an also a screenshot of patch 7 from a Linux machine in case you have not seen it yet. Only the polar performance graph window causes some trouble - it can be expanded and made wider OK but the graphs and the scale remain always the same size, i.e. very narrow. Otherwise, good portability for your code!

tactics_p7_on_linux
tom-r commented 7 years ago

Petri,

the polar performance graph window is basically copied for wind history... It shouldn't be a big deal to make it resizeable if wind history is resizeable ... Coming back to JW : from the mathematical point of view it makes sense to multiply the sin / cos functions with the length of the vector (currspd). The offset we both see is probably the difference to "1" (which we use, when not adding currspd).

I wouldn't say that NKEs calculation (which I don't know) is the holy grale, you wouldn't believe how many bugs are in the Multigraphic software ... But it's a good reference point. Especially at low current speeds (<0.15 kts) there are differences. I think these are due to the fact that they have a different smoothing algorithm and have all the data values "at hand" at the same time, like a snapshot, whereas O receives the instrument data one after another via a slow NMEA connection (this is the source of the noise we see). I think I'll do a branch just for fun, and combine both currdir values in one view, like "<org °> / <JW°>" for testing ... although in stable conditions "my" calculation matches exactly NKEs ... No big deal and I have both values visible side by side.

Another thing I'm thinking about is "fading" the chart overlay arrow for low current speeds <0.2 knots, simply by giving it more transparency. As a hint that it is not so reliable ...

It'll take a while until I can do real live testing again, as we "lost" our saildrive transmission ... probably the rubber joint btw. motor and saildrive-gearbox broken (we sailed ~250 miles back w/o engine, and arrived back in our marina today). A technician is coming on wednesday to analyze, then we need to order parts, repair, and so on. It'll take some time...

Thomas

ghost commented 7 years ago

Hi, Thomas,

Let's hope that the doctor will not find too expensive parts to change in your SailDrive! I changed all joints in mine in 2015 and I always wonder how long they would last; like to think forever since I am motoring not so often - but I know that I am wrong! :)

I am a bit confused why you would like to do vector calculations while I was thinking, after observing that your code corresponds LaViola's paper method (6) and that he states "Therefore, substituting q for ~p, equations 1, 2, and 6 are applied to each of the four quaternion components and an explicit renormalization is done to make sure the predicted quaternion is on the unit sphere", that you calculate indeed with three quaternion components with some transformation of a polar vector to a quaternion like this https://sourceforge.net/p/transengine/code/HEAD/tree/transQuaternion/transQuaternion/transQuaternion.cpp#l34 - and then back the smoothed quaternion result to a polar vector. Indeed, if you feed in polar vectors like J.W. you guys will end up to get quite similar results, him using SES in his datasheet and you using DES. If you both end up to use DES, then that's it! :)

Which is probably what NKE is using in their calculator. They have one advantage though, a more deterministic databus and a higher sampling speed. Tactics need to deal with undeterministic data (NMEA-0183 + MiniPlex + WiFi + OpenCPN in my case). That's why I am glad that you have it as a reference, otherwise academic discussions would never be able to define when the result is "good enough". I think that now it is: I have no illusions on NKE SW quality (cf. the heel sentences) but, on the other hand, they are used in about every Figaro Beneteau (I am moored next to a training center) and I reckon that these guys are comparing the values with what they get from their Ardena Pro and with their feeling when they sail in the currents of Brittany, no manufacturer would survive this test if their product is crap. Like I said, I've found Tactics to show very consistent values in a spot where there is always a current from same direction with slight variations in speed.

Actually, I think that Tactics needs to better than NKE because of the unorganized DAQ system the NMEA-0183+OpenCPN it has to rely on. That's I was enthusiastic when I read in you code about the LaViola method. Similar problems of sloppy sensors in difficult drone etc. flying tasks are reported to be resolved using quaternion based methods, I have found; it is not only for computer graphics. Like this: www.mdpi.com/1424-8220/15/8/19302/pdf - see Figure 1 for some impressive results to deal with the noise.

Your idea of fading current indicator is not bad at all: the current which is less strong has also less importance to the skipper! Another idea is to collect and use for the same purpose a quality flag/value (inspired by distributed DAQ systems): if the noise level is too high and/or sampling rate is too low the vector display could take fading colors, IMO.

I'll check the polar performance window in Linux again with debugger: In Windows build, both do work well. In Linux build both polar performance and wind history windows can be resized but only the wind history scales are following the resized window while polar performance window's scale and graph don't follow the new window contour, remaining always the same size. Can be an issue with Linux WxWidgets, I'll let you know if I find a solution.

Best regards,

Petri

ghost commented 7 years ago

Hi Thomas,

Sorry to bug you, but the idea how your code so efficiently adapts the LaViola-method without (obviously) using quaternion conversion of the vector haunted me. I thought since there is no 3D calculations needed how one presents a 2D polar vector as quaternion? As a single complex number! (There is no roll and pitch here). First, your code predicts the next vector length _ExpSmoothCurrSpd = mExpSmoothCurrSpd->GetSmoothVal(currspd); and then it converts the angle into a unit length complex number

    m_ExpSmoothSinCurrDir = mSinCurrDir->GetSmoothVal(sin(rad));
    m_ExpSmoothCosCurrDir = mCosCurrDir->GetSmoothVal(cos(rad));

where cos() is the real and sin() is the imaginary component of the complex number, which get their next predicted values above in the monotonic (supposedly, but not in real life) sampling rate. Then atan2() converts the obtained complex unit length number into an angle, which now represents the predicted (smoothed) angle. cf. for example http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/complex/transforms/ (I found some examples in game programmers forums for angle calculation usage).

Do you confirm that my analysis is correct? In that case, no reason to multiply the sin() and cos() values since the vector length component is estimated separately, right?

I endorse this method, of course; separating the vector length under its own DES calculation is a good idea for efficiency - your empiric testing shows that the results are good enough.

With that, when you are going to make this plugin "official" so that more people will use it ? 👍

Best regards,

Petri

ghost commented 7 years ago

Hi Thomas,

Related to reported Linux "bug" in Linux version of PolarPerformance scaling remaining stuck - it was not a bug at all but a feature inherited from the WindDirHistory window which the tester forgot: horizontal shall not be used but "vertical" orientation. Sorry about that. Not very intuitive... But since it has been inherited, better leave it. Actually, I went into the debugger to figure this out! FYI, in performance.cpp I noticed that in Linux ddd there is a problem with your source files: it is not good with UTF-8 and the scrolling stops as soon as you have a letter " ú " or symbols such as " ° ". Good news that I have not yet found any Linux specific issue in your code, it remains fully portable!

Best regards,

Petri

t should screenshot from 2017-07-12 23-32-09

rgleason commented 5 years ago

This is a little late to suggest, but for NmeaConverter we had the same problem and solved it pretty simply.

Here were my math suggestions: https://github.com/RooieDirk/NmeaConverter_pi/issues/18#issuecomment-494417453

And this is what spidgrou did:

All data comes from Raymarine instrument with Nmea 0183.
here the two instruction to have on OpenCPN:

    True Heading
    True Wind Direction 0-359

$XXHDT,$??HDG1,T
$WIMWD,($??MWV1+$??HDT1)+ceil((-($??MWV1+$??HDT1))/360)*360,T,,M,$??MWV3,N,,M

It works very good.

($??MWV1+$??HDT1)+ceil((-($??MWV1+$??HDT1))/360)*360

Math angle + Math.ceil( (-angle-179) / 360 ) * 360

What is math.ceil? Java script function. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil The Math.ceil() function returns the smallest integer greater than or equal to a given number. Note: Math.ceil(null) returns integer 0 and does not give a NaN error.

ghost commented 5 years ago

Hi Rick,

Thanks for the suggestion, but I don't see how this is related to the original suggestion from JW to use different smoothing method for current calculations? Anyway, the actual smoothing method was found to be adequate.

The thread seems to be about true wind calculation, BTW, while the current calculation requires also that one calculates the leeway:

2019-07-14_014956_vector_calculations_current

Not that complicated but the issue was rather with the smoothing, not the calculation itself.

A very interesting thing in your post caught my eye: there was a mention about JavaScript functions. If it is so that the NMEA Converter can call JavaScript functions, this opens a new world: you can suggest to them make a connector to Node Red of IBM and voilà! they would have their own dashboard on their fingertips! 👍 (Just and idea I can propose here since the joy killers will never read this 😁 ).

Thank you for having thought about this issue,

Petri

rgleason commented 5 years ago

Yes about javascriprt function, but this comes from Dirk's writing about nmeaconverter functions, and I have not looked at the code at all.

Conachair writes all the time about node red. It sounds very good.

Thanks Rick