MovePilot arc(): unexpected behaviour

This is where you talk about the EV3 software itself, installation issues, and programming talk.

Moderators: roger, gloomyandy, skoehler

User avatar
jippiee
New User
Posts: 11
Joined: Tue Dec 26, 2017 1:07 am

MovePilot arc(): unexpected behaviour

Postby jippiee » Wed Feb 21, 2018 8:42 pm

The arc(radius, angle) method in MovePilot works fine when I specify the radius equal to the offset of the chassis' wheels.

But when I use a larger radius things get a bit strange.

Code: Select all

package wro.testing.chassis;

import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.MotorPort;
import lejos.robotics.RegulatedMotor;
import lejos.robotics.chassis.Chassis;
import lejos.robotics.chassis.Wheel;
import lejos.robotics.chassis.WheeledChassis;
import lejos.robotics.navigation.MovePilot;

public class Arc {

   private MovePilot pilot;
   
   public Arc() {
      RegulatedMotor leftMotor = new EV3LargeRegulatedMotor(MotorPort.B);
      RegulatedMotor rightMotor = new EV3LargeRegulatedMotor(MotorPort.C);
      Wheel leftWheel = WheeledChassis.modelWheel(leftMotor, 6.225).offset(7.521).invert(true);
      Wheel rightWheel = WheeledChassis.modelWheel(rightMotor, 6.225).offset(-7.521).invert(true);
      Chassis chassis = new WheeledChassis( new Wheel[] {leftWheel, rightWheel}, WheeledChassis.TYPE_DIFFERENTIAL);
      
      pilot = new MovePilot(chassis);
   }

   public static void main(String[] args) {
      Arc a = new Arc();
      a.pilot.arc(50, 90);
   }

}

In this example I expected my robot to drive a quarter on the circumference of a circle with radius 50cm. So compared to its start point it should have gone 50cm forwards and 50cm to the left and the heading should be rotated by 90 degrees. Moreover I thought, that to maintain a nice circular path, the motors would rotate at different speeds and come to a halt simultaneously.

Instead this is what happened: https://youtu.be/3F379H_eHlo

As you can tell both motors rotate at the same speed and the right one simply turns a bit further. Am I correct to assume this is not arc's intended behavior? And if it is, is there another way to achieve an arc? (possibly also without stopping at the beginning and end)

User avatar
gloomyandy
leJOS Team Member
Posts: 6018
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Re: MovePilot arc(): unexpected behaviour

Postby gloomyandy » Wed Feb 21, 2018 9:18 pm

For continuous movement, use the Chassis methods directly. Using the setVelocity methos will let you specify a move in terms of both linear and angular velocity. If you provide a non zero value for both you will get a smooth arc movement. Setting the angular velocity to zero drives straight and setting the linear velocity to zero turns on the spot.
leJOS news https://lejosnews.wordpress.com/

User avatar
jippiee
New User
Posts: 11
Joined: Tue Dec 26, 2017 1:07 am

Re: MovePilot arc(): unexpected behaviour

Postby jippiee » Wed Feb 21, 2018 10:10 pm

Yes, I'm familiar with the chassis.setVelocity method. I even wrote an Extension to the WheeledChassis class to measure the distance and rotation traveled.

Code: Select all

package wro.setup;

import lejos.robotics.chassis.Wheel;
import lejos.robotics.chassis.WheeledChassis;
import lejos.utility.Matrix;

/**
 * This class is meant to be used instead of a {@link WheeledChassis}. As the name
 * implies, this class extends the Chassis by providing methods to measure the
 * distance and degrees traveled.
 * @author jippiee
 *
 */
public class ChassisExtension extends WheeledChassis {

   protected Matrix tachoAtMeasureStart;
   
   /**
    * Constructor. <br>
    * See {@link WheeledChassis} for more information.
    */
   public ChassisExtension(Wheel[] wheels, int dim) {
      super(wheels, dim);
      resetMeasurement();
   }

   /**
    * Starts a new Measurement. This method simply stores the current Tacho
    * Counts of the chassis' motors, so we can calculate the difference.
    */
   public void resetMeasurement() {
      tachoAtMeasureStart = getAttribute(TACHOCOUNT);
   }
   
   /**
    * Measures the distance from the chassis' current Position to the last time
    * <code>resetMeasurement()</code> has been called, in the units of the wheel
    * diameter.
    * @return the distance from the reset point
    */
   public double measureDistance() {
      Matrix currentTacho = getAttribute(TACHOCOUNT);
      Matrix delta = currentTacho.minus(tachoAtMeasureStart);      
      delta = reverse.times(delta);
      double distance = Math.sqrt(delta.get(0, 0) * delta.get(0, 0) + delta.get(1, 0) * delta.get(1, 0));      
      return distance;
   }
   
   /**
    * Measures the amount of degrees the chassis has turned in comparison to the
    * last time <code>resetMeasurement()</code> has been called.
    * @return the amount of degrees the chassis has turned
    */
   public double measureRotation() {
      Matrix currentTacho = getAttribute(TACHOCOUNT);
      Matrix delta = currentTacho.minus(tachoAtMeasureStart);      
      delta = reverse.times(delta);
      double rotation = delta.get(2, 0);      
      return rotation;
   }
   
   
   /**
    * Moves the chassis in an arc without stoping at the begining or end
    * @param radius
    * the radius of the arc.
    * A positive radius means the center of the arc is on the left side of the robot,
    * the center of a negative arc is on the right side of the robot. Infinite radius is not allowed.
    * A radius of 0 makes the robot spin in place.
    * @param angle
    * The number of degrees of the arc. A positive number of degrees makes the robot go forward,
    * a negative number makes it go backward.
    */
   public void arcNoStop(double radius, double angle) {      
      double linSpeed = Math.signum(angle)*Math.abs(getLinearVelocity());
      double angSpeed = (linSpeed*180)/(Math.PI*radius);
      double angleAbs = Math.abs(angle);
      resetMeasurement();
      do {
         setVelocity(linSpeed, angSpeed);
      } while (Math.abs(measureRotation()) < angleAbs);
   }
   
   
   public void leftForward() {
      arcNoStop(7.521, 90);
   }
   
   public void leftBack() {
      arcNoStop(7.521, -90);
   }
   
   public void rightForward() {
      arcNoStop(-7.521, 90);
   }
   
   public void rightBack() {
      arcNoStop(-7.521, -90);
   }
   
   public void travelNoStop(double distance) {
      double linSpeed = Math.signum(distance)*Math.abs(getLinearVelocity());
      double distanceAbs = Math.abs(distance);
      resetMeasurement();
      do {
         setVelocity(linSpeed, 0);
      } while (Math.abs(measureDistance()) < distanceAbs);
   }
   
   
   
   @Deprecated
   public Matrix currentTacho() {
      return getAttribute(TACHOCOUNT);
   }
   
   @Deprecated
   public Matrix delta() {
      return currentTacho().minus(tachoAtMeasureStart);
   }
   
   @Deprecated
   public Matrix reverseTimesDelta() {
      Matrix currentTacho = getAttribute(TACHOCOUNT);
      Matrix delta = currentTacho.minus(tachoAtMeasureStart);
      return reverse.times(delta);
   }
}

The only problem with this is that isn't as accurate as I had at first hoped. Maybe I just have to specify a smaller angle...

User avatar
gloomyandy
leJOS Team Member
Posts: 6018
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Re: MovePilot arc(): unexpected behaviour

Postby gloomyandy » Thu Feb 22, 2018 8:51 am

If you want to track the position of a robot using the Chassis class why not just use the PoseProvider that is built into the class. It works very well. See:
https://lejosnews.wordpress.com/2016/02 ... ile-robot/
which compares the built in tracking to that provided by a system that adds an IMU to augment the accuracy during turns. Although it can be improved the basic tracking is still very good and typically much better than anything that relies on calculating the position based upon the angles that the robot has supposed to have turned.
leJOS news https://lejosnews.wordpress.com/

User avatar
jippiee
New User
Posts: 11
Joined: Tue Dec 26, 2017 1:07 am

Re: MovePilot arc(): unexpected behaviour

Postby jippiee » Fri Feb 23, 2018 3:23 pm

Ok, I think I've got it working now.

Code: Select all

package wro.testing.chassis;

import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.MotorPort;
import lejos.robotics.RegulatedMotor;
import lejos.robotics.chassis.Chassis;
import lejos.robotics.chassis.Wheel;
import lejos.robotics.chassis.WheeledChassis;
import lejos.robotics.geometry.Point;
import lejos.robotics.localization.PoseProvider;
import lejos.robotics.navigation.Pose;

public class Arc {

   //private MovePilot pilot;
   private Chassis chassis;
   private PoseProvider pose;
   
   public Arc() {
      RegulatedMotor leftMotor = new EV3LargeRegulatedMotor(MotorPort.B);
      RegulatedMotor rightMotor = new EV3LargeRegulatedMotor(MotorPort.C);
      Wheel leftWheel = WheeledChassis.modelWheel(leftMotor, 6.225).offset(7.521).invert(true);
      Wheel rightWheel = WheeledChassis.modelWheel(rightMotor, 6.225).offset(-7.521).invert(true);
      chassis = new WheeledChassis( new Wheel[] {leftWheel, rightWheel}, WheeledChassis.TYPE_DIFFERENTIAL);
      
      pose = chassis.getPoseProvider();      
      //pilot = new MovePilot(chassis);
   }
   
   public void turn() {
      Pose zeropose = pose.getPose();
      zeropose.setHeading(0);
      pose.setPose(zeropose);
      
      chassis.setVelocity(10, 20);
      while (pose.getPose().getHeading() < 90) {
         Thread.yield();
      }
      //chassis.stop();
   }
   
   public void drive() {
      Point startpoint = pose.getPose().getLocation();
      
      chassis.setVelocity(10, 0);
      while (pose.getPose().distanceTo(startpoint) < 20) {
         Thread.yield();
      }
      //chassis.stop();
   }
   
   public static void main(String[] args) {
      Arc a = new Arc();
      for (int i=0; i<8; i++) {
         a.drive();
         a.turn();
      }
      //a.pilot.arc(50, 90);
   }

}

Is it correct to use Thread.yield() in the waiting loop?

User avatar
gloomyandy
leJOS Team Member
Posts: 6018
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Re: MovePilot arc(): unexpected behaviour

Postby gloomyandy » Fri Feb 23, 2018 4:22 pm

A short sleep would probably be better.
leJOS news https://lejosnews.wordpress.com/


Return to “EV3 Software”

Who is online

Users browsing this forum: Bing [Bot] and 1 guest