Android Open Source - smartcar Drawing Canvas






From Project

Back to project page smartcar.

License

The source code is released under:

GNU General Public License

If you think the Android project smartcar listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * This class handles the joystick appearance, its behaviour and the physics involved. Also generates the
 * string to be sent.//from   w  ww.j a v a  2s .  c om
 * @author Team Pegasus (dimi)
 */

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.Timer;
import javax.swing.JPanel;


@SuppressWarnings("serial")
public class DrawingCanvas extends JPanel implements MouseListener, MouseMotionListener, ActionListener{
  Graphics2D pointerCircle;
  Ellipse2D.Double pointer;
  int totalWidth, totalHeight, bigCircleDiameter,bigCircleRad, centerX,centerY;
  double pointerCenterX, pointerCenterY, pointerX, pointerY, sphereX, sphereY,prevPointerX, prevPointerY;
  int pDiameter = 40;
  int outerCircleX = 8;
  int outerCircleY = 8;
  boolean atCenter = true;
  boolean outOfBounds = false;
  Timer goBack = new Timer(1,this);
  Timer getCoordinates = new Timer (150,this);
  ClientOutput out;
  public DrawingCanvas(Dimension dimension, ClientOutput userOutput) {
    totalWidth = (int) dimension.getWidth();
    totalHeight = (int) dimension.getHeight();
    sphereX = (totalHeight-outerCircleX-6)/2;
    sphereY = sphereX;
    pointerCenterX = sphereX- (pDiameter/2)+10; // 10 is probably the stroke
    pointerCenterY = sphereY - (pDiameter/2)+10;
    prevPointerX = pointerCenterX;
    prevPointerY = pointerCenterY;
    bigCircleDiameter = totalHeight-10;
    bigCircleRad = bigCircleDiameter/2;
    centerX = (totalHeight-outerCircleX+14)/2;
    centerY = (totalHeight-outerCircleX+12)/2;
    addMouseListener(this);
    addMouseMotionListener(this);
    out = userOutput;
    revalidate(); //not sure if needed
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);    
    /* the outer bigger circle */
    bigOuterCircle(g);
    /* the line in the middle of the outer bigger circle */
    centralHorizontalLine(g);
    /* the sphere in the center */ 
    centralSphere(g);
    /* our pointer */
    joyStickPointer(g);
  }

  private void joyStickPointer(Graphics g) {
    /* our pointer */
    pointerCircle = (Graphics2D)g;
    if (atCenter){
      pointer = new Ellipse2D.Double(pointerCenterX, pointerCenterY,pDiameter,pDiameter);
      pointerX = pointerCenterX;
      pointerY = pointerCenterY;
      prevPointerX = pointerCenterX;
      prevPointerY = pointerCenterY;
    }else{
      pointer = new Ellipse2D.Double(pointerX, pointerY,pDiameter,pDiameter);
    }
    pointerCircle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    pointerCircle.setStroke(new BasicStroke(10));
    pointerCircle.setColor(new Color(255,0,0));
    pointerCircle.draw(pointer);    
  }

  private void centralSphere(Graphics g) {
    /* the sphere in the center */ 
    Graphics2D g2d = (Graphics2D)g;
    Ellipse2D.Double center = new Ellipse2D.Double(sphereX,sphereY,20,20);
    g2d.fill(center);    
  }

  private void centralHorizontalLine(Graphics g) {
    /* the line in the middle of the outer bigger circle */
    Graphics2D centralLine = (Graphics2D)g;
    centralLine.setStroke(new BasicStroke(4));
    centralLine.drawLine(outerCircleX,(totalWidth+outerCircleY-4)/2, totalWidth-1,(totalWidth+outerCircleY-4)/2);    
  }

  private void bigOuterCircle(Graphics g){
    /* the outer bigger circle */
    Graphics2D g2d = (Graphics2D)g;
    Ellipse2D.Double bigCircle = new Ellipse2D.Double(outerCircleX,outerCircleY,bigCircleDiameter,bigCircleDiameter);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setColor(new Color(0, 0, 0));
    g2d.setStroke(new BasicStroke(8));
    g2d.draw(bigCircle);
  }

  private boolean inBounds(int x, int y){
    /* calculating whether that point is within the circle */
    double axisX = Math.pow((centerX - x), 2);
    double axisY = Math.pow((centerY - y), 2);
    double distance = Math.sqrt((axisX + axisY));
    return (int) distance < bigCircleRad;
  }

  @Override
  public void mouseClicked(MouseEvent e) {
    // TODO Auto-generated method stub

  }

  @Override
  public void mousePressed(MouseEvent e) {
    if (inBounds(e.getX(), e.getY())) {
      if (goBack.isRunning()) {
        goBack.stop();
      }

      //update the pointer position
      pointerX = e.getX() - (pDiameter / 2);
      pointerY = e.getY() - (pDiameter / 2);
      atCenter = false;
      repaint();
      if (!getCoordinates.isRunning()) getCoordinates.start(); //start sending
    }


  }

  @Override
  public void mouseReleased(MouseEvent e) {
    goBack.start();
    if (getCoordinates.isRunning()){
      getCoordinates.stop();
      //  out.send2pi("#0$0"); //stop the motor and the wheel when releasing mouse
      out.send2pi("!0:0"); // tank mode
    }

  }

  @Override
  public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub

  }

  @Override
  public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub

  }

  @Override
  public void mouseDragged(MouseEvent e) {
    if (inBounds(e.getX(), e.getY())) {
      if (!goBack.isRunning()) {
        /* move the pointer along with mouse */
        pointerX = e.getX() - (pDiameter / 2);
        pointerY = e.getY() - (pDiameter / 2);
        atCenter = false;
        repaint();
        if (!getCoordinates.isRunning()) getCoordinates.start();
      }
    }    
  }

  @Override
  public void mouseMoved(MouseEvent e) {
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    if (e.getSource() == goBack){
      if (!atCenter){
        /* move back to the center */
        if (pointerCenterX > pointerX) pointerX++;
        if (pointerCenterX < pointerX) pointerX--;
        if (pointerCenterY >pointerY) pointerY++;
        if (pointerCenterY < pointerY) pointerY--;
        if (pointerCenterY == pointerY && pointerCenterX == pointerX){
          atCenter = true;
          goBack.stop();
        }
        repaint();
      }
    }

    if (e.getSource() == getCoordinates){
      if (prevPointerX != pointerX || prevPointerY != pointerY){
        prevPointerX = pointerX;
        prevPointerY = pointerY;
        int scale = 8;
        double cursorX = pointerX + (pDiameter/2);
        double cursorY = pointerY + (pDiameter/2);
        double distanceX = cursorX - centerY;
        double scaledBy4distanceX = (distanceX * scale) / (bigCircleRad);
        scaledBy4distanceX = Math.round(scaledBy4distanceX);
        distanceX = (distanceX * 100) / (bigCircleRad);

        double distanceY = centerY - cursorY;
        double scaledBy4distanceY = (distanceY * scale) / (bigCircleRad);
        scaledBy4distanceY = Math.round(scaledBy4distanceY);
        distanceY = (distanceY * 100) / (bigCircleRad);
        /* passing the signed value of distance so to get optimum results */
        int angle = getAngle(distanceX,Math.abs(distanceY)); //not accurate when distance scaled by 4!!!
        int speed = getSpeed(cursorX,cursorY); //speed scaled to [-4,4]
        //    String dataOut = "!" + angle + ":" + speed ;
        int[] motors = getMotors(angle, speed);
        String dataOut = "!" + motors[0] + ":" + motors[1];
        out.send2pi(dataOut);
      }
    }
  }

  private int[] getMotors(int angle, int speed){
    double scale = 8.0;
    float rel = (float) ((angle * scale) / 90.0) ;
    rel = Math.round(rel);
    rel = (int) scale - Math.abs(rel);
    float sideSpeed = Math.round((float) ((rel/scale) * speed));
    int[] motorsOut = new int[2];
    if (angle>0){
      motorsOut[0] = speed;  
      motorsOut[1] = (int) sideSpeed;
    }else{
      motorsOut[0] = (int) sideSpeed;
      motorsOut[1] = speed;
    }
    if (motorsOut[0] == speed && motorsOut[1] == 0) motorsOut[1] = -speed;
    if (motorsOut[1] == speed && motorsOut[0] == 0) motorsOut[0] = -speed;

    System.out.println("left speed: " + motorsOut[0] + " right speed: " + motorsOut[1]);

    return motorsOut;
  }

  private int getSpeed(double x, double y){
    /* get speed as distance from center and direction
     * of speed from whether it's over or lower than the line */
    int scale = 8;
    double axisX = Math.pow((centerX - x), 2);
    double axisY = Math.pow((centerY - y), 2);
    int prefix = (int) ((centerY-y) / Math.abs(centerY-y));
    double distance = Math.sqrt((axisX + axisY));
    return  (int) (prefix*(distance*scale)/(bigCircleRad-20)); //scale of 4
  }
  private int getAngle(double x, double y){
    /* get angle as the corner of the triangle between the cursor position
     * the diameter and the center */
    double tan = Math.atan2(x, y); // x first because we want to count vertically the degrees
    double degrees = Math.round(Math.toDegrees(tan));
    return (int) degrees;
  }
}




Java Source Code List

.ClientOutput.java
.DrawingCanvas.java
.JoystickGUI.java
.JoystickMain.java
piSockets.SerialOutput.java
piSockets.SocketReceive.java
piSockets.SocketsMain.java
se.chalmers.balmung.smartcar.JoystickView.java
se.chalmers.balmung.smartcar.MainActivity.java
se.chalmers.balmung.smartcar.SettingsActivity.java