LogoLogo
  • Welcome!
  • Mission Statement
  • Contributing Guidelines
    • Embed CADs in Wiki Articles
  • VEX Worlds Livestream Archive
    • VEX U
    • V5RC High School
    • V5RC Middle School
    • VIQRC Middle School
    • VIQRC Elementary School
    • JROTC
  • ⚙️Hardware
    • Design Fundamentals
      • Gear Ratios
      • Internal Forces (Stress)
      • Torque
      • RPM
      • Center of Mass
    • Introduction to VEX Parts
      • Structure
        • C-Channels and Angles
        • Fasteners
        • Retainers
        • Gussets and Brackets
        • Bearings
        • Plate Metal and Flat Bars
      • Motion
        • High Strength Components
        • Gears and Sprockets
        • Traction Wheels
        • Mecanum Wheels
        • Omnidirectional Wheels
        • Flex Wheels
    • Robot Decorations
      • Part Dyeing
      • Metal Coloring
      • License Plate Holders
    • Lifts
      • Double Reverse Four Bar (DR4B or RD4B)
      • Four Bar
      • Scissor Lift
      • Six Bar
      • Other Lifts
      • Best Practices
    • Shooting Mechanisms
      • Catapult
      • Flywheel
      • Linear Puncher
    • Drivetrains
      • Tank Drive
      • Mecanum Drive
      • Holonomic Drive
      • Designing a Drivetrain
      • Best Practices
    • Pivots & Joints
    • Pneumatics
      • Best Practices - Pneumatics
    • Intakes
    • Flip Out Mechanisms
    • Defensive Mechanisms
    • Misc. Building Techniques
    • VexU
      • Common Manufacturing Techniques
        • 3D Printing
        • Laser Cutting
      • Custom Manufactured Parts Library
      • Commercial Off The Shelf Parts Library
  • 👑Team Administration
    • New Team Resources
      • Creating The Team
      • Gaining Interest for Robotics Teams
      • Attending Competitions
        • Elimination Bracket
    • Team Dynamics
      • Organization Structure and Longevity
      • Member Allocation and Management
      • How *Not* To Run a Team
    • Team Finances
      • One-Year Team Financial Breakdown
      • Funding Your Teams
    • Hosting Competitions
      • Live Streaming
      • Tournament Manager
        • Competition Electronics
        • Creating a Tournament
        • Tools
          • Field Set Control
          • Connecting Mobile Devices
          • Connecting Raspberry Pis
        • Match Control
          • Inputting Match Scores
          • Inputting Skills Scores
          • Inputting Scores on TM Mobile
        • Displays
        • Alliance Selection
      • Additional Event Partner Resources
    • VexU Organization Management
      • Getting Started in VexU
      • Team / Personnel Management
      • Volunteering At Local Events
  • 📚The Judging Process
    • The Engineering Design Process
      • Test and Refine
    • The Engineering Notebook
      • Segments of the Notebook
      • BLRS2 '23-'24 Engineering Notebook
      • Integrating Inventor Models into Documentation
      • Engineering Notebook Rubric Breakdown
    • The Interview
      • Interview Rubric Breakdown
    • Using Notion for an Engineering Notebook
      • How to Setup a Notebook
      • How to Create Entries
      • How to Export a Notebook
      • Purdue SIGBots Notion Template
        • Game Analysis
        • Identify The Problem
        • Brainstorm Solution
        • Select Best Approach & Plan
        • Build Log
        • Programming Log
        • Testing Solution
        • Tournament Recap
        • Innovative Feature
  • 🖥️VEX CAD
    • CAD Programs
      • Inventor
      • Fusion 360
      • Solidworks
      • OnShape
      • Protobot
    • Making a Chassis
      • Inventor Chassis: The Basics
        • Installation
        • User Interface Overview
        • Dark Mode
        • Assemblies
        • Placing Parts
        • Navigating CAD
        • Changing Visual Style
        • Grounding
        • Connecting Two C-Channels
        • Modifying Existing Constraints
        • Toggling Visibility on Existing Parts
        • Completing Half of the Chassis
          • Inner Drive Channel
          • Bearing Flats
          • Motors
          • Wheels
          • Sprockets
          • Spacers, Washers and Standoffs
          • Spacers Cont.
        • Creating Mid-Plane
        • Mirroring
      • Inventor Chassis: Best Practices
        • File Structure
        • Subassemblies
        • Wheel Subassembly
        • Origin Planes
        • Cross Brace
        • Drive Channels
        • Simple Motor iMates
        • Replacing Simple Electronics
        • Completing Half of the Drive
          • Bearing Flats (Best Practice)
          • Wheels
          • Powered Gear
          • Spacer Boxing
          • Spacers, Washers and Standoffs (Best Practice)
        • Model Browser Folders
        • Mirroring (Best Practice)
        • Model Browser Folder (Right)
        • Main Assembly
      • Fusion 360 Chassis
      • Solidworks Chassis, Chain, and Custom Plastic
    • Remembering The Best
      • 62A Skyrise
      • 400X Nothing But Net
      • 2587Z Nothing But Net
      • 365X Starstruck
      • 62A In The Zone
      • 202Z In The Zone
      • 5225A In The Zone
      • 169A Turning Point
      • 929U Turning Point
      • 7K Tower Takeover
      • 5225A Tower Takeover
      • 62A Change Up
    • Scuff Controller
  • 💻Software
    • Odometry
    • Path Planning
    • Robotics Basics
      • Arcade Drive
      • Tank Drive
      • Joystick Deadzones
      • Curvature (Cheesy) Drive
      • Subsystem Toggling
    • Organizing Code
      • Code Style
      • Code Styling Guide
      • Writing Good Comments
      • Version Control
    • Control Algorithms
      • Bang Bang
      • PID Controller
      • Basic Pure Pursuit
      • Flywheel Velocity Control
      • Kalman Filter
      • Take Back Half (TBH) Controller
      • RAMSETE Controller
    • Competition Specific
      • Operator Control
      • Autonomous Control
    • C++ Basics for VEX Robotics
      • Basic Control Flow
      • Enumerations
      • Namespaces (::)
      • Multiple Files (C/C++)
    • VEX Programming Software
      • PROS
        • OkapiLib
      • vexide
      • Robot Mesh Studio (RMS)
      • EasyC
      • RobotC
      • VEXcode
      • Midnight C
    • General
      • Stall Detection
      • Register Programming
      • Sensors and Odometry in Autonomous
      • Embedded Programming Tips
      • Debugging
      • Bit Shift
      • Bit Mask
      • Autoformatting
      • Finite State Machine
      • Data Logging
    • Object Recognition
      • Red Green Buoy
      • AMS
      • OpenCV
      • OpenNI
    • 🤖AI in VRC: Pac-Man Pete
  • ⚡VEX Electronics
    • V5 ESD Protection Board
    • VEX Electronics
      • VEX V5 Brain
        • V5 Electronics Observations and Issues
      • VEX Controller
      • VEXnet and V5 Robot Radio
      • VEX Battery
      • VEX Motors
    • VEX Sensors
      • 3-Pin / ADI Sensors
        • Encoder
        • Potentiometer
        • Limit Switch
        • Bumper Switch
        • Accelerometer
        • Gyroscope
        • Ultrasonic
        • Line Tracker
        • LED Indicator
      • Smart Port Sensors
        • GPS Sensor
        • Rotation Sensor
        • Vision Sensor
        • Optical Sensor
        • Distance Sensor
        • Inertial Sensor (IMU)
        • 3-Wire Expander
    • V5 Brain Wiring Guide
    • Legacy
      • VEX Cortex
      • Power Expander
      • VEX Motor Controller
      • VEX Cortex Wiring Guide
  • General Electronics
    • General Topics
      • External Boards
        • ASUS Tinker Board S
        • Arduino
        • Beagleboard
        • Leaflabs Maple
        • LattePanda
        • Meadow F7 Micro
        • Netduino
        • ODROID-XU4
        • Pandaboard
        • Raspberry Pi
      • Analog-Digital Converter (ADC)
      • Bit-Bang
      • GPIO
      • I2C
      • Jitter
      • Line Noise
      • List of Tools
      • Output Drive
      • Power Consumption
      • Radius Array
      • Resettable Fuse (PTC)
      • SPI
      • Slew Rate
      • Stalling
      • USART
      • UART
      • 5 Volt Tolerant
      • DC Motor Basics
Powered by GitBook
LogoLogo

This work is licensed under a Attribution-ShareAlike 2.0 Generic License

On this page
  • Implementation
  • Teams Contributed to this Article:

Was this helpful?

Edit on GitHub
Export as PDF
  1. Software
  2. Robotics Basics

Curvature (Cheesy) Drive

Fancy Arcade Drive for better robot control

PreviousJoystick DeadzonesNextSubsystem Toggling

Last updated 1 year ago

Was this helpful?

Curvature Drive, or "Cheesy Drive", is a controller mapping for operator control that was first popularized by Team 254, The Cheesy Poofs, of FRC. Curvature Drive applies some math to the joystick inputs from a controller to provide a more intuitive driving experience for new VEX (or FRC) drivers

The original Cheesy Drive implementation (from their ) essentially does three things:

  • The "curvature" naming comes from the algorithm's change to the way that the "turn" joystick input is processed. When you a driving forward or backwards and turning at the same time, the turn input affects the curvature of the movement rather than adding/subtracting linearly from the wheel speeds. The turn output is a sum of the throttle and turn inputs, meaning that the robot will turn faster when it's moving forward at a higher speed. Again, the goal here is more control at low speeds. Note that the turn input is not changed when the robot is turning in place, this just affects the way the robot drives in an "S" shaped path.

  • Cheesy Drive also applies some non-linearity to the joystick input so that there is more control at the low speeds. Larger changes in joystick inputs result in smaller changes in real speed when driving slow, but when the joystick is pushed to a high speed, you jump up to full speed faster.

  • Third, that turn input is affected by a negative inertia accumulator. Most robots have a fair bit of turning inertia, which can make it easy to accidentally overshoot a turn. The negative inertia accumulator acts almost like a reverse - the longer the robot has been turning (fast) for, the slower the robot will turn.

Implementation

You can find an implementation of Cheesy Drive, with all three components listed above, in the or in the snippet below. The snippet is platform-agnostic, and should run without modification in either PROS or VEXCode.

// We apply a sinusoidal curve (twice) to the joystick input to give finer
// control at small inputs.
static double _turnRemapping(double iturn) {
	double denominator = sin(PI / 2 * CD_TURN_NONLINEARITY);
	double firstRemapIteration =
	    sin(PI / 2 * CD_TURN_NONLINEARITY * iturn) / denominator;
	return sin(PI / 2 * CD_TURN_NONLINEARITY * firstRemapIteration) / denominator;
}

// On each iteration of the drive controller (where we aren't point turning) we
// constrain the accumulators to the range [-1, 1].
double quickStopAccumlator = 0.0;
double negInertiaAccumlator = 0.0;
static void _updateAccumulators() {
	if (negInertiaAccumlator > 1) {
		negInertiaAccumlator -= 1;
	} else if (negInertiaAccumlator < -1) {
		negInertiaAccumlator += 1;
	} else {
		negInertiaAccumlator = 0;
	}

	if (quickStopAccumlator > 1) {
		quickStopAccumlator -= 1;
	} else if (quickStopAccumlator < -1) {
		quickStopAccumlator += 1;
	} else {
		quickStopAccumlator = 0.0;
	}
}

double prevTurn = 0.0;
double prevThrottle = 0.0;
std::pair<double, double> cheesyDrive(double ithrottle, double iturn) {
	bool turnInPlace = false;
	double linearCmd = ithrottle;
	if (fabs(ithrottle) < DRIVE_DEADBAND && fabs(iturn) > DRIVE_DEADBAND) {
		// The controller joysticks can output values near zero when they are
		// not actually pressed. In the case of small inputs like this, we
		// override the throttle value to 0.
		linearCmd = 0.0;
		turnInPlace = true;
	} else if (ithrottle - prevThrottle > DRIVE_SLEW) {
		linearCmd = prevThrottle + DRIVE_SLEW;
	} else if (ithrottle - prevThrottle < -(DRIVE_SLEW * 2)) {
		// We double the drive slew rate for the reverse direction to get
		// faster stopping.
		linearCmd = prevThrottle - (DRIVE_SLEW * 2);
	}

	double remappedTurn = _turnRemapping(iturn);

	double left, right;
	if (turnInPlace) {
		// The remappedTurn value is squared when turning in place. This
		// provides even more fine control over small speed values.
		left = remappedTurn * std::abs(remappedTurn);
		right = -remappedTurn * std::abs(remappedTurn);

	} else {
		double negInertiaPower = (iturn - prevTurn) * CD_NEG_INERTIA_SCALAR;
		negInertiaAccumlator += negInertiaPower;

		double angularCmd =
		    abs(linearCmd) *  // the more linear vel, the faster we turn
		        (remappedTurn + negInertiaAccumlator) *
		        CD_SENSITIVITY -  // we can scale down the turning amount by a
		                          // constant
		    quickStopAccumlator;

		right = left = linearCmd;
		left += angularCmd;
		right -= angularCmd;

		_updateAccumulators();
	}

	prevTurn = iturn;
	prevThrottle = ithrottle;
	
	return std::make_pair(left, right);
}

Teams Contributed to this Article:

(Purdue SIGBots)

💻
2015 Java Code
integral controller
Team BLRS Turning Point code
BLRS