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.
:)
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.
:)
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.![]()
// 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);
}
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;
}
:)
@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
// 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.
//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.
// 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:
// 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. ![]()
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!
April Fools! This is not April Fools code. :)
See Gallery post:
Lost in Space PGraphics Exploration
:)
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
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!
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
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))
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);
}
:)
Thought i would give the square version of the indicator another try.
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
}