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;
}
:)
ok, just have a 2 brain cell moment!
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
// 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. ![]()
Hello again @philtkp,
There are many tutorials here and some may help:
Tutorials / Processing.org
I keep referring to the above and the references after all these years!
After all that is said and done you have to write a lot of code and experiment to fully understand how everything ties togethor.
I strongly encourage you to write small snippets of code to understand behavior.
Then work on piecing it togethor.
I provided an example that complements your code.
The left half is the original code and mouse only is ranged for left half!
I added a PGraphics and display it on right side.
I had to change some of the translates and constrain the roll.
// LINEAR COMPASS
//import processing.serial.*;
//Serial fd;
PGraphics hdg;
PGraphics comp;
PGraphics ahm;
PImage fade;
float Pitch;
float Bank;
float Azimuth;
float degree1;
float yawOffset = 0.0f;
float SpanAngle=120;
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
// Added:
PGraphics test()
{
PGraphics p3d = createGraphics(300, 300, P3D);
p3d.beginDraw();
p3d.translate(p3d.width/2, p3d.height/2); //origin at center
p3d.lights();
//p3d.background(0); // Try with or without this!
p3d.background(255, 0, 0, 20); // A bit of transparencey for testing
p3d.fill(0, 255, 0);
p3d.rotateX(radians(-pitch));
p3d.rotateZ(radians(roll));
float s = 2.0;
p3d.box(s*40, s*10, s*90);
p3d.endDraw();
return p3d;
}
void setup()
{
// init
size(800, 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);
push(); //0
translate(width/4, height/2); //changed
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, width/2, -range, range); //global // changed
roll = constrain(roll, -100, 100); //added
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);
//rotateZ(radians(roll));
image(ahm, 0, 0);
println("PITCH: "+pitch, " ROLL: "+roll, "YAW: "+yaw);
pop(); //0
// Added:
push(); //1
PGraphics test3D = test();
stroke(255, 0, 0);
strokeWeight(10);
strokeCap(ROUND); //otherwise point is a square
point(0, 0, 0); // Origin (0, 0, 0)
// Method 1
//image(test3D, width/2 + 50, 50); // Centers it on right half
// or:
// Method 2
translate(width/2, 0); // Origin now on right half top left
translate(width/4, height/2); // Origin is at center of righ half, translations cumulative!
imageMode(CENTER);
image(test3D, 0, 0);
point(0, 0, 0); // Origin (0, 0, 0)
// or:
// Method 3
//translate(width/2, 0);
//imageMode(CORNERS);
//image(test3D, 50, 50);
//point(0, 0, 0); // Origin (0, 0, 0)
pop(); //2
}
/**********************************************************/
/* 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();
}
Programming with translations and rotations can certainly be a challenge!
References:
See also the references for:
perspective
ortho
These may explain your second image with the shape is off to the right when it is not centered. You could also move the camera! That is another topic.
:)