Read Serial array then plot it

Oh my goodness, that’s good, glv. I played with the data a little bit and got something too. I won’t be posting the code because it was brute force. Here’s a shot of it. I transformed the elevation to my latitude and rotated the image until the longitude line hit the 3 star circles of equal altitude fix. The satellite plots lose their visual coolness but it’s apparent that if they are below the horizon, they dont get plotted.

It was backwards when draped over the sphere. I’m working on a version which gives the view from inside the sphere - look to the east, it should be on the right. look north, it should be directly in front.

3 Likes

I’m recording some data now.

This helps visualize to have N S E W and an equator. It occurred to me that zenith should be directly above the receiver latitude and longitude. The way I have it now zenith is the north pole. Once I get the visual orientation down, I’m going to use sterretje’s idea to vary the color of the track based on SNR. I’m using his code to parse and it is about as thorough as could be conceived and a beautiful
example of Java. I might even look into other NMEA sentences and plot the circles of equal altitude limited to the satellites used in the fix. Maybe update every few seconds and it would be visible how these circles vary with altitude and azimuth. This would be something drawn where I dont want “persistance” and want it to refresh with new data.

Anyway, back to the grind in the morning.

3 Likes

This is the best I can do right now. Upload is not allowed. I got home and thought I had 15MB of data and then I closed the sketch I’m using to save data and it changed to 4.9MB. ??? I’m trying again. Here is the link:https://github.com/HarryDrones/NACA4Series/blob/master/Archive.zip

this link is just a GPGSV.zip:https://github.com/HarryDrones/NACA4Series/blob/master/GPGSV.zip

Hello @HackinHarry,

Thanks for the data!

Cool beans!

I thank you for this topic!
I like to keep my mind engaged and can do some cool things with GPS data.

Animation from the smaller set of data you provided:

GPS

I am collecting some data with my Android and saving with Processing using:

There are many other apps to do this; I just happened to have this on my phone.

I do a lot of long nature hikes and will collect some data and plot my adventures in 3D.

:)

1 Like

I tried your example, glv. That’s amazing how simple. What’s not simple is that I have to go to another computer to see it. The next attempt to save data is at about 7MB so far. I’ll make sure my glasses are on when I hit stop this time. :wink:

Off to the grind again.

I got the big 15MB data zipped at this link:https://github.com/HarryDrones/NACA4Series/blob/master/GPGSV.zip

It fills the sky pretty good. One thing that starts to become better defined is the path for a few of the satellites. In the sketch glv posted I swapped the saturation value with the hue:

colorMode(HSB, 100, 32, 100);

If the SNR is low, then it is red, medium is yellow, and high is green.

1 Like

Hello again!

Thanks for sharing the data!

I added the extra satellites to my sketch and took your 15MB data out for a spin:

test2

Only a 90° sweep… GIF was was getting too large to upload.
I increased the steps in the for loop to over 100 otherwise it was too slow.

Saving frames and using the built in Movie Maker to make GIFs.

Simple proof of concepts is all I seem to have time for these days.
I did also plot with spherical co-ordinates and the result was the same as the two rotations and did not include that code.

There is some cool stuff here:

It takes a bit of getting used to navigating the site.

I found the rotation conversions helpful for some projects I worked on:

:)

1 Like

When I said simple, I think it’s more accurate to say that processing abstracts the complex and makes it seem simple. I didn’t run into rotation matrices or quaternions until I started playing with IMU’s and then a statistics course I once had started to make sense.

Thanks for the link.

1 Like

This isnt as colorful as glv’s, but I can look at it from different angles.

GPS_Sphere3


1 Like

Good grief, that’s a bit ugly. :wink: I’ve got some time so I’m going to try and get “inside” the data for a better view.

Of course, now I see a new direction to take this. Now I want to use the $GPGSA sentence to get which satellites are used in the fix. I only need the first three. I saved a file that collected GPGSA and GPGSV and I tried to nest a for loop for the GPGSA within the for loop for the GPGSV for loop. It would read the GPGSV and then stop after one pass and not read the GPGSA. This is where @sterretje 's more thorough parsing class might be useful.

The idea is that I will take the altitude and azimuth for the first three satellites used in the fix and use some functions I have to calculate the COP’s and then plot these circles. As the satellites move, these circles will change and new satellites will be used. A large amount of data like over the course of a day should show these circles bouncing around and growing and shrinking but the intersection will remain the same.

I made a little progress. I can get the first three satellites of the fix from $GPGSA and I can get the altitude and azimuth from $GPGSV. The next step is to draw the COP’s using the functions I already have for that.

Back to the grind in the morning.

Well, I’m lost. I can’t find a good way to plot the COP from the first three satellites used in the fix. My functions from something I wrote 5 years ago need GHA, Declination, Altitude. I’m using azimuth for GHA, altitude is altitude, and I’m using altitude again for declination. I figure I can transform these if I can get something working first. I tried to shoe horn some code and it ran all night endlessly, yikes. I tried something different(hey, not usually insane, not time to go there)and I got an array out of bounds.

I used @sterretje 's and @glv 's code to draw the azimuth altitude points on a Pimage after reading from saved GPS data. I saved that image and then used code to draw a sphere with that image draped.

I added my COP functions to that code and it draws the nice solid green circle. What I was hoping was that I could parse for satellites used in the fix and also get altitude and azimuth for those satellites. I know this much, it will involve combining data from GPGSV and GPGSA, but how?

Here are the functions needed to draw a circle based on an assumed latitude and longitude, and altitude and direction. Then convert that to cartesian coordinates and plot curvevertex points.

//original code from navigationalalgorithms.com and Andres Ruiz


boolean getPoints(){
    released = false;   
  Mz = Rz(Math.toRadians(360.0) - GHA, Mz);
 //  Mz = Rz(Math.toRadians(360.0) - Math.toRadians(az0), Mz);
  
  My =  Ry(Math.toRadians(90.0) - dec, My);
//  My =  Ry( Math.toRadians(el0), My);
//    My =  Rx(Math.toRadians(90.0) - dec, My);
 
  int w = 0;

  for( double L0 = -180.0; L0 <= 180.0; L0 += .1 )
    {
  //  released = false;
  //  println("top of For LooP; " + released);
      vv =  VectorSpherical2Cartesian((alt),Math.toRadians(L0) );

      vy =  MatrixVecProd( My, vv, vy );

      vyz =  MatrixVecProd( Mz, vy, vyz );

      wpt[w] = C2ELat( vyz[0], vyz[1], vyz[2]);
      wpt[w+1] = C2ELon( vyz[0], vyz[1], vyz[2]);

      WPT = toFloatArray(wpt);

      x[w] = map(WPT[w+1],radians(-180) ,radians(180),texture.width, texture.width - texture.width);
      y[w] = map(WPT[w],radians(-90),(radians(90)),texture.height,texture.height - texture.height);

      texture.beginDraw();
      texture.point(x[w],y[w]);
      texture.noFill();
      texture.stroke(0,255,0);
      texture.strokeWeight(3);
      texture.beginShape();
      texture.curveVertex(x[w],y[w]);
      texture.curveVertex(x[w],y[w]);
      texture.endShape();
      texture.endDraw();
   released = true;
    }
    

      w++;

     // }
      println(released);
      println("Before return statement: " + released);
return released;
} 






//Funcition to convert double[] to float[]
float[] toFloatArray(double[] arr) {
  if (arr == null) return null;
  int n = arr.length;
  float[] ret = new float[n];
  for (int i = 0; i < n; i++) {
  ret[i] = (float)arr[i];
  }
  return ret;
}
// end of function to convert double[] to float[]



public double C2ELat( double x, double y, double z )
{
  double[]res = new double[3];
  res[0] = Math.sqrt( x*x+y*y+z*z);  //R
//*B = ASIN(z/(*R));
  res[1] = Math.atan2( z, Math.sqrt(x*x+y*y) ); //B
  res[2] = Math.atan2( y, x ); //L

  return (res[1]);

}

public double C2ELon( double x, double y, double z )
{
  double[]res = new double[3];
  res[0] = Math.sqrt( x*x+y*y+z*z);  //R
  res[1] = Math.atan2( z, Math.sqrt(x*x+y*y) ); //B
  res[2] = Math.atan2( y, x ); //L

  return (res[2]);

}
 

public double[] E2C( double B, double L, double R )
{
  double[]res = new double[3];
  
  res[0] = R*Math.cos((B))*Math.cos((L));
  res[1] = R*Math.cos((B))*Math.sin((L));
  res[2] = R*Math.sin((B));
 

 
  return(res);
}
 
 public double[][] Rx( double a, double[][] M ){

  M[0][0] = 1.0;
  M[1][0] = 0.0;
  M[2][0] = 0.0;
  M[0][1] = 0.0;
  M[1][1] = Math.cos(a); //Math.cos(Math.toRadians(a));
  M[2][1] = Math.sin(a); //Math.sin(Math.toRadians(a));
  M[0][2] = 0.0;
  M[1][2] = -Math.sin(a); //-Math.sin(Math.toRadians(a));
  M[2][2] = Math.cos(a); //Math.cos(Math.toRadians(a));
  
  return(M);
}

public double[][] Ry( double a, double[][] M ){

  M[0][0] = Math.cos(a);
  M[1][0] = 0.0;
  M[2][0] = -Math.sin(a);
  M[0][1] = 0.0;
  M[1][1] = 1.0;
  M[2][1] = 0.0;
  M[0][2] = Math.sin(a);
  M[1][2] = 0.0; 
  M[2][2] = Math.cos(a);
  
  return(M);
}

public double[][] Rz( double a, double[][] M ){

  M[0][0] = Math.cos(a); //Math.cos(a);
  M[1][0] = Math.sin(a);
  M[2][0] = 0.0;
  M[0][1] = -Math.sin(a);
  M[1][1] = Math.cos(a);
  M[2][1] = 0.0;
  M[0][2] = 0.0; 
  M[1][2] = 0.0; 
  M[2][2] = 1.0;
  
  return(M);
}
 
public double[] MatrixVecProd( double[][] A, double[] v, double[] res ) {

  int i,j;
  int n = 3;

  for( i=0; i<n; i++ ) {
    res[i] = 0.0;
    for( j=0; j<n; j++ ) {
    res[i] += A[i][j]*v[j];
   
  }
}

  return (res);
}




 
 double[] C2E( double x, double y, double z ){ 
    double B;
    double L;
   double R = Math.sqrt( x*x+y*y+z*z);  
 B = Math.asin(z/(R));  
  //  B = Math.atan2( z, Math.sqrt(x*x+y*y) );  
    L = Math.atan2( y, x );
    double res[] = new double[2];
    res[0] = Math.toDegrees(B);
    res[1] = Math.toDegrees(L);
   // println(res);
    return res;
 }

 
  double[] VectorSpherical2Cartesian(double B, double L){
  
   double v[] = new double[3];
   v[0] = Math.cos(B) * Math.cos(L);
   v[1] = Math.cos(B) * Math.sin(L);
   v[2] = Math.sin(B);
//   println(Math.toDegrees(B));
//   println(Math.toDegrees(L));
   return(v);
   
 }
 
  double[] Unit(double x[]) {
   
   return (aVector(1.0/Mod(x),x));
   
 }
 
 double Mod(double x[]) {

  return(Math.sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]));
  
}
   
   double Mod4(double x[]) {

    return((x[0] * x[0] + x[1] * x[1] + x[2] * x[2]));
   
   }
   
  double[] Add(double x[], double y[]) {
  double z[] = new double[3];
  for (int i = 0; i < 3; i++) {
       z[i] = x[i] + y[i];
       
      } 
    return z;
  }
  

      
  double[] Subtract(double x[], double y[]) {
  double z[] = new double[3];
  for (int i = 0; i < 3; i++) {
       z[i] = x[i] - y[i];
      } 
      return z;
  }
     
 double[] aVector(double a, double x[]) {
   double z[] = new double[3];
   z[0] = a * x[0];
   z[1] = a * x[1];
   z[2] = a * x[2];
  // z[3] = a * x[3];
   
   return (z);
   
 }
 

 
  double Dot(double x[], double y[])
 {
   return (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]);
   
 }
 
 double[] Cross(double x[], double y[]){
  
   double z[] = new double[3];
   z[0] = (x[1]*y[2]) - (x[2]*y[1]);
   z[1] = (x[2]*y[0]) - (x[0]*y[2]);
   z[2] = (x[0]*y[1]) - (x[1]*y[0]);
   
   return (z);
   
 }

I appreciate any help sorting out a good approach.

If anyone wonders where I got these functions:

The paper I downloaded was “Use of rotation matrices to plot a circle of equal altitude”. It’s what makes the solid green circle.

1 Like

I haven’t made any progress other than realizing that I’ve been plotting satellites wrong. Altitude and Azimuth is relative to the latitude and longitude of the receiver and I’ve been plotting it relative to the North Pole. It looks kinda cool, but it’s wrong. My interest isn’t there to correct it.

In back of my mind is the project that got me playing with processing in the first place. I want to use an IMU running on a Pico to point at a star, press a button and record the altitude and time. Do this with 3 different stars and calculate a fix and determine the amount of error. Basically, it would be an electronic astrolabe. Half a century ago I had a course in Astronomy and for a lab we used an astrolabe made from a yard stick to observe some stars and calculate our position. It was fun to be out on a crisp fall evening, but error prone. Obviously, that lab exercise stuck in my head and distracts from any other project until I do it.

Sounds familiar. I’m working on a project and needed a GUI for that; I’ve now spend more time on building the GUI than on writing the real application :smiley:

It’s been several months since I last looked at this. I had a limited amount of time to play with it and then I knew I was doomed to work, sleep, no play. I sometimes daydream about it while working, but the job I have seriously steals my creativity and leaves me ticked off. I’ll make the time again.

1 Like

I can empathize with that.

I got one of these (freebie!) to play with but have not even had time to solder the pins yet:

Maybe in the new year!

Happy holidays!

:)

1 Like