Horizon artificial and compass animation

Hi guys, I want to draw an Artificial horizon and a compass by processing can someone tell me how to do that please, I put here a picture of what I want to realize. output_aFMRzy

Can we see the picture please?

Hi I upoalded the picture you can see it

Have you got any code so far? Having something to work from will help.

I recommend starting with the circles around both of these as well as the white lines within them.

That’s what I wanted to tell you , I have the code of this animation I found it in a blog but I want to understand how its works step by step I mean how to draw this two instrumnet steb by step I want to realize it , if I give yo the code can you tell me how to draw them begining by circles and colors …ect

Could we see that code?
What language is it in?

Hi zohrahamadene,

It might feel intimidating but you really just need to break it down to elementary pieces and everything will comme together!

Let’s start with the artificial horizon:

  • First you have those thin lines in circles. You can see that there is one small then one big then one small and so on. Second it is simply just some stroke arrange in circle and spaced out by the same angle every time.
  • Then you have the big green strokes on top of those lines. This time you can use a rectangle fill it in green with a black stroke. Then you just need to rotate it to the proper angle.
  • After you have those lines in the middle. One big, one small, and so on. All spaced out the same way.

As you can see every individual piece taken separately is not that complex. Draw them one by one, and forget about the animation for now.

If you get stuck at drawing some specific part come back here with that specific problem and we’ll be happy to help :slight_smile:

3 Likes

Hi jb4x, I’m a beginner in Processing I dont know details about it !

I mean for now I want to learn how to draw cirlce then those lines and colors…

And that’s actually an excellent exercice to try and get to know more about Processing!

Try this piece of code for starter:

void setup() {
  size(500, 500);  // Set the size of the canvas
  background(20);  // Set the color of the background
  stroke(200);  // Set the color of the stroke
  strokeWeight(1);  // Set the thickness of the stroke

  float angleStep = HALF_PI / 30; // The angle between two stroke (In this case 30 would be the number of strokes in a quarter of circle
  boolean longStroke = false;  // Will be use to draw a short line or a long line

  translate(width/2, height/2);  // Translate all the drawing by half the width and half the height to center it 
  for (float angle = 0; angle < TWO_PI; angle += angleStep) { // Looping from an angle of 0 to an angle of 2 PI to draw a full cricle of line
    rotate(angleStep); // Rotate the line that we draw by the angleStep (It is cumulative so the first time it will rotate by angleStep, the second time by 2*angleStep and so on)
    if (longStroke) { // If we need to draw a long line
      line(0, -200, 0, -180); // We draw the long line. Note that it is not drawn where it will end up but just straight above the origin. The rotating is done by the rotate function boferhand and so is the translation with the translate function
    } else { // Otherwise it is a short line
      line(0, -190, 0, -180);
    }
    longStroke = !longStroke; // If we drew a long line we will need to draw a short line after and the other way around
  }
}

And now, try to modify it to get the outer white stripes!

3 Likes

Hi jb4x, I wish if you put comments for each line to understand pleaase

There you go :slight_smile:

1 Like
void setup() { //Run once at the beginning
  size(500, 500); //Sets the size of the screen
  background(20); //Sets the background color to a dark gray
  stroke(200); //Sets the line/stroke color to a light gray
  strokeWeight(1); //Sets the thickness of the lines/strokes to 1 pixel
  noFill(); //Shapes aren't filled in.

  float angleStep = HALF_PI / 30; //The angle that the programs moves by each time (HALF_PI / 30 radian intervals)
  boolean longStroke = false; //Whether the line drawn is a long one.

  translate(width/2, height/2); // Sets (0, 0) to the middle of the screen
  for (float angle = 0; angle < TWO_PI; angle += angleStep) { //Goes through every angle
    rotate(angleStep); //Rotates the screen by that angle
    if (longStroke) { //If it is a long line
      line(0, -200, 0, -180); //Draw a long line at y: -200
    } else { //If it isn't a long line
      line(0, -190, 0, -180); //Draw a short line at y: -190
    }
    longStroke = !longStroke; //Sets "longStroke" to the opposite of what it is now, so the next one will be the opposite length
  }
}

Oh wait @jb4x just did it! :joy:
I guess you get 2 takes on it then…

3 Likes

Here the code of the animation can you please make comments for each line to understand

import org.firmata.*;
import cc.arduino.*;

//Thanks to Adrian Fernandez for the beta-version
//Modified and updated as per latest IDE by Aritro Mukherjee (April,2016)
//Check the detailed tutorial @ www.hackster.io/Aritro
// Sensor used while demonstration (MPU-6050,6DOF)

import processing.serial.*;
import cc.arduino.*;

int W=1400; //My Laptop's screen width 
int H=700;  //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; 


Serial port;
float Phi;    //Dimensional axis
float Theta;
float Psi;

void setup() 
{ 
  size(W, H); 
  rectMode(CENTER); 
  smooth(); 
  strokeCap(SQUARE);//Optional 
  
  println(Serial.list()); //Shows your connected serial ports
  port = new Serial(this, Serial.list()[0], 115200); 
  //Up there you should select port which arduino connected and same baud rate.
  port.bufferUntil('\n'); 
}
void draw() 
{ 
  background(0); 
  translate(W/4, H/2.1);  
  MakeAnglesDependentOnMPU6050(); 
  Horizon(); 
  rotate(-Bank); 
  PitchScale(); 
  Axis(); 
  rotate(Bank); 
  Borders(); 
  Plane(); 
  ShowAngles(); 
  Compass(); 
  ShowAzimuth(); 
}
void serialEvent(Serial port) //Reading the datas by Processing.
{
   String input = port.readStringUntil('\n');
  if(input != null){
   input = trim(input);
  String[] values = split(input, " ");
 if(values.length == 3){
  float phi = float(values[0]);
  float theta = float(values[1]); 
  float psi = float(values[2]); 
  print(phi);
  print(theta);
  println(psi);
  Phi = phi;
  Theta = theta;
  Psi = psi;
   }
  }
}
void MakeAnglesDependentOnMPU6050() 
{ 
  Bank =-Phi/5; 
  Pitch=Theta*10; 
  Azimuth=Psi;
}
void Horizon() 
{ 
  scale(ArtificialHoizonMagnificationFactor); 
  noStroke(); 
  fill(0, 180, 255); 
  rect(0, -100, 900, 1000); 
  fill(95, 55, 40); 
  rotate(-Bank); 
  rect(0, 400+Pitch, 900, 800); 
  rotate(Bank); 
  rotate(-PI-PI/6); 
  SpanAngle=120; 
  NumberOfScaleMajorDivisions=12; 
  NumberOfScaleMinorDivisions=24;  
  CircularScale(); 
  rotate(PI+PI/6); 
  rotate(-PI/6);  
  CircularScale(); 
  rotate(PI/6); 
}
void ShowAzimuth() 
{ 
  fill(50); 
  noStroke(); 
  rect(20, 470, 440, 50); 
  int Azimuth1=round(Azimuth); 
  textAlign(CORNER); 
  textSize(35); 
  fill(255); 
  text("Azimuth:  "+Azimuth1+" Deg", 80, 477, 500, 60); 
  textSize(40);
  fill(25,25,150);
  text("FLIGHT SIMULATOR", -350, 477, 500, 60); 
}
void Compass() 
{ 
  translate(2*W/3, 0); 
  scale(CompassMagnificationFactor); 
  noFill(); 
  stroke(100); 
  strokeWeight(80); 
  ellipse(0, 0, 750, 750); 
  strokeWeight(50); 
  stroke(50); 
  fill(0, 0, 40); 
  ellipse(0, 0, 610, 610); 
  for (int k=255;k>0;k=k-5) 
  { 
    noStroke(); 
    fill(0, 0, 255-k); 
    ellipse(0, 0, 2*k, 2*k); 
  } 
  strokeWeight(20); 
  NumberOfScaleMajorDivisions=18; 
  NumberOfScaleMinorDivisions=36;  
  SpanAngle=180; 
  CircularScale(); 
  rotate(PI); 
  SpanAngle=180; 
  CircularScale(); 
  rotate(-PI); 
  fill(255); 
  textSize(60); 
  textAlign(CENTER); 
  text("W", -375, 0, 100, 80); 
  text("E", 370, 0, 100, 80); 
  text("N", 0, -365, 100, 80); 
  text("S", 0, 375, 100, 80); 
  textSize(30); 
  text("COMPASS", 0, -130, 500, 80); 
  rotate(PI/4); 
  textSize(40); 
  text("NW", -370, 0, 100, 50); 
  text("SE", 365, 0, 100, 50); 
  text("NE", 0, -355, 100, 50); 
  text("SW", 0, 365, 100, 50); 
  rotate(-PI/4); 
  CompassPointer(); 
}
void CompassPointer() 
{ 
  rotate(PI+radians(Azimuth));  
  stroke(0); 
  strokeWeight(4); 
  fill(100, 255, 100); 
  triangle(-20, -210, 20, -210, 0, 270); 
  triangle(-15, 210, 15, 210, 0, 270); 
  ellipse(0, 0, 45, 45);   
  fill(0, 0, 50); 
  noStroke(); 
  ellipse(0, 0, 10, 10); 
  triangle(-20, -213, 20, -213, 0, -190); 
  triangle(-15, -215, 15, -215, 0, -200); 
  rotate(-PI-radians(Azimuth)); 
}
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=800;  
  textSize(GaugeWidth/30); 
  float StrokeWidth=1; 
  float an; 
  float DivxPhasorCloser; 
  float DivxPhasorDistal; 
  float DivyPhasorCloser; 
  float DivyPhasorDistal; 
  strokeWeight(2*StrokeWidth); 
  stroke(255);
  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(15); 
      stroke(0); 
      line(DivxPhasorCloser, DivyPhasorCloser, DivxPhasorDistal, DivyPhasorDistal); 
      strokeWeight(8); 
      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(3); 
  line(-115, 0, 115, 0); 
  line(0, 280, 0, -280); 
  fill(100, 255, 100); 
  stroke(0); 
  triangle(0, -285, -10, -255, 10, -255); 
  triangle(0, 285, -10, 255, 10, 255); 
}
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);  
  text("Pitch:  "+Pitch1+" Deg", -20, 411, 500, 60); 
  text("Bank:  "+Bank*100+" 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(3); 
  textSize(24); 
  textAlign(CENTER); 
  for (int i=-4;i<5;i++) 
  {  
    if ((i==0)==false) 
    { 
      line(110, 50*i, -110, 50*i); 
    }  
    text(""+i*10, 140, 50*i, 100, 30); 
    text(""+i*10, -140, 50*i, 100, 30); 
  } 
  textAlign(CORNER); 
  strokeWeight(2); 
  for (int i=-9;i<10;i++) 
  {  
    if ((i==0)==false) 
    {    
      line(25, 25*i, -25, 25*i); 
    } 
  } 
}

@zohrahamadene – I see that you posted the code several times, but as a new user posting code that contained a web link (to hackster.io/Aritro) the spam filter thought that you were a spammer. I have restored the last version of your source code post.

Hi Zora. how can I use your code for ADXL345?

Arduino Code:

 // Low-pass filter
  Phi = 0.94 * rollF + 0.06 * roll;
  Theta = 0.94 * pitchF + 0.06 * pitch;
  Psi = (Phi+Theta)/2;

            Serial.print(Phi);
            Serial.print("/");
            Serial.print(Theta);
            Serial.print("/");
            Serial.println(Psi);```