Below is a look at the robot, scaled by a factor of two, by modifying the code slightly.
Robot.java
import javafx.geometry.Pos; import javafx.scene.Group; import javafx.scene.layout.Pane; import javafx.scene.paint.*; import javafx.scene.shape.*; import javafx.collections.*; public class Robot { double px, py, theta; double vl, vr; double vx, vy; double mass; double radius = 15.0;; Color color; Group grp = new Group(); Robot() { color = Color.WHITE; setPose(50,50,0); setVelocity(7,-7); } Robot(int px, int py, int vr, int vl, Color color) { setPose(px,py,0); setVelocity(vr,vl); this.color = color; } public String toString() { String str = "("+px+", "+py+") " + color; return str; } public void move() { px += vl; py += vr; } public void setPose(double x, double y, double angle) { px = x; py = y; theta=angle; grp.setTranslateX(px); grp.setTranslateY(py); grp.setRotate(theta); } public void setVelocity(double vr, double vl) { this.vr = vr; this.vl = vl; } public String showVelocity() { double ell = 12.0; if (vr==vl) { if (Math.abs(vr)>0) return String.format("linear motion, v = %.1f",vr); else return "Robot stopped"; } double RADIUS = Math.abs(ell/2*(vr+vl)/(vr-vl)); double PERIOD = 2*ell/(vr-vl); String dir = (PERIOD>0? "counterclockwise": "clockwise"); PERIOD = Math.abs(PERIOD); if (RADIUS==0.0) return String.format("vr %.1f vl %.1f spin, period = %.1f PI %s",vr,vl,PERIOD,dir); else return String.format("vr %.1f vl %.1f radius %.1f, period %.1f PI %s",vr,vl,RADIUS,PERIOD,dir); } public void updateVelocity() { double v = 0.5*(vr+vl); double rtheta = Math.toRadians(theta); vx = v*Math.cos(rtheta); vy = v*Math.sin(rtheta); } public void move(double delta) { double radg = Math.atan(1.0)/45.0; double wp = 12.0*radg; double dv, dtheta, rtheta; dtheta = (vl-vr)*delta/wp; dv = 0.5*(vr+vl)*delta; rtheta = radg*theta; px += dv*Math.cos(rtheta); py += dv*Math.sin(rtheta); theta += dtheta; grp.setTranslateX(px); grp.setTranslateY(py); grp.setRotate(theta); } public void draw(Pane parent) { //double resc = 3.0; //grp.setScaleX(resc); //grp.setScaleY(resc); Circle cir = new Circle(0.0,0.0,radius); cir.setFill(Color.TRANSPARENT); //cir.setStroke(Color.BLACK); Path p = new Path(); ObservableList<PathElement> pl = p.getElements(); pl.add(new MoveTo(-8,10)); pl.add(new LineTo(12,10)); pl.add(new LineTo(16,0)); pl.add(new LineTo(12,-10)); pl.add(new LineTo(-8,-10)); pl.add(new ClosePath()); p.setFill(color); Rectangle wheel1 = new Rectangle(-4,-8,8,4); wheel1.setFill(Color.BLACK); Rectangle wheel2 = new Rectangle(-4,4,8,4); wheel2.setFill(Color.BLACK); grp.getChildren().addAll(cir,p,wheel1,wheel2); parent.getChildren().add(grp); } // returns time before striking window public double intersect_window(double width, double height) { double t; double tx = 1000; if (vx<0) { t = (px-radius)/(-vx); if (t<tx) tx = t; } else if (vx>0) { t = (width - px - radius)/vx; if (t<tx) tx = t; } if (vy<0) { t = (py-radius)/(-vy); if (t<tx) tx = t; } else if (vy>0) { t = (height - py - radius)/vy; if (t<tx) tx = t; } return tx; } }
Maintained by John Loomis, updated Tue Feb 20 17:24:15 2018