Announcement

Collapse
No announcement yet.

Setting Motor Speed with Joystick

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Setting Motor Speed with Joystick

    We are trying to get our programming set where the joystick movement will correspond to how fast the motor is turning. We have tried the range clip and scale input from last year, but it is not working. Is there anyone who could help?

  • #2
    Please elaborate what is "not working"? Also, have you tried the sample code FIRST provided this year?

    Comment


    • #3
      Because the joysticks return from -1-1, and the motors take a power of -1,-1, you can set the power directly to the joystick.

      Here's a snippet to get you started:

      Code:
      leftDriveMotor.setPower(-gamepad1.left_stick_y);
      rightDriveMotor.setPower(gamepad1.right_stick_y);

      Comment


      • #4
        Originally posted by 4634 Programmer View Post
        Because the joysticks return from -1-1, and the motors take a power of -1,-1, you can set the power directly to the joystick.

        Here's a snippet to get you started:

        Code:
        leftDriveMotor.setPower(-gamepad1.left_stick_y);
        rightDriveMotor.setPower(gamepad1.right_stick_y);
        Oh, and you're going to want to have that in your main loop

        Comment


        • #5
          We found that made the robot twitchy around the zero point - hard to center on debris, for example.

          One option is to make your drive command the cube of the stick position along the lines of:
          output_x = Math.pow(stick_x,3.0);

          This gives full range for the motor but slows the stick response way down in that range where you need precision. Makes it much easier for a stressed out driver to line up on things.
          Mentor, teams 8578 & 11959

          Comment


          • #6
            There is a setDeadzone(); code but I am not sure how to use it.

            Comment


            • #7
              Originally posted by KernelPanic View Post
              We found that made the robot twitchy around the zero point - hard to center on debris, for example.

              One option is to make your drive command the cube of the stick position along the lines of:
              output_x = Math.pow(stick_x,3.0);

              This gives full range for the motor but slows the stick response way down in that range where you need precision. Makes it much easier for a stressed out driver to line up on things.
              The scaling equation we used last year was "(tanh(x)^3)/tanh(1))" (I am reading last year's code as I write this so a might have forgotten something).

              In general most teams who use scaling, usually scale to something like the following:
              (x/1.07)(.62x^2 + .45)

              The tanh function is in the Math class, whereas the x^2 is simplest to write x * x (Java doesn't offer an exponent operator; ^ is the bitwise XOR operator)

              Comment


              • #8
                (tanh(x)^3)/tanh(1)) would never let you go full speed but that may have been the intention.

                https://www.wolframalpha.com/input/?...%5E3)%2Ftanh(1)

                In input of 1 results in an output of 0.58.

                x^3 is nice because it works for negative values, provides a similar curve for smaller values, but still outputs 1.0 for an input of 1.0.

                Comment


                • #9
                  Originally posted by 4634 Programmer View Post
                  Because the joysticks return from -1-1, and the motors take a power of -1,-1, you can set the power directly to the joystick.

                  Here's a snippet to get you started:

                  Code:
                  leftDriveMotor.setPower(-gamepad1.left_stick_y);
                  rightDriveMotor.setPower(gamepad1.right_stick_y);
                  Hi. You code snippet worries me a bit.

                  It looks like you are negating the left stick, but not the right stick.
                  I'm guessing you did this to get both motors running forward .

                  This will work, but it's a really bad way to do it. It means that every time you do a motor calculation you will need to remember which is reversed etc.
                  This doesn't matter too much in teleop, but it's a pint in Auto.

                  The propper way to do this is to ENSURE that both motors move forward when you apply a forward power values.
                  This is done by setting one motor direction to "reverse", as in the samples...

                  leftMotor.setDirection(DcMotor.Direction.FORWARD);
                  rightMotor.setDirection(DcMotor.Direction.REVERSE) ;

                  Now when you give a positive power, each motor will go forward.

                  Then, because dumb joysticks give a negative value when you puts them forward, you negate BOTH joysticks

                  leftDriveMotor.setPower(-gamepad1.left_stick_y);
                  rightDriveMotor.setPower(-gamepad1.right_stick_y);

                  When you get to do autonomous you can now RELY on the fact that positive is forward on both motors.

                  Note: I harp on this all the time because it's one of those simple things that can waste a LOT of time getting started with autonomous.
                  Use exactly the same motor setup for both Auto and Teleop.

                  Comment


                  • #10
                    Originally posted by mlwilliams View Post
                    (tanh(x)^3)/tanh(1)) would never let you go full speed but that may have been the intention.

                    https://www.wolframalpha.com/input/?...%5E3)%2Ftanh(1)

                    In input of 1 results in an output of 0.58.

                    x^3 is nice because it works for negative values, provides a similar curve for smaller values, but still outputs 1.0 for an input of 1.0.
                    mlwilliam, you are correct in that was the one of the intentions of the scaling function; I forgot to mention that the drivers had a way to willfully disable the scaling when they wanted speed versus control.

                    Anyway, if you want a tanh scaling function that scales -1 to -1 and 1 to 1, you can use (tanh(x)/tanh(1))^3.

                    Comment


                    • #11
                      I'm sure that works well ... but am curious, if we're going to the trouble of cubing a number, is there an advantage to adding a trig function and a division as well (as opposed to simply cubing the input value)? Not saying there isn't, but the benefit is not obvious to me.
                      Mentor, teams 8578 & 11959

                      Comment


                      • #12
                        Originally posted by KernelPanic View Post
                        I'm sure that works well ... but am curious, if we're going to the trouble of cubing a number, is there an advantage to adding a trig function and a division as well (as opposed to simply cubing the input value)? Not saying there isn't, but the benefit is not obvious to me.
                        For many years, FTC has just been squaring the joystick value to get a non-linear curve. And it's a lot les costly just to multiply the value by itself, rather than using trig or transentental functions to do it.
                        Remember guys... it's just a joystick that gets slammed left and right most of the time

                        I will add that in most cases, the reason that robots are twitchy when trying to be steered slightly is that the motor's response to small power levels is quite unpredictable. When using open loop control, it's hard to get a motor to move slowly if there is any friction involved.

                        If you want to get smooth/slight turning (for picking up particles, or aligning with goals) you really need encoders on the wheels, and do all your driving in RUN_USING_ENCODER mode.
                        This will let you actually see the benefit of the fancy joystick code.
                        In this mode you can actually hope to get 5%, 10%, 15% speeds. Without it, you will be lucky to see anything under 30% while trying to do a spin turn.

                        If you aren't using encoders to drive, then most of your joystick math is wasted.

                        Phil.

                        Comment


                        • #13
                          The code below is from the K9TankDrive example included in the opmodes folder last year, and it looks similar to code from RobotC days. Curve fitting suggests that this is a table estimating an exponential function rather than a power function. One thing nice about this is you can easily modify it to your needs.

                          That said a few years ago one idea that our programmers tried that was a success with the drivers was setting the joysticks to have only two speeds, most of the travel of the stick was one speed, slow for precise control. When the stick was close to the end of travel, the robot went at max speed.


                          Code:
                          /*
                          	 * This method scales the joystick input so for low joystick values, the 
                          	 * scaled value is less than linear.  This is to make it easier to drive
                          	 * the robot more precisely at slower speeds.
                          	 */
                          	double scaleInput(double dVal)  {
                          		double[] scaleArray = { 0.0, 0.05, 0.09, 0.10, 0.12, 0.15, 0.18, 0.24,
                          				0.30, 0.36, 0.43, 0.50, 0.60, 0.72, 0.85, 1.00, 1.00 };
                          		
                          		// get the corresponding index for the scaleInput array.
                          		int index = (int) (dVal * 16.0);
                          		
                          		// index should be positive.
                          		if (index < 0) {
                          			index = -index;
                          		}
                          
                          		// index cannot exceed size of array minus 1.
                          		if (index > 16) {
                          			index = 16;
                          		}
                          
                          		// get value from the array.
                          		double dScale = 0.0;
                          		if (dVal < 0) {
                          			dScale = -scaleArray[index];
                          		} else {
                          			dScale = scaleArray[index];
                          		}
                          
                          		// return scaled value.
                          		return dScale;
                          	}

                          Comment

                          Working...
                          X