Linear compass display to use with a MPU

Hello @philtkp ,

I found my BNO055!

Still works like a charm!

The bottom right is not connected… I think I had Bluetooth connected at one time.

:)

@glv

Sweet!, I’m using the Sparkfun RedBoard and the GY80. They were a bit dusty but fired right up.

@glv Now that i started using the GY80 vice the mouse i noticed that when i rotate the board CLOCK WISE the displayed readings go COUNTER CLOCK WISE. cant seem to correct that.:tired_face:

CODE


// LINEAR COMPASS
import processing.serial.*;
Serial fd;

PGraphics hdg;
PGraphics comp;
PGraphics ahm;

PImage fade;

float Pitch;
float Bank;
float Azimuth;
float degree1;
//float yaw = 0.0f;
float yawOffset = 0.0f;
float SpanAngle=120;
//float GaugeWidth=304;  
//float StrokeWidth=1;
//float an;
//float DivxPhasorCloser;
//float DivxPhasorDistal;
//float DivyPhasorCloser;
//float DivyPhasorDistal;
int W=300; //My Laptop's screen width
int H=300; 
int degree = 0; 
int heading = 0;
int pitch = 0;
int roll = 0;
int yaw = 0;
int yawDeg = 0;
int rollDeg = 0;
int pitchDeg = 0 ;
int NumberOfScaleMajorDivisions;
int NumberOfScaleMinorDivisions;
PVector v1, v2; 
//
// ---------------------------------------------------------------
//
void setup()
{
  // init
  size(800, 800, P2D);
  hdg = createGraphics(300,50);
  comp = createGraphics(300,300);
  ahm = createGraphics(300,300);
  
  fade = loadImage("fade2.png");
  
  fd = new Serial(this, Serial.list()[1], 115200);
  // Defer callback until new line
  fd.bufferUntil('\n');
  rectMode(CENTER);
  smooth();
  strokeCap(SQUARE);//Optional
  //background(0);
} // func 
 
void draw() 
{ 
 
 
 
 background(0);
 LCompass();
 Compass();
 drawHorz();
 
 println("PITCH: "+pitch," ROLL: "+roll,"YAW: "+yaw);
//println("Linear compass : DEGREE = "+ degree," YAW DEGREE = "+ (360-(yawDeg%360)));
  
}

void serialEvent (Serial fd) 
{
  // get the ASCII string:
  String rpstr = fd.readStringUntil('\n');
  if (rpstr != null) {
    String[] list = split(rpstr, ':');
    pitch = ((int)float(list[0]));
    roll = ((int)float(list[1]));
    yaw = ((int)float(list[2]));
        
  }
}

/**********************************************************/
/* DRAW LINEAR COMPASS WITH FADE
/**********************************************************/
void LCompass(){
 

 hdg.beginDraw();
 hdg.background(255);
 
  hdg.image(fade,300,50);
// black rect (the whole compass)
 hdg.noFill();
 hdg.stroke(0); //Black
 hdg.rect(0, 0, 299, 49);
  
// yellow rect (the display)  
 hdg.fill(255,255,2);
 hdg.rect(0, 25, 299, 24);
  
  // yellow triangle 
   
 hdg.stroke(0);// black
 hdg.fill(255, 255, 2); // yellow 
  
 hdg.triangle(150-5, 18, 150+5, 18, 150, 24);
 
 int degree = 360-(yaw%360);
  
 // DISPLAY DEGREES
 hdg.stroke(0);// black
 hdg.fill(0); //  black 
 hdg.textAlign(CENTER);
 hdg.textSize(16);
 hdg.text(yawDeg,150, 15); 
 
 // DRAW BLACK DEGREE MARKS
 hdg.stroke(0); // black
 int lengthLine = 0;  
 for (int i=0; i < 360; i+=5)
 {
   if (i%90==0) { 
     lengthLine=9;
   } 
   else if(i%45==0){
     lengthLine=6;
   }
   else
   {
     lengthLine=3;
   }
   hdg.line(((degree-30)+i)%360, 26, ((degree-30)+i)%360, 26+lengthLine);
   hdg.fill(0);
  
  }
  hdg.textSize(14);
  hdg.text("S", ((degree-30)+360)%360, 47);
  hdg.text("N", ((degree-30)+180)%360, 47);
  hdg.text("E", ((degree-30)+270)%360, 47);
  hdg.text("W", ((degree-30)+450)%360, 47);
  hdg.textSize(10);
  hdg.text("NW", ((degree-30)+495)%360, 47);
  hdg.text("NE", ((degree-30)+225)%360, 45);
  hdg.text("SE", ((degree-30)+315)%360, 45);
  hdg.text("SW", ((degree-30)+405)%360, 45);
 
 //  draw red line in display
 hdg.stroke(255, 2, 2); 
 hdg.line(150, 26, 150, 48);
  
  println("yaw: ",+yaw," yawDeg:",+yawDeg," degree: ",degree%360);
  
 hdg.image(fade,0,0); 
 hdg.endDraw();
 image(hdg, 280, 320);
 }
 
/**********************************************************/
/* DRAW DIAL COMPASS
/**********************************************************/
void Compass(){
 comp.beginDraw();
 comp.background(0);
 
 yaw = (int)map(yaw, 0, 360, 0, 360);
 yawDeg = (int)(yaw%360);
  
 comp.pushMatrix();
 comp.noStroke();
 comp.fill(108, 156, 255); // Fill sky color
 comp.ellipse(150, 150, 220, 220);
 
 if((int)yaw >= 1 && (int)yaw <= 180) // Keeps numbers positive
    yawDeg = (int)yaw;
  else yawDeg = 360 + (int)yaw;

 // DRAW DEGREES INSIDE COMPASS 
  comp.noFill();
  comp.stroke(255); //Black
  comp.rect(125, 222, 50, 30);
  comp.fill(0); //Black
  comp.rect(125, 222, 50, 30);
  comp.textSize(20);
  comp.fill(255,255,255);
  comp.textAlign(CENTER);
  comp.text(yawDeg, 150, 245); 
 
  comp.translate(150, 150);   
  
  CompassPointer();
  
  comp.popMatrix();
  comp.pushMatrix();
  
  /* Draws the circular scale on compass */
   comp.translate(150, 150); 
   comp.stroke(255);
   comp.strokeWeight(2);
   comp.noFill();
   comp.ellipse(0, 0, 220, 220);
   
   SpanAngle=180;
   NumberOfScaleMajorDivisions=18;
   NumberOfScaleMinorDivisions=36; 
   
   CircularScale(); 

   comp.rotate(PI);
   SpanAngle=180;  
   
   CircularScale();
   comp.rotate(-PI);
   
   comp.translate(-300, 100);
   comp.textSize(20);
   comp.fill(255,255,255);
   comp.textAlign(CENTER);
   comp.text("W", 165, -92);
   comp.text("E", 430, -92);
   comp.text("N", 300, -230);
   comp.text("S", 300, 42);
   comp.rotate(PI/4);
   comp.textSize(15);
   comp.text("NW",-0, -280);
   comp.text("SE",  275, -280);
   comp.popMatrix();
   comp.rotate(-PI/4);
   comp.text("NE",140,220);
   comp.text("SW",-140, 220);
   
   comp.endDraw();
   image(comp, 280, 10);
}

/**********************************************************/
/* DRAW ROLL/PITCH INDICATOR                              */
/**********************************************************/
void drawHorz() {
  
  ahm.beginDraw();
  ahm.translate(0,0);  
 
//  int pitchDeg = 360-(pitch%360);
 roll = (int)map(roll, 0, 360, 0, 360);
  rollDeg = (int)((roll%360));

 //if((int)Pitch >= 1 && (int)Pitch <= 180)
 //    pitchDeg = (int)pitch;
 // else pitchDeg = 360 + (int)Pitch;
 
  Pitch = (int)map(pitch, 0, 360, 0, 360);
  pitchDeg = (int)((Pitch%360));
 
 //println("BANK: ",+rollDeg," PITCH: ",+pitchDeg);
 //println("pitch: ",+pitch," Pitch:",+Pitch," pitchDeg: ",(pitchDeg%360));
  
  ahm.noStroke();
  ahm.fill(0, 180, 255);//fills sky
  ahm.rect(0, 0, 300, 300);
  ahm.fill(95, 55, 40); //Fills ground
  
  ahm.rotate(-rollDeg);
  ahm.rect(0, 150+pitchDeg%360, 300, 300); 
  ahm.translate(150,150);
  ahm.push();
  ahm.rotate(rollDeg);
  ahm.rotate(-PI-PI/6);
 
  SpanAngle=120;
  NumberOfScaleMajorDivisions=12;
  NumberOfScaleMinorDivisions=24;  
 
  CircularScale2(); 
  ahm.rotate(PI+PI/6);
  ahm.rotate(-PI/6);  
  CircularScale2();
  ahm.rotate(PI/6);
  ahm.rotate(-rollDeg%360); 
  
  
  PitchScale();
  Axis(); 
  ahm.pop();
  ahm.rotate(rollDeg%360);
  ahm.endDraw();
   image(ahm, 280, 390);
}
/********************************************************/
/*    Draw cirular scale                                */
/* Code from Adrian Fernandez 4-19-2013                 */
/********************************************************/
void CircularScale()
{
  float GaugeWidth=304;  
  comp.textSize(GaugeWidth/20);
  float StrokeWidth=1;
  float an;
  float DivxPhasorCloser;
  float DivxPhasorDistal;
  float DivyPhasorCloser;
  float DivyPhasorDistal;
  comp.strokeWeight(2*StrokeWidth);
  comp.stroke(255);
  comp.noFill();
   

  float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
  float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMinorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMinorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));  
     
    comp.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
  }

  DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
  DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMajorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMajorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
    if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
    {
      comp.strokeWeight(5);
      comp.stroke(255);
      
      comp.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
      comp.strokeWeight(1);
      comp.stroke(100, 255, 100);
      
      comp.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
    else
    {
      comp.strokeWeight(3);
      comp.stroke(255);
      comp.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
  }
}
/********************************************************/
/*    Draw cirular scale                                */
/* Code from Adrian Fernandez 4-19-2013                 */
/********************************************************/
void CircularScale2()
{
  float GaugeWidth=304;  
  ahm.textSize(GaugeWidth/20);
  float StrokeWidth=1;
  float an;
  float DivxPhasorCloser;
  float DivxPhasorDistal;
  float DivyPhasorCloser;
  float DivyPhasorDistal;
  ahm.strokeWeight(2*StrokeWidth);
  ahm.stroke(255);
  ahm.noFill();
   

  float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
  float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMinorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMinorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));  
     
    ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
  }

  DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
  DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMajorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMajorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
    if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
    {
      ahm.strokeWeight(5);
      ahm.stroke(255);
      
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
      ahm.strokeWeight(1);
      ahm.stroke(100, 255, 100);
      
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
    else
    {
      ahm.strokeWeight(3);
      ahm.stroke(255);
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
  }
}



/***************************************************/
/* Draws the compass pointer                       */
/***************************************************/ 
 void CompassPointer()
{
  comp.rotate(radians(yaw));  
  comp.stroke(0);
  //strokeWeight(1);
  comp.fill(255,255,255);
  
  comp.beginShape();
    comp.vertex(0,-105);
    comp.vertex(12, 100);
    comp.vertex(0, 80);
    comp.vertex(-12, 100);
  comp.endShape(CLOSE);
  
  comp.ellipse(0, 0, 9, 9);  
  comp.ellipse(0, 0, 3, 3); 
}
/***************************************************/
/* Draw the pitch scale                            */
/***************************************************/
void PitchScale()
{ 
  
  //ahm.push();
  //ahm.translate(0,0);
  
  ahm.stroke(255);
  ahm.fill(255);
  ahm.strokeWeight(2);
  ahm.textSize(15);
  ahm.textAlign(CENTER,CENTER);
  for (int i=-4;i<5;i++)
  {  
    if ((i==0)==false)
    {
      ahm.line(40, 20*i, -40, 20*i);
    }  
    ahm.text(""+i*20, 20, 20*i, -150, 20);
    ahm.text(""+i*20, -20, 20*i, 150, 20);
  }
  //textAlign(CORNER);
  ahm.strokeWeight(2);
  for (int i=-9;i<10;i++)
  {  
    if ((i==0)==false)
    {    
      ahm.line(20, 10*i, -20, 10*i);
    }
  }
 //ahm.pop();
}


/***************************************************/
/* Draw red axis lines                             */
/***************************************************/
void Axis()
{
  ahm.stroke(255,0,0);
  ahm.strokeWeight(2);
  ahm.line(-45, 0, 45, 0);
  ahm.line(0, 90, 0, -90);
  ahm.fill(100, 255, 100); //GREEN
  ahm.stroke(0);
  ahm.strokeWeight(1);
  ahm.triangle(0, -107, -6, -90, 6, -90);
  ahm.triangle(0, 107, -6, 90, 6, 90);
} 

fade2 This is the fade i used to give the linear compass a some what 3d look.

I’m going to see if i can take the kinks of the roll and pick indicator. Time to put on another pot of coffee.

Hello @philtkp,

Wrap your head around this (no pun intended):

int wrap360(int a)
  {
  return (a%360 + 360)%360;
  }

void draw() 
{  
 // N is width/2 for mouseX
 // This works for any negative value (may be excessive here):
 // yaw = ((int) map(mouseX, 00, width, -180, 180)%360+360)%360; // handles negatives with %
 
 // Cleaner presentation of above:
 int yawMap = (int) map(mouseX, 00, width, -180, 180);// handles negatives with % 
 yaw = wrap360(yawMap);
 
 // This works for your case:
 yaw = ((int) map(mouseX, 00, width, -180,  180)+360)%360; // handles negatives with %
 
 // Also works for 0 to 360
 //yaw = (int) map(mouseX, 0, width, 0, 360)%360;
 
 background(0);
 LCompass();
 Compass();
 drawHorz();
 
 fill(255);
 textSize(24);
 text(yaw, 20, 30); 
 
 println("PITCH: "+pitch," ROLL: "+roll,"YAW: "+yaw);
//println("Linear compass : DEGREE = "+ degree," YAW DEGREE = "+ (360-(yawDeg%360)));  
}

Generalized wrap function for any int value:

int wrap360(int a)
  {
  return (a%360 + 360)%360;
  }

:)

ok, just have a 2 brain cell moment!:hushed_face: i had the board with the smd parts facing up when it should of been down. grabbed one that had the pins soldered on the other side and it works fine. aaAAHHHH.

@glv I’m working on the roll/pitch indicator. I’m doing the pitch part first.

have a problem with the pitch scale degrees. I’m unable to align it to zero when using PGraphics

its in drawHorz() and PitchScale(). I think its this part of the code
ahm.text(""+i*20, 20, 20*i, -150, 20); // draws left side degrees
ahm.text(""+i*20, -20, 20*i, 150, 20); // draws right side degrees

CODE USING PGRAPHICS


// LINEAR COMPASS
import processing.serial.*;
Serial fd;

PGraphics hdg;
PGraphics comp;
PGraphics ahm;

PImage fade;

float Pitch;
float Bank;
float Azimuth;
float degree1;
//float yaw = 0.0f;
float yawOffset = 0.0f;
float SpanAngle=120;
//float GaugeWidth=304;  
//float StrokeWidth=1;
//float an;
//float DivxPhasorCloser;
//float DivxPhasorDistal;
//float DivyPhasorCloser;
//float DivyPhasorDistal;
int W=300; //My Laptop's screen width
int H=300; 
int degree = 0; 
int heading = 0;
int pitch = 0;
int roll = 0;
int yaw = 0;
int yawDeg = 0;
int rollDeg = 0;
int pitchDeg = 0 ;
int NumberOfScaleMajorDivisions;
int NumberOfScaleMinorDivisions;
PVector v1, v2; 
//
// ---------------------------------------------------------------
//
void setup()
{
  // init
  size(800, 800, P2D);
  hdg = createGraphics(300,50);
  comp = createGraphics(300,300);
  ahm = createGraphics(300,300);
  
  fade = loadImage("fade2.png");
  
  fd = new Serial(this, Serial.list()[1], 115200);
  // Defer callback until new line
  fd.bufferUntil('\n');
  rectMode(CENTER);
  smooth();
  strokeCap(SQUARE);//Optional
  //background(0);
} // func 
 
void draw() 
{ 
 
 
 
 background(0);
 LCompass();
 Compass();
 drawHorz();
 
 println("PITCH: "+pitch," ROLL: "+roll,"YAW: "+yaw);
//println("Linear compass : DEGREE = "+ degree," YAW DEGREE = "+ (360-(yawDeg%360)));
  
}

void serialEvent (Serial fd) 
{
  // get the ASCII string:
  String rpstr = fd.readStringUntil('\n');
  if (rpstr != null) {
    String[] list = split(rpstr, ':');
    pitch = ((int)float(list[0]));
    roll = ((int)float(list[1]));
    yaw = ((int)float(list[2]));
        
  }
}

/**********************************************************/
/* DRAW LINEAR COMPASS WITH FADE
/**********************************************************/
void LCompass(){
 

 hdg.beginDraw();
 hdg.background(255);
 
  hdg.image(fade,300,50);
// black rect (the whole compass)
 hdg.noFill();
 hdg.stroke(0); //Black
 hdg.rect(0, 0, 299, 49);
  
// yellow rect (the display)  
 hdg.fill(255,255,2);
 hdg.rect(0, 25, 299, 24);
  
  // yellow triangle 
   
 hdg.stroke(0);// black
 hdg.fill(255, 255, 2); // yellow 
  
 hdg.triangle(150-5, 18, 150+5, 18, 150, 24);
 
 int degree = 360-(yawDeg%360);
 
 
 // DISPLAY DEGREES
 hdg.stroke(0);// black
 hdg.fill(0); //  black 
 hdg.textAlign(CENTER);
 hdg.textSize(16);
 hdg.text(yawDeg%360,150, 15); 
 
 // DRAW BLACK DEGREE MARKS
 hdg.stroke(0); // black
 int lengthLine = 0;  
 for (int i=0; i < 360; i+=5)
 {
   if (i%90==0) { 
     lengthLine=9;
   } 
   else if(i%45==0){
     lengthLine=6;
   }
   else
   {
     lengthLine=3;
   }
   hdg.line(((degree-30)+i)%360, 26, ((degree-30)+i)%360, 26+lengthLine);
   hdg.fill(0);
  
  }
  hdg.textSize(14);
  hdg.text("S", ((degree-30)+360)%360, 47);
  hdg.text("N", ((degree-30)+180)%360, 47);
  hdg.text("E", ((degree-30)+270)%360, 47);
  hdg.text("W", ((degree-30)+450)%360, 47);
  hdg.textSize(10);
  hdg.text("NW", ((degree-30)+495)%360, 47);
  hdg.text("NE", ((degree-30)+225)%360, 45);
  hdg.text("SE", ((degree-30)+315)%360, 45);
  hdg.text("SW", ((degree-30)+405)%360, 45);
 
 //  draw red line in display
 hdg.stroke(255, 2, 2); 
 hdg.line(150, 26, 150, 48);
  
 hdg.image(fade,0,0); 
 hdg.endDraw();
 image(hdg, 280, 320);
 }
 
/**********************************************************/
/* DRAW DIAL COMPASS
/**********************************************************/
void Compass(){
 comp.beginDraw();
 comp.background(0);
 
 yaw = (int)map(yaw, 0, 360, 0, 360);
 yawDeg = (int)(yaw%360);
  
 comp.pushMatrix();
 comp.noStroke();
 comp.fill(108, 156, 255); // Fill sky color
 comp.ellipse(150, 150, 220, 220);
 
println("dial compass " + yaw, yawDeg);
 
  if((int)yaw >= 1 && (int)yaw <= 180)
     yawDeg = (int)yaw;
  else yawDeg = 360 + (int)yaw;

 // DRAW DEGREES INSIDE COMPASS 
  comp.noFill();
  comp.stroke(255); //Black
  comp.rect(125, 222, 50, 30);
  comp.fill(0); //Black
  comp.rect(125, 222, 50, 30);
  comp.textSize(20);
  comp.fill(255,255,255);
  comp.textAlign(CENTER);
  comp.text(yawDeg%360, 150, 245); 
 
  comp.translate(150, 150);   
  
  CompassPointer();
  
  comp.popMatrix();
  comp.pushMatrix();
  
  /* Draws the circular scale on compass */
   comp.translate(150, 150); 
   comp.stroke(255);
   comp.strokeWeight(2);
   comp.noFill();
   comp.ellipse(0, 0, 220, 220);
   
   SpanAngle=180;
   NumberOfScaleMajorDivisions=18;
   NumberOfScaleMinorDivisions=36; 
   
   CircularScale(); 

   comp.rotate(PI);
   SpanAngle=180;  
   
   CircularScale();
   comp.rotate(-PI);
   
   comp.translate(-300, 100);
   comp.textSize(20);
   comp.fill(255,255,255);
   comp.textAlign(CENTER);
   comp.text("W", 165, -92);
   comp.text("E", 430, -92);
   comp.text("N", 300, -230);
   comp.text("S", 300, 42);
   comp.rotate(PI/4);
   comp.textSize(15);
   comp.text("NW",-0, -280);
   comp.text("SE",  275, -280);
   comp.popMatrix();
   comp.rotate(-PI/4);
   comp.text("NE",140,220);
   comp.text("SW",-140, 220);
   
   comp.endDraw();
   image(comp, 280, 10);
}

/**********************************************************/
/* DRAW ROLL/PITCH INDICATOR                              */
/**********************************************************/
void drawHorz() {
  
  ahm.beginDraw();
 // ahm.translate(0,0);  
 
 //  int pitchDeg = 360-(pitch%360);
  //Bank = (int)map(roll, 0, 360, 0, 360);
  //rollDeg = (int)((Bank%360));

 //if((int)Pitch >= 1 && (int)Pitch <= 180)
 //    pitchDeg = (int)pitch;
 // else pitchDeg = 360 + (int)Pitch;
 
  Pitch = (int)map(pitch, 0, 360, 0, 360);
  pitchDeg = (int)((Pitch%360));
 
 println("BANK: ",+rollDeg," PITCH: ",+pitchDeg);
 println("pitch: ",+pitch," Pitch:",+Pitch," pitchDeg: ",(pitchDeg%360));
  
  ahm.noStroke();
  ahm.fill(0, 180, 255);//fills sky
  ahm.rect(0, 0, 300, 300);
  ahm.fill(95, 55, 40); //Fills ground
  
 //ahm.rotate(-rollDeg);
  ahm.rect(0, 150-pitchDeg%360, 300, 300); 
  ahm.translate(150,150); // Places pitch scale center
  //ahm.push();
  //ahm.rotate(rollDeg);
  ahm.rotate(-PI-PI/6); // Centers upper scale
 
  SpanAngle=120;
  NumberOfScaleMajorDivisions=12;
  NumberOfScaleMinorDivisions=24;  
 
  CircularScale2(); //Draws upper scale
  ahm.rotate(PI+PI/6); // Centers lower scale
  ahm.rotate(-PI/6);   //
  CircularScale2(); //Draws lower scale
  ahm.rotate(PI/6); // Aligns pitch scale and axis
  //ahm.rotate(-rollDeg%360); 
  
  
  PitchScale();
  Axis(); 
  //ahm.pop();
  //ahm.rotate(rollDeg%360);
  ahm.endDraw();
   image(ahm, 280, 390);
}
/********************************************************/
/*    Draw cirular scale                                */
/* Code from Adrian Fernandez 4-19-2013                 */
/********************************************************/
void CircularScale()
{
  float GaugeWidth=304;  
  comp.textSize(GaugeWidth/20);
  float StrokeWidth=1;
  float an;
  float DivxPhasorCloser;
  float DivxPhasorDistal;
  float DivyPhasorCloser;
  float DivyPhasorDistal;
  comp.strokeWeight(2*StrokeWidth);
  comp.stroke(255);
  comp.noFill();
   

  float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
  float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMinorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMinorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));  
     
    comp.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
  }

  DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
  DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMajorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMajorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
    if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
    {
      comp.strokeWeight(5);
      comp.stroke(255);
      
      comp.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
      comp.strokeWeight(1);
      comp.stroke(100, 255, 100);
      
      comp.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
    else
    {
      comp.strokeWeight(3);
      comp.stroke(255);
      comp.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
  }
}
/********************************************************/
/*    Draw cirular scale                                */
/* Code from Adrian Fernandez 4-19-2013                 */
/********************************************************/
void CircularScale2()
{
  float GaugeWidth=304;  
  ahm.textSize(GaugeWidth/20);
  float StrokeWidth=1;
  float an;
  float DivxPhasorCloser;
  float DivxPhasorDistal;
  float DivyPhasorCloser;
  float DivyPhasorDistal;
  ahm.strokeWeight(2*StrokeWidth);
  ahm.stroke(255);
  ahm.noFill();
   

  float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
  float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMinorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMinorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));  
     
    ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
  }

  DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
  DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMajorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMajorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
    if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
    {
      ahm.strokeWeight(5);
      ahm.stroke(255);
      
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
      ahm.strokeWeight(1);
      ahm.stroke(100, 255, 100);
      
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
    else
    {
      ahm.strokeWeight(3);
      ahm.stroke(255);
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
  }
}



/***************************************************/
/* Draws the compass pointer                       */
/***************************************************/ 
 void CompassPointer()
{
  comp.rotate(radians(yaw));  
  comp.stroke(0);
  //strokeWeight(1);
  comp.fill(255,255,255);
  
  comp.beginShape();
    comp.vertex(0,-105);
    comp.vertex(12, 100);
    comp.vertex(0, 80);
    comp.vertex(-12, 100);
  comp.endShape(CLOSE);
  
  comp.ellipse(0, 0, 9, 9);  
  comp.ellipse(0, 0, 3, 3); 
}
/***************************************************/
/* Draw the pitch scale                            */
/***************************************************/
void PitchScale()
{ 
  
  //ahm.push();
  //ahm.translate(0,0);
  
  ahm.stroke(255);
  ahm.fill(255);
  ahm.strokeWeight(2);
  ahm.textSize(14);
  ahm.textAlign(CENTER,CENTER);
  for (int i=-4;i<5;i++)
  {  
    if ((i==0)==false)
    {
      ahm.line(40, 20*i, -40, 20*i); // Draws wider lines
    }  
    ahm.text(""+i*20, 20, 20*i, -150, 20); // draws left side degrees
    ahm.text(""+i*20, -20, 20*i, 150, 20); // draws right  side degrees
  }
  //textAlign(CORNER);
  ahm.strokeWeight(1);
  for (int i=-9;i<10;i++)
  {  
    if ((i==0)==false)
    {    
      ahm.line(20, 10*i, -20, 10*i); // Draws narrower lines
    }
  }
 //ahm.pop();
}


/***************************************************/
/* Draw red axis lines                             */
/***************************************************/
void Axis()
{
  ahm.stroke(255,0,0);
  ahm.strokeWeight(2);
  ahm.line(-45, 0, 45, 0);
  ahm.line(0, 90, 0, -90);
  ahm.fill(100, 255, 100); //GREEN
  ahm.stroke(0);
  ahm.strokeWeight(1);
  ahm.triangle(0, -107, -6, -90, 6, -90);
  ahm.triangle(0, 107, -6, 90, 6, 90);
} 

but works without using it.

CODE WITHOUT USING PGRAPHICS
//Artificial Horizon+Compass by Adrian Fernandez 4-19-2013
//Built with Processing 1.5.1
int W=300; //My Laptop's screen width
int H=300;  //My Laptop's screen height
float Pitch;
float Bank;
float Azimuth;
float ArtificialHoizonMagnificationFactor=0.7;
float CompassMagnificationFactor=0.85;
float SpanAngle=120;
int NumberOfScaleMajorDivisions;
int NumberOfScaleMinorDivisions; 
PVector v1, v2; //For testing only

void setup()
{
  size(300, 300); 
  rectMode(CENTER);
  smooth();
  //strokeCap(SQUARE);//Optional
}

void draw()
{
  background(0); 
  //
  MakeAnglesDependentOnMouse();
  
  Horizon();
  
  //Borders();
  //Plane();
  ShowAngles(); 
  
}

void MakeAnglesDependentOnMouse() //For testing only.
{ 
  v2= new PVector(); 
  v1= new PVector(W/2, H/2);
  v2.x=mouseX;
  v2.y=mouseY;
  Bank = PVector.angleBetween(v1, v2);
  Pitch=mouseY-H;
  Azimuth=(180/PI*10*Bank)%360;
}

void Horizon()
{
  translate(150, 150);  
  
  
  noStroke();
  fill(0, 180, 255);//fills sky
  rect(2, 2, 298, 298);
  fill(95, 55, 40); //Fills ground
  rotate(-Bank);
  rect(0, 300+Pitch, 298, 298); 
  rotate(Bank);
  rotate(-PI-PI/6);
  SpanAngle=120;
  NumberOfScaleMajorDivisions=12;
  NumberOfScaleMinorDivisions=24;  
  CircularScale(); 
  rotate(PI+PI/6);
  rotate(-PI/6);  
  CircularScale();
  rotate(PI/6);
  rotate(-Bank); 
  PitchScale();
  Axis(); 
  rotate(Bank);
}





void Plane()
{
  fill(0);
  strokeWeight(1);
  stroke(0, 255, 0);
  triangle(-20, 0, 20, 0, 0, 25); 
  rect(110, 0, 140, 20);
  rect(-110, 0, 140, 20);
}

void CircularScale()
{
  float GaugeWidth=304;  
  textSize(GaugeWidth/20);
  float StrokeWidth=1;
  float an;
  float DivxPhasorCloser;
  float DivxPhasorDistal;
  float DivyPhasorCloser;
  float DivyPhasorDistal;
  strokeWeight(2*StrokeWidth);
  stroke(255);
  noFill();

  float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
  float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMinorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMinorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));   
    line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
  }

  DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
  DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMajorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMajorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
    if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
    {
      strokeWeight(5);
      stroke(0);
      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
      strokeWeight(1);
      stroke(100, 255, 100);
      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
    else
    {
      strokeWeight(3);
      stroke(255);
      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
  }
}

void Axis()
{
  stroke(255, 0, 0);
  strokeWeight(2);
  line(-45, 0, 45, 0);
  line(0, 90, 0, -90);
  fill(100, 255, 100);
  stroke(0);
  triangle(0, -107, -6, -90, 6, -90);
  triangle(0, 107, -6, 90, 6, 90);
} 

void ShowAngles()
{
  textSize(30);
  fill(50);
  noStroke();
  rect(-150, 400, 280, 40);
  rect(150, 400, 280, 40);
  fill(255); 
  Pitch=Pitch/5;
  int Pitch1=round(Pitch); 
  Bank=Bank*180/PI;
  int Bank1=round(Bank);
  text("Pitch:  "+Pitch1+" Deg", -20, 411, 500, 60);
  text("Bank:  "+Bank1+" Deg", 280, 411, 500, 60);
}

void Borders()
{
  noFill();
  stroke(0);
  strokeWeight(400);
  rect(0, 0, 1100, 1100);
  strokeWeight(200);
  ellipse(0, 0, 1000, 1000); 
  fill(0);
  noStroke();
  rect(4*W/5, 0, W, 2*H);
  rect(-4*W/5, 0, W, 2*H);
}

void PitchScale()
{  
  stroke(255);
  fill(255);
  strokeWeight(2);
  textSize(15);
  textAlign(CENTER,CENTER);
  for (int i=-4;i<5;i++)
  {  
    if ((i==0)==false)
    {
      line(40, 20*i, -40, 20*i);
    }  
    text(""+i*20, 60, 20*i, 100, 30);
    text(""+i*20, -60, 20*i, 100, 30);
  }
  //textAlign(CORNER);
  strokeWeight(2);
  for (int i=-9;i<10;i++)
  {  
    if ((i==0)==false)
    {    
      line(20, 10*i, -20, 10*i);
    }
  }
} 

Hello @philtkp,

This aligned the numbers to the scale:

    ahm.text(""+i*20, 20, 20*i -10, -150, 20); // draws left side degrees   
    ahm.text(""+i*20, -20, 20*i -10, 150, 20); // draws right  side degrees

I do not often use the text box so had to look that up!

Reference:
text() / Reference / Processing.org

This also worked on my end:

  pitch = ((int) map(mouseX, 00, width, -95,  95));
  pitch = constrain(pitch, -90, 90);
  
  int ym = 160-90; // y margin
  pitchDeg = (int) map(pitch, -90, 90, ym, 300- ym); // You want this mapped to the scale
  println(pitch, pitchDeg);
  
  ahm.noStroke();
  ahm.fill(0, 180, 255);//fills sky
  ahm.rect(0, 0, 300, 300);
  ahm.fill(95, 55, 40); //Fills ground
  
  ahm.rect(0, 0, 300, pitchDeg);

What data is being received for yaw, pitch and roll?
Helps on my end to simulate with mouse or otherwise.
I like to simulate!

Have fun!

:)

Another thing you can do with PGraphics is create the image in advance in setup()

Simplified example:

float SpanAngle=120;

int NumberOfScaleMajorDivisions;
int NumberOfScaleMinorDivisions;

int dir = 1;

PImage cpd, cpp;

// Global setup
void setup() {
  // Setup graphics
  size(400, 400);

  cpd = makeCompassDial();
  cpp = makeCompassPointer();

  imageMode(CENTER);
  image(cpd, width/2, height/2);
  image(cpp, 200, 200);
}

int angleDriver; // For linear and phase

// For counter
int wrap360(int angle)
  {
  //return (count + 360) % 360;    // Ok for one cycle!
  return (angle%360 + 360) % 360;  // In case angle is negative!
  }

void draw()
{
  background(255);
  image(cpd, width/2, height/2);

  //angleDriver = (angleDriver + dir + 360) % 360;  //dir = +1 or -1 
  angleDriver = wrap360(angleDriver + dir);
  
float angle = radians(180) * sin(radians(angleDriver));     // sinusoidal

 push();
  translate(width/2, height/2);
  rotate(angle);
  image(cpp, 0, 0);
 pop();
 
 fill(0);
 textAlign(CENTER, TOP);
 textSize(24);
 //text((int)((degrees(angle)%360 + 360) % 360), width/2, 20);
 text(wrap360((int)degrees(angle)), width/2, 20);
}

/**********************************************************/
/* Draw Compass Dial                               */
/**********************************************************/

PGraphics cp; // Global because I was passing a function

PImage makeCompassDial() {

  cp = createGraphics (300, 300);

  cp.beginDraw();
  cp.background(255, 0, 0, 10); // some opacity for development!
  cp.translate(450, 50);

 cp.pushMatrix();

  cp.noStroke();
  cp.fill(108, 156, 255); // Fill sky color
  cp.ellipse(-300, 100, 220, 220);

 cp.popMatrix();

 cp.pushMatrix();

  /* Draws the circular scale on compass */
  cp.translate(-300, 100);

  cp.stroke(255);
  cp.strokeWeight(2);
  cp.noFill();
  cp.ellipse(0, 0, 220, 220);

  SpanAngle=180;
  NumberOfScaleMajorDivisions=18;
  NumberOfScaleMinorDivisions=36;;

  cp.translate(-300, 100);
  cp.textSize(20);
  cp.fill(0);
  cp.textAlign(CENTER);
  cp.text("W", 165, -92);
  cp.text("E", 430, -92);
  cp.text("N", 300, -230);
  cp.text("S", 300, 42);
  cp.rotate(PI/4);
 cp.popMatrix();

  cp.endDraw();

  PImage img = cp.get();
  return  img;
}

/***************************************************/
/* Draw Compass Pointer                       */
/***************************************************/

PImage makeCompassPointer()
{
  PGraphics cp2 = createGraphics (200, 200);

  cp2.beginDraw();
  cp2.translate(100, 100);
  cp2.stroke(0);
  strokeWeight(2);
  cp2.fill(255, 255, 255);

  cp2.triangle(0, -100, -10, 100, 10, 100);

  cp2.endDraw();

  PImage img1 = cp2.get();
  return  img1;
}

void mousePressed()
  {
  dir *= -1;  //chamge direction
  }

I was aware that you could do that. “SWEET”

Been trying to get the pitch working properly. I’m thing i need to map the ground rectangle. but anything tried miss aligns the pitch scale. this is what I’m trying to get

I know these should be at 90 increments of a 360 degree cycle.

CODE


// LINEAR COMPASS
import processing.serial.*;
Serial fd;

PGraphics hdg;
PGraphics comp;
PGraphics ahm;
PImage fade;


float Pitch;
float Bank;
float Azimuth;
float degree1;
//float yaw = 0.0f;
float yawOffset = 0.0f;
float SpanAngle=120;
//float GaugeWidth=304;  
//float StrokeWidth=1;
//float an;
//float DivxPhasorCloser;
//float DivxPhasorDistal;
//float DivyPhasorCloser;
//float DivyPhasorDistal;
int W=300; //My Laptop's screen width
int H=300; 
int degree = 0; 
int heading = 0;
int pitch = 0;
int roll = 0;
int yaw = 0;
int yawDeg = 0;
int rollDeg = 0;
int pitchDeg = 0;
int NumberOfScaleMajorDivisions;
int NumberOfScaleMinorDivisions;
PVector v1, v2; 
//
// ---------------------------------------------------------------
//
void setup()
{
  // init
  size(800, 800, P3D);
  
  ahm = createGraphics(300,300);

    
  fd = new Serial(this, Serial.list()[1], 115200);
  // Defer callback until new line
  fd.bufferUntil('\n');
 
  rectMode(CENTER);
  smooth();
  strokeCap(SQUARE);//Optional
  background(0);
} // func 
 
void draw() 
{ 
 
 drawHorz();

 
 
 println("PITCH: "+pitch," ROLL: "+roll,"YAW: "+yaw);
//println("Linear compass : DEGREE = "+ degree," YAW DEGREE = "+ (360-(yawDeg%360)));
  
}

/**********************************************************/
/* DRAW ROLL/PITCH INDICATOR                              */
/**********************************************************/
void drawHorz() {
  
  ahm.beginDraw();
  ahm.translate(0,0);  
  
 //  int pitchDeg = 360-(pitch%360);
  //Bank = (int)map(roll, 0, 360, 0, 360);
  //rollDeg = (int)((Bank%360));

 if((int)Pitch >= 1 && (int)Pitch <= 180)
     pitchDeg = (int)pitch;
 else pitchDeg = 360 + (int)Pitch;
 
  //Pitch = (int)map(pitch, 0, 360, 0, 360);
  //pitchDeg = (int)((Pitch%360));
  pitchDeg = ((int) map(pitch, 00, width, -95,  95));
  pitchDeg = constrain(pitch%360, -90, 90);
  
  int ym = 160-90; // y margin
  pitchDeg = (int) map(pitch, -90, 90, ym, 300- ym); // You want this mapped to the scale
  pitchDeg = (pitchDeg%360 + 360) % 360; // keep pitchDeg positive
 
  println("pitch: ",+pitch," Pitch:",+Pitch," pitchDeg: ",(pitchDeg%360));
  
  ahm.noStroke();
  
  ahm.fill(0, 180, 255);//fills sky
  ahm.rect(0, 0, 300, 300);
  
  ahm.fill(95, 55, 40); //Fills ground
  ahm.rect(0, ((pitchDeg%360)), 300, pitch); 
  
  ahm.translate(150,150); // Places pitch scale center
  ahm.rotate(-PI-PI/6); // Centers upper scale
 
  SpanAngle=120;
  NumberOfScaleMajorDivisions=12;
  NumberOfScaleMinorDivisions=24;  
 
  CircularScale2(); //Draws upper scale
  ahm.rotate(PI+PI/6); // Centers lower scale
  ahm.rotate(-PI/6);   //
  CircularScale2(); //Draws lower scale
  ahm.rotate(PI/6); // Aligns pitch scale and axis
  //ahm.rotate(-rollDeg%360); 
  
  
  PitchScale();
  Axis(); 
  //ahm.pop();
  //ahm.rotate(rollDeg%360);
  ahm.endDraw();
   image(ahm, 280, 390);
}
/********************************************************/
/*    Draw cirular scale                                */
/* Code from Adrian Fernandez 4-19-2013                 */
/********************************************************/
void CircularScale2()
{
  float GaugeWidth=304;  
  ahm.textSize(GaugeWidth/20);
  float StrokeWidth=1;
  float an;
  float DivxPhasorCloser;
  float DivxPhasorDistal;
  float DivyPhasorCloser;
  float DivyPhasorDistal;
  ahm.strokeWeight(2*StrokeWidth);
  ahm.stroke(255);
  ahm.noFill();
   

  float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
  float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMinorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMinorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));  
     
    ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
  }

  DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
  DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;

  for (int Division=0;Division<NumberOfScaleMajorDivisions+1;Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMajorDivisions;  
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
    if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
    {
      ahm.strokeWeight(5);
      ahm.stroke(255);
      
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
      ahm.strokeWeight(1);
      ahm.stroke(100, 255, 100);
      
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
    else
    {
      ahm.strokeWeight(3);
      ahm.stroke(255);
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
  }
}


/***************************************************/
/* Draw the pitch scale                            */
/***************************************************/
void PitchScale()
{ 
  
  //ahm.push();
  //ahm.translate(0,0);
  
  ahm.stroke(255);
  ahm.fill(255);
  ahm.strokeWeight(2);
  ahm.textSize(14);
  ahm.push();
  ahm.translate(0,0);
  ahm.textAlign(CENTER,CENTER);
  for (int i=-4;i<5;i++)
  {  
    if ((i==0)==false)
    {
      ahm.line(40, 20*i, -40, 20*i); // Draws wider lines
    }  
        
   ahm.text(""+i*20, 20, 20*i -10, -150, 20); // draws left side degrees   
   ahm.text(""+i*20, -20, 20*i -10, 150, 20); // draws right  side degrees
   
  }
  //textAlign(CORNER);
  ahm.strokeWeight(1);
  for (int i=-9;i<10;i++)
  {  
    if ((i==0)==false)
    {    
      ahm.line(20, 10*i, -20, 10*i); // Draws narrower lines
    }
  }
 ahm.pop();
}

void serialEvent (Serial fd) 
{
  // get the ASCII string:
  String rpstr = fd.readStringUntil('\n');
  if (rpstr != null) {
    String[] list = split(rpstr, ':');
    pitch = ((int)float(list[0]));
    roll = ((int)float(list[1]));
    yaw = ((int)float(list[2]));
        
  }
}

Hello @philtkp,

I played with your code a bit.

Open at your own risk:

Summary
// LINEAR COMPASS
import processing.serial.*;
Serial fd;

PGraphics hdg;
PGraphics comp;
PGraphics ahm;
PImage fade;

float Pitch;
float Bank;
float Azimuth;
float degree1;
//float yaw = 0.0f;
float yawOffset = 0.0f;
float SpanAngle=120;
//float GaugeWidth=304;
//float StrokeWidth=1;
//float an;
//float DivxPhasorCloser;
//float DivxPhasorDistal;
//float DivyPhasorCloser;
//float DivyPhasorDistal;
int W=300; //My Laptop's screen width
int H=300;
int degree = 0;
int heading = 0;
int pitch = 0;
int roll = 0;
int yaw = 0;
int yawDeg = 0;
int rollDeg = 0;
int pitchDeg = 0;
int NumberOfScaleMajorDivisions;
int NumberOfScaleMinorDivisions;
PVector v1, v2;

int m = 2; // Multiplier

//
// ---------------------------------------------------------------
//

void setup()
{
  // init
  size(400, 400, P3D);

  ahm = createGraphics(300, 300);

  //fd = new Serial(this, Serial.list()[1], 115200);
  //// Defer callback until new line
  //fd.bufferUntil('\n');

  rectMode(CENTER);
  smooth();
  strokeCap(SQUARE);//Optional
  background(0);
} // func

void draw()
{ 
  background(128);
   
  translate(width/2, height/2);
  imageMode(CENTER);
  
  m = 1; // 1 for 90, 2 for 180 scale Just the scale!
  
  int range = 100;
  
  // Only focused on this now:
  pitch = (int) map(mouseY, 0, height, -range, range); //global
  
  // Only focused on this now:
  roll = (int) map(mouseX, 0, height, -range, range); //global

  if ((abs(roll) | abs(pitch)) > 90)  // DAnger! Danger!
    background(255, 0, 0);

  int ym = 150-90; // y margin
  pitchDeg = (int) map(pitch, -90, 90, ym, 300-ym); // You want this mapped to the scale  
  drawHorz(pitchDeg);
  
 push();
  //rotateZ(radians(roll));
  image(ahm, 0, 0);
 pop();

  println("PITCH: "+pitch, " ROLL: "+roll, "YAW: "+yaw);
}

/**********************************************************/
/* DRAW ROLL/PITCH INDICATOR                              */
/**********************************************************/
void drawHorz(int pitchDeg) {

  ahm.beginDraw();
  ahm.translate(0, 0);
  ahm.noStroke();

  ahm.fill(0, 180, 255);//fills sky
  ahm.rect(0, 0, 500, 500);

  ahm.fill(95, 55, 40); //Fills ground
  //ahm.rect(0, 0, 300, pitchDeg);
  
// First atempt:
  //ahm.beginShape();
  //ahm.vertex(0, 0);
  //ahm.vertex(300, 0);
  //ahm.vertex(300, pitchDeg + 150*sin(radians(roll)));
  //ahm.vertex(0,   pitchDeg - 150*sin(radians(roll)));  
  //ahm.endShape();
  
  float halfW = 300/2;                // rectangle half-width
  float rollShift = tan(radians(roll)) * halfW;  
  
  ahm.beginShape();
  ahm.vertex(0, pitchDeg - rollShift); // top-left moves up/down
  ahm.vertex(300, pitchDeg + rollShift); // top-right moves up/down
  ahm.vertex(300, 300);                // bottom-right stays
  ahm.vertex(0, 300);                  // bottom-left stays
  ahm.endShape(CLOSE);
    
  ahm.translate(150, 150); // Places pitch scale center
  ahm.rotate(-PI-PI/6); // Centers upper scale

  SpanAngle=120;
  NumberOfScaleMajorDivisions=12;
  NumberOfScaleMinorDivisions=24;

  CircularScale2(); //Draws upper scale
  ahm.rotate(PI+PI/6); // Centers lower scale
  ahm.rotate(-PI/6);   //
  CircularScale2(); //Draws lower scale
  ahm.rotate(PI/6); // Aligns pitch scale and axis
  
  ahm.rotate(radians(roll));

  PitchScale();
  ahm.endDraw();
}
/********************************************************/
/*    Draw cirular scale                                */
/* Code from Adrian Fernandez 4-19-2013                 */
/********************************************************/
void CircularScale2()
{
  float GaugeWidth=304;
  ahm.textSize(GaugeWidth/20);
  float StrokeWidth=1;
  float an;
  float DivxPhasorCloser;
  float DivxPhasorDistal;
  float DivyPhasorCloser;
  float DivyPhasorDistal;
  ahm.strokeWeight(2*StrokeWidth);
  ahm.stroke(255);
  ahm.noFill();


  float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
  float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;

  for (int Division=0; Division<NumberOfScaleMinorDivisions+1; Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMinorDivisions;
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));

    ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
  }

  DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
  DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;

  for (int Division=0; Division<NumberOfScaleMajorDivisions+1; Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMajorDivisions;
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
    if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
    {
      ahm.strokeWeight(5);
      ahm.stroke(255);

      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
      ahm.strokeWeight(1);
      ahm.stroke(100, 255, 100);

      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    } else
    {
      ahm.strokeWeight(3);
      ahm.stroke(255);
      ahm.line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
  }
}


/***************************************************/
/* Draw the pitch scale                            */
/***************************************************/
void PitchScale()
{
  ahm.stroke(255);
  ahm.fill(255);
  ahm.strokeWeight(2);
  ahm.textSize(14);
  ahm.push();
  ahm.translate(0, 0);
  ahm.textAlign(CENTER, CENTER);
  for (int i=-4; i<5; i++)
  {
    if ((i==0)==false)
    {
      ahm.line(40, 20*i, -40, 20*i); // Draws wider lines
    }

    ahm.text(""+i*20*m, 20, 20*i -10, -150, 20); // draws left side degrees
    ahm.text(""+i*20*m, -20, 20*i -10, 150, 20); // draws right  side degrees
  }
  //textAlign(CORNER);
  ahm.strokeWeight(1);
  for (int i=-9; i<10; i++)
  {
    if ((i==0)==false)
    {
      ahm.line(20, 10*i, -20, 10*i); // Draws narrower lines
    }
  }
  ahm.pop();
}

Roll and pitch are typically +/- 90 for Euler angles.
You will run into issues greater than this and may have to give it further consideration as the axis flip and you get Gimbal lock.
You may have to consider quaternions… I had these issues before and manage to sort it out. That was a while back!

Try and provide runnable code please.
Mapping for mouse to represent your ranges helps.
Some of the naming was hard to read like Pitch and pitch; variable names should not be upper case (Java rules) and these are too similar.
It is easy to rename everything with the Processing rename utility!

I hope the feedback is well received as it was intended to be.

Have fun!

:)

Risk has been Taken. I’m still here. Your feedback has been well received. This is all a learning curve for me. I’ll have to read up on quaternions. I’ve been trying to clean up my code. I see what you mean by some of the naming variables. I’m glad that is is the only thing that keeps me up at night these days.

I stepped back a bit to make sure i was understanding the use of translate(). Now i have a question. since i’ve been using PGraphics to display my screens without a problem. till now, i’m unable to display a cube or a shape using PGraphics. acn these be used together? I was able to get what wanted to do but just curious. this way im to visualize my bearings

I really appreciate the knowledge you have shared. :beer_mug:

Exploring PGraphics and got a bit carried away with this one!
There may be something in there that can help.

It is April 1… so open at your own risk!

Code

April Fools! This is not April Fools code. :)

April Fools' Day - Wikipedia

See Gallery post:
Lost in Space PGraphics Exploration

:)

Nice! :grinning_face_with_smiling_eyes:

I just stepped back a bit to see that i understood the commands i was using. it has helped a lot.

@glv

I’ve been trying several without any progress. I was wondering if this could be done with a sphere. wrapping it with a jpg of the horizon.

now i just need to figure out how to control the pitch and the roll properly. You think this is a good alternative? I tried it with the code i have, but it’s a bit quirky

CODE

This is some code i found on the forum from 2017

void setup() { 
  size(600, 600, P3D); 
  background(0); 
  
  PImage earth = loadImage( "horz.jpg");
  globe = createShape(SPHERE, 100); 
  globe.setStroke(false);
  globe.setTexture(earth);
  noStroke();
}

void draw() {
  background(0);
  translate(width/2, height/2);
  rotateY(map(mouseX,0,width,-PI,PI));
  rotateZ(map(mouseY,0,width,-PI,PI));
  shape(globe);
}

You will figure it out!
The order matters for Euler rotations… yaw, pitch and roll.

I suggest writing some keyboard controls for the simulations.
I did not include the “extras” in my code below.

I remember having one of those floating sphere compasses in my Ford Falcon way back when!

Code
float yaw, pitch, roll;
float displayYaw; 
float offset;
int timer = 0;

//PGraphics pg; 

PShape globe;

public void settings()
  { 
  size(500, 500, P3D);
  smooth();
  }

public void setup()
  {
  /* size commented out by preprocessor */;
  
  surface.setLocation(10, 10); // Fixes occasional issue of not displaying!
  surface.setTitle("Lost in Space");
  
  background(0); //Initial
  
  // Imeage was generated with this:
  //pg = createGraphics(4*360, 4*180, P2D);
  //createHorizon();
  
  // Initial styles  
  textSize(24);  
  /* smooth commented out by preprocessor */; // This is the default
    
  PImage earth = loadImage("horizon.png");
  globe = createShape(SPHERE, 100); 
  globe.setStroke(false);
  //globe.setTexture(pg);
  globe.setTexture(earth);
  } 


public void draw()
  {
  background(0);
  
  //Common styles (consider moving to setup() )
  fill(255);
  textSize(24); //Always set maximum size in setup()
  textAlign(CENTER, CENTER);
  
 push(); 
  translate(width/2, height/2);
  lights();
 
  //ypr();    // keyboard and\or mouse controls not included
  
  if (frameCount<2*60)
    {
    offset = 0;
    yaw = pitch = roll = 0;
    println(frameCount);
    }
  else if( frameCount>=2*60 && frameCount<4*60) 
    {
    offset = -90 - 30;  // Try with offset set to 0 to see why I did this  
    yaw = pitch = roll = 0;
    println(frameCount);    
    }  
  else
    {
    // These are in degrees
    offset = -90 - 30;  // Try with offset set to 0 to see why I did this  
    yaw = timer/3.0;
    pitch = 10*sin(timer*(TAU/(4*360)));
    roll =  10*sin(timer*(TAU/(0.5*360)));
    
    timer++;
    }
  
  angleEulerUpdate(yaw, pitch, roll, offset);
  
  shape(globe);
 pop(); 
  }


public void angleEulerUpdate(float yaw, float pitch, float roll, float offset)
  {       
  rotateY(radians(offset)); // This is for model alignment. 
  rotateY(radians(-yaw));   // later
  rotateZ(radians(pitch));  // pitch
  rotateX(radians(roll));   // roll  
  }

I generated an image with a PGraphics to provide some sense of orientation and understand the texturing and saved it as an image:

The 0 (1/2 of it) was lost in initial attempts so I offset it and then adjusted in the code.

Have fun! I know I am.

Reference:

PShape / Processing.org < 3D textures

:)


import processing.serial.*;
Serial fd;

PShape globe;

float SpanAngle=120;
float yawOffset = 0.0f;

int pitch = 0;
int roll = 0;
int yaw = 0;
int NumberOfScaleMajorDivisions;
int NumberOfScaleMinorDivisions;

void setup() {
size(600, 600, P3D);

// fd = new Serial(this, Serial.list()[1], 115200);
// fd.bufferUntil(‘\n’);

// background(0);
//String http = “http://”;
PImage earth = loadImage( “horz.jpg”);
globe = createShape(SPHERE, 170);
globe.setStroke(false);
globe.setTexture(earth);
noStroke();
}

void draw() {
background(0);

translate(width/2,height/2); // Places pitch scale center

push();
translate(0,0,170); // places pitch scaale and axis infront of globe

//rotateZ(radians(roll));
rotateZ(map(mouseX,0,width,-PI,PI));
Axis();
PitchScale();

rotate(-PI-PI/6); // Centers upper scale

SpanAngle=120;
NumberOfScaleMajorDivisions=12;
NumberOfScaleMinorDivisions=24;  

CircularScale(); //Draws upper scale
rotate(PI+PI/6); // Centers lower scale
rotate(-PI/6);   //
CircularScale(); //Draws lower scale
rotate(PI/6);    // Aligns pitch scale and axis

pop();

rotateX(map(mouseY,0,width,-PI,PI));
//rotateX(radians(pitch));
//rotateZ(radians(roll));

shape(globe);

}

///
// Draw red axis lines                             /
///
void Axis()
{
stroke(255,0,0);
strokeWeight(2);
line(-45, 0, 45, 0);
line(0, 90, 0, -90);
fill(100, 255, 100); //GREEN
stroke(0);
strokeWeight(1);
triangle(0, -107, -6, -90, 6, -90);
triangle(0, 107, -6, 90, 6, 90);
}

///
/ Draw the pitch scale                            /
///
void PitchScale()
{

//ahm.push();
//ahm.translate(0,0);

stroke(255);
fill(255);
strokeWeight(2);
textSize(14);
//  push();
translate(0,0);
textAlign(CENTER,CENTER);
for (int i=-4;i<5;i++)
{
if ((i==0)==false)
{
line(40, 20i, -40, 20i); // Draws wider lines
}

text(“”+i20, 20, 20i -10, -150, 20); // draws left side degrees
text(“”+i20, -20, 20i -10, 150, 20); // draws right  side degrees

}
//textAlign(CORNER);
strokeWeight(1);
for (int i=-9;i<10;i++)
{
if ((i==0)==false)
{
line(20, 10i, -20, 10i); // Draws narrower lines
}
}

//image(ahmglass,-148,-148);
}
///
//*    Draw cirular scale                                /
// Code from Adrian Fernandez 4-19-2013                 */
///
void CircularScale()
{
float GaugeWidth=304;
textSize(GaugeWidth/20);
float StrokeWidth=1;
float an;
float DivxPhasorCloser;
float DivxPhasorDistal;
float DivyPhasorCloser;
float DivyPhasorDistal;
strokeWeight(2*StrokeWidth);
stroke(255);
noFill();

float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;

for (int Division=0;Division<NumberOfScaleMinorDivisions+1;Division++)
{
an=SpanAngle/2+DivisionSpanAngle/NumberOfScaleMinorDivisions;
DivxPhasorCloser=DivCloserPhasorLenghtcos(radians(an));
DivxPhasorDistal=DivDistalPhasorLenghtcos(radians(an));
DivyPhasorCloser=DivCloserPhasorLenghtsin(radians(an));
DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));

line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);

}

DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;

for (int Division=0;Division<NumberOfScaleMajorDivisions+1;Division++)
{
an=SpanAngle/2+DivisionSpanAngle/NumberOfScaleMajorDivisions;
DivxPhasorCloser=DivCloserPhasorLenghtcos(radians(an));
DivxPhasorDistal=DivDistalPhasorLenghtcos(radians(an));
DivyPhasorCloser=DivCloserPhasorLenghtsin(radians(an));
DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
{
strokeWeight(5);
stroke(255);

  line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
  strokeWeight(1);
  stroke(100, 255, 100);
  
  line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
}
else
{
  strokeWeight(3);
  stroke(255);
  line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
}

}
}

//***************************************************
//*
//***************************************************
void serialEvent (Serial fd)
{
// get the ASCII string:
String rpstr = fd.readStringUntil(‘\n’);
if (rpstr != null) {
String
 list = split(rpstr, ‘:’);
pitch = ((int)float(list[0]));
roll = ((int)float(list[1]));
yaw = ((int)float(list[2]));

}
}

Sometimes it is one of these when rotating text (from my experience):

In your case I moved the shape up:

  translate(width/2, height/2, -100); // Places pitch scale center
  
  push();
  rotateX(map(mouseY,0,width,-PI,PI));
  //rotateX(radians(pitch));
  //rotateZ(radians(roll));
   
  shape(globe);
  pop();

:)

glv

CODE

import processing.serial.*;
Serial fd;

PShape globe;

float SpanAngle=120;
float yawOffset = 0.0f;

int pitch = 0;
int roll = 0;
int yaw = 0;
int NumberOfScaleMajorDivisions;
int NumberOfScaleMinorDivisions;

void setup() {

  size(600, 600, P3D);

 // fd = new Serial(this, Serial.list()[1], 115200);
  //fd.bufferUntil('\n');

  PImage earth = loadImage( "horz.jpg");
  globe = createShape(SPHERE, 170);
  globe.setStroke(false);
  globe.setTexture(earth);
  noStroke();
}

void draw() {

  background(0);
  translate(width/2, height/2, -100); // Places pitch scale center
  push();
  rotateX(map(mouseY,0,width,-PI,PI));
  rotateZ(map(mouseX,0,width,-PI,PI)); //  <---------------------
  //rotateX(radians(pitch));
  //rotateZ(radians(roll));


  shape(globe);

  pop();

  push();
  translate(0, 0, 170); // places pitch scaale and axis infront of globe

  push();
  rotateZ(map(mouseX,0,width,-PI,PI));//   <-----------------------
  //rotateZ(radians(roll));
  
  PitchScale();
  Axis();
  pop();

  rotate(-PI-PI/6); // Centers upper scale

  SpanAngle=120;
  NumberOfScaleMajorDivisions=12;
  NumberOfScaleMinorDivisions=24;

  CircularScale(); //Draws upper scale
  rotate(PI+PI/6); // Centers lower scale
  rotate(-PI/6);   //
  CircularScale(); //Draws lower scale
  rotate(PI/6);    // Aligns pitch scale and axis
  pop();
}

//***************************************************/
//* Draw red axis lines                             */
//***************************************************/
void Axis()
{
  stroke(255, 0, 0);
  strokeWeight(2);
  line(-45, 0, 45, 0);
  line(0, 90, 0, -90);
  fill(100, 255, 100); //GREEN
  stroke(0);
  strokeWeight(1);
  triangle(0, -107, -6, -90, 6, -90);
  triangle(0, 107, -6, 90, 6, 90);
}

//***************************************************/
/* Draw the pitch scale                            */
//***************************************************/
void PitchScale()
{

  stroke(255);
  fill(255);
  strokeWeight(2);
  textSize(14);
  //  push();
  translate(0, 0);
  textAlign(CENTER, CENTER);
  for (int i=-4; i<5; i++)
  {
    if ((i==0)==false)
    {
      line(40, 20*i, -40, 20*i); // Draws wider lines
    }

    text(""+i*20, 20, 20*i -10, -150, 20); // draws left side degrees
    text(""+i*20, -20, 20*i -10, 150, 20); // draws right  side degrees
  }
  //textAlign(CORNER);
  strokeWeight(1);
  for (int i=-9; i<10; i++)
  {
    if ((i==0)==false)
    {
      line(20, 10*i, -20, 10*i); // Draws narrower lines
    }
  }

  
}
//********************************************************/
//*    Draw circular scale                               */
//* Code from Adrian Fernandez 4-19-2013                 */
//********************************************************/
void CircularScale()
{
  float GaugeWidth=304;
  textSize(GaugeWidth/20);
  float StrokeWidth=1;
  float an;
  float DivxPhasorCloser;
  float DivxPhasorDistal;
  float DivyPhasorCloser;
  float DivyPhasorDistal;
  strokeWeight(2*StrokeWidth);
  stroke(255);
  noFill();


  float DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/9-StrokeWidth;
  float DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.5-StrokeWidth;

  for (int Division=0; Division<NumberOfScaleMinorDivisions+1; Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMinorDivisions;
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));

    line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
  }

  DivCloserPhasorLenght=GaugeWidth/2-GaugeWidth/10-StrokeWidth;
  DivDistalPhasorLenght=GaugeWidth/2-GaugeWidth/7.4-StrokeWidth;

  for (int Division=0; Division<NumberOfScaleMajorDivisions+1; Division++)
  {
    an=SpanAngle/2+Division*SpanAngle/NumberOfScaleMajorDivisions;
    DivxPhasorCloser=DivCloserPhasorLenght*cos(radians(an));
    DivxPhasorDistal=DivDistalPhasorLenght*cos(radians(an));
    DivyPhasorCloser=DivCloserPhasorLenght*sin(radians(an));
    DivyPhasorDistal=DivDistalPhasorLenght*sin(radians(an));
    if (Division==NumberOfScaleMajorDivisions/2|Division==0|Division==NumberOfScaleMajorDivisions)
    {
      strokeWeight(5);
      stroke(255);

      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
      strokeWeight(1);
      stroke(100, 255, 100);

      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    } else
    {
      strokeWeight(3);
      stroke(255);
      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal);
    }
  }
}


//***************************************************
//*
//***************************************************
void serialEvent (Serial fd)
{
  // get the ASCII string:
  String rpstr = fd.readStringUntil('\n');
  if (rpstr != null) {
    String[] list = split(rpstr, ':');
    pitch = ((int)float(list[0]));
    roll = ((int)float(list[1]));
    yaw = ((int)float(list[2]));
  }
}

I have it working like I think it should (needs to be cleaned up) the only thing I’m having an issue with is, I had to use the same call twice (rotateZ(map(mouseX,0,width,-PI,PI)):wink: to make the globe, axis and pitch scale rotate together without also rotating the Circular Scale. I’ll keep at it.

Hello @philtkp,

You may consider something like this:

void draw()
  {
  background(0);
  lights();

  float rollAngle  = map(mouseX, 0, width,  -PI, PI);
  float pitchAngle = map(mouseY, 0, height, -PI, PI);

  translate(width/2, height/2, zOffset);

  drawGlobe(pitchAngle, rollAngle);  
  drawOverlay(rollAngle);
  }

:)

@glv

Thought i would give the square version of the indicator another try.

CODE
int pitch;
int yaw;
int roll;

void setup()
{
size(400,400,P3D);
smooth();
}

void draw()
{

  background(0); 
  
  pitch = ((int) map(mouseY-200,0, 400, 0, 1200));
  roll = ((int) map(mouseX,0, 360, 0, 360));
  
  translate(width/2,height/2); 
  stroke(0);
  
  
 
  println("PITCH: ",pitch + " ROLL: ", roll);
  
  pushMatrix();

  rotate(radians(roll%360));
 
  noStroke();
  
  fill(0, 180, 255); // SKY COLOR
  rect(-250, -250, width+100, height+100 );
  
  fill(95, 55, 40); // GROUND COLOR
  rect(-250, pitch-250, width+100, height+100);
  
  stroke(255);
  strokeWeight(1);
  line(-250, pitch-250, 250, pitch-250); // Draw line to see center of horizon separation
  
  popMatrix();
  
  stroke(255);
  strokeWeight(1);
  line(0, -100, 0, 100); // Draw cross hairs for visual reference
  line(-100, 0, 100, 0);
  
  stroke(0);
  strokeWeight(60);
  noFill();
  rect(-200, -200, width, height,75); // Draw the outside frame
  
}