package ctbot.utils; import nanovm.ctbot.drivers.Motor; import nanovm.lang.Math; public class Navigator { public static NaviGoal nextGoal; private static float lastSpeed; final static float SPEEDUP = 1.0f; // 1(cm/s)/cm final static float MAX_SPEED = 0.20f; // 20 cm/s final static float MAX_TURN_SPEED = 0.04f; // 4 cm/s final static float MAX_SPEED_INC = 0.005f; // 0.5 (cm/s)/tick final static float MIN_SPEED = 0.01f; // 1 (cm/s) final static float RAD_FAR_DELTA = 0.01f; // 0.01 rad public static int status; public final static int STATUS_IDLE = 0; // Navigation is idle public final static int STATUS_RUNNING = 0; // Navigation is doing the job public final static int STATUS_STUCKED = 0; // Navigation has problems, replanning needed! public static NaviGoal popGoal() { if (nextGoal==null){ return null; } else { NaviGoal g1 = null; NaviGoal g2 = nextGoal; while(g2.nextGoal!=null){ g1 = g2; g2 = g2.nextGoal; } if (g1==null) nextGoal = null; else g1.nextGoal = null; return g2; } } public static void appendGoal(NaviGoal goal) { if (nextGoal==null){ nextGoal = goal; } else { NaviGoal g = nextGoal; while(g.nextGoal!=null) g = g.nextGoal; g.nextGoal = goal; } } public static void halt(){ Motor.setLeftSpeed(0); Motor.setRightSpeed(0); Motor.setLeft(0); Motor.setRight(0); lastSpeed=0.0f; } public static void stop(){ halt(); Motor.stop(); } static float checkTurnSpeed(float speed, float dori){ float distSpeed = Math.max(Math.abs(dori)*0.08f, MIN_SPEED); if (speed>MAX_TURN_SPEED) speed=MAX_TURN_SPEED; if (speed<-MAX_TURN_SPEED) speed=-MAX_TURN_SPEED; if (speed>0) speed = Math.min(Math.min(distSpeed, speed), lastSpeed+MAX_SPEED_INC); else speed = Math.max(Math.max(-distSpeed, speed), lastSpeed-MAX_SPEED_INC); lastSpeed=speed; return speed; } static float checkSpeed(float speed, float dist){ float distSpeed = Math.max(dist*SPEEDUP, MIN_SPEED); if (speed>MAX_SPEED) speed=MAX_SPEED; if (speed<-0.5f*MAX_SPEED) speed=-0.5f*MAX_SPEED; if (speed>0) { float space = Math.min(FreeDist.left, FreeDist.right); if (space<0.3f) { speed= nanovm.lang.Math.min(speed, MAX_SPEED * 0.25f); } else if (space<0.5f){ float spacespeed = MAX_SPEED*0.25f + (space-0.3f)*5.0f*MAX_SPEED*0.75f; speed= Math.min(speed, spacespeed); } speed = Math.min(Math.min(distSpeed, speed), lastSpeed+MAX_SPEED_INC); } else speed = Math.max(Math.max(-distSpeed, speed), lastSpeed-MAX_SPEED_INC); lastSpeed=speed; return speed; } static void goStraight(float speed){ Motor.setLeftSpeed((int) (speed / Odometry.M_PER_TICK)); Motor.setRightSpeed((int)(speed/Odometry.M_PER_TICK)); } static void goCircle(float radius, float speed){ if (Math.abs(radius)<0.5f*Odometry.M_WHEEL_DISTANCE) { speed /= 0.5f*Odometry.M_WHEEL_DISTANCE; if (radius<0) speed*=-1.0f; } else { speed /= radius; } float speedL = speed * (radius - 0.5f*Odometry.M_WHEEL_DISTANCE); float speedR = speed * (radius + 0.5f*Odometry.M_WHEEL_DISTANCE); Motor.setLeftSpeed((int)(speedL/Odometry.M_PER_TICK)); Motor.setRightSpeed((int)(speedR/Odometry.M_PER_TICK)); } static void goRotate(float speed){ Motor.setLeftSpeed((int)(speed/Odometry.M_PER_TICK)); Motor.setRightSpeed((int)(-speed/Odometry.M_PER_TICK)); } /* private static boolean doGoal(NaviGoal goal){ if (goal==null) return false; if (goal.subGoal!=null){ if (!doGoal(goal.subGoal)){ NaviGoal oldSubGoal = goal.subGoal; NaviGoal newSubGoal = oldSubGoal.nextGoal; goal.subGoal = newSubGoal; if (newSubGoal!=null) { while(true) Leds.set(Leds.BLUE); } } return true; } return goal.work(); } */ public static boolean work(){ FreeDist.update(); // update Sensors if (nextGoal!=null){ if (status==STATUS_IDLE) status=STATUS_RUNNING; if (!nextGoal.doWork()){ nextGoal = nextGoal.nextGoal; } } if (nextGoal==null){ status = STATUS_IDLE; stop(); return false; } return true; } }