// Kine.java from CH 3 S&N Autonomous Mobile Robots // given starting position, goal is origin, control vector // navagate to goal. From any x0,y0 to x1,y1 OK, just compute dx,dy // rotate entire frame of reference for final theta other than 0.0 // plot with x1,y1 at 0,0 import java.*; import java.awt.*; import java.awt.event.*; public class Kine extends Frame { // chosen control parameters double kr = 3.0, ka = 8.0, kb = -3.0; // was -1.5; // chosen starting point double xi0 = 0.5, yi0 = 0.5; // from double xi1 = -0.5, yi1 = -0.5; // to in unit box double t = 0.0, dt = 0.01; double tstep = 0.01, tlast = 0.0; // try 100 step per sec double dx, dy; double alpha, beta, theta, dalpha, dbeta, dtheta; double rho, drho; double scale = 180.0; int cycle = 0; boolean done = false; Kine() { setTitle("Kine"); setSize(500,500); setBackground(Color.white); setForeground(Color.black); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setVisible(true); init(); new MyThread().start(); } class MyThread extends Thread // for movement computation { MyThread() { // everything in "run" } public void run() { while(true) { try { physicsComputation(); // System.out.println(id+" thread is running"); // debug sleep(50); // milliseconds delay } catch(InterruptedException e) { System.out.println("interruptedException"); } } } } void init() { System.out.println("Kine.java starting"); dx = xi1-xi0; // delta position to origin dy = yi1-yi0; rho = Math.sqrt(dx*dx+dy*dy); alpha = Math.PI/8.0; // angle robot X to goal beta = -Math.PI/4.0; // angle robot cg to goal theta = -(beta+alpha); // angle robot X to inertial } // end init int p(double x) // simple transformation on a point { double offset = 250.0; double scale = 1.0; return (int)(x*scale + offset); } int q(double y) // simple transformation on a point { double offset = 250.0; double scale = 1.0; return (int)(offset-y*scale); } double px(double x, double y) // rotation and translation { double offsetx = -dx*scale; double r, a; r = Math.sqrt(x*x+y*y); a = Math.atan2(y,x); return r*Math.cos(a+theta) + offsetx; } double py(double x, double y) // simple transformation on a point { double offsety = -dy*scale; double r, a; r = Math.sqrt(x*x+y*y); a = Math.atan2(y,x); return r*Math.sin(a+theta) + offsety; } void physicsComputation() { double tnow; // for drawing timing control if(done) return; if(rho < 0.001) // close enough { System.out.println("dx="+dx+", dy="+dy+", theta="+theta); done = true; } else if(rho < 0.005) {dt = 0.0005; tstep = 0.0;} else if(rho < 0.01) {dt = 0.001; tstep = 0.001;} else if(rho < 0.1) {dt = 0.01; tstep = 0.01;} // compute deltas from control system drho = -kr*rho*Math.cos(alpha); dalpha = kr*Math.sin(alpha) - ka*alpha - kb*beta; dbeta = -kr*Math.sin(alpha); dtheta = -(dbeta+dalpha); // robot has to move distance drho*dt // at angle theta+dtheta*dt dx = dx + drho*dt*Math.cos(theta+dtheta*dt); dy = dy + drho*dt*Math.sin(theta+dtheta*dt); rho = Math.sqrt(dx*dx+dy*dy); theta = theta+dtheta*dt; alpha = -(theta - Math.atan2(dy, dx)); beta = -(theta + alpha); t = t+dt; // simulation time repaint(); } // end physicsComputation public void paint(Graphics g) { double offsetx, offsety, sinth, costh; g.setColor(Color.red); // goal g.drawLine(p(-10.0), p( 0.0), p(10.0), p( 0.0)); g.drawLine(p( 0.0), p(-10.0), p( 0.0), p(10.0)); //glTranslatef(-dx*scale, -dy*scale, 0.0); //glRotatef(theta*180.0/Math.PI, 0.0, 0.0, 1.0); // use, p, px, py g.setColor(Color.black); // robot //glBegin(GL_LINE_LOOP); // box // glVertex2f( -5.0, -10.0); // glVertex2f(+30.0, -10.0); // glVertex2f(+30.0, +10.0); // glVertex2f( -5.0, +10.0); //glEnd(); g.drawLine(p(px( -5.0,-10.0)), q(py( -5.0,-10.0)), p(px(+30.0,-10.0)), q(py(+30.0,-10.0))); g.drawLine(p(px(+30.0,-10.0)), q(py(+30.0,-10.0)), p(px(+30.0,+10.0)), q(py(+30.0,+10.0))); g.drawLine(p(px(+30.0,+10.0)), q(py(+30.0,+10.0)), p(px( -5.0,+10.0)), q(py( -5.0,+10.0))); g.drawLine(p(px( -5.0,+10.0)), q(py( -5.0,+10.0)), p(px( -5.0,-10.0)), q(py( -5.0,-10.0))); //glBegin(GL_LINE_LOOP); // wheel // glVertex2f(-10.0, -10.0); // glVertex2f(+10.0, -10.0); // glVertex2f(+10.0, -14.0); // glVertex2f(-10.0, -14.0); //glEnd(); g.drawLine(p(px(-10.0,-10.0)), q(py(-10.0,-10.0)), p(px(+10.0,-10.0)), q(py(+10.0,-10.0))); g.drawLine(p(px(+10.0,-10.0)), q(py(+10.0,-10.0)), p(px(+10.0,-14.0)), q(py(+10.0,-14.0))); g.drawLine(p(px(+10.0,-14.0)), q(py(+10.0,-14.0)), p(px(-10.0,-14.0)), q(py(-10.0,-14.0))); g.drawLine(p(px(-10.0,-14.0)), q(py(-10.0,-14.0)), p(px(-10.0,-10.0)), q(py(-10.0,-10.0))); //glBegin(GL_LINE_LOOP); // wheel // glVertex2f(-10.0, +10.0); // glVertex2f(+10.0, +10.0); // glVertex2f(+10.0, +14.0); // glVertex2f(-10.0, +14.0); //glEnd(); g.drawLine(p(px(-10.0,+10.0)), q(py(-10.0,+10.0)), p(px(+10.0,+10.0)), q(py(+10.0,+10.0))); g.drawLine(p(px(+10.0,+10.0)), q(py(+10.0,+10.0)), p(px(+10.0,+14.0)), q(py(+10.0,+14.0))); g.drawLine(p(px(+10.0,+14.0)), q(py(+10.0,+14.0)), p(px(-10.0,+14.0)), q(py(-10.0,+14.0))); g.drawLine(p(px(-10.0,+14.0)), q(py(-10.0,+14.0)), p(px(-10.0,+10.0)), q(py(-10.0,+10.0))); g.setColor(Color.green); // cg //glBegin(GL_LINES); // glVertex2f(-10.0, 0.0); // glVertex2f(+10.0, 0.0); // glVertex2f(0.0, -10.0); // glVertex2f(0.0, +10.0); //glEnd(); g.setColor(Color.green); // goal g.drawLine(p(px(-10.0, 0.0)), q(py(-10.0, 0.0)), p(px( 10.0, 0.0)), q(py( 10.0, 0.0))); g.drawLine(p(px( 0.0,-10.0)), q(py( 0.0,-10.0)), p(px( 0.0, 10.0)), q(py( 0.0, 10.0))); } // end paint public static void main(String args[]) { new Kine(); } } // end main // end Kine.java