RC
RoboControl Documentation

VEX V5 Robotics Integration

Build competition-ready autonomous programs with advanced path planning, odometry, and code generation for VEX V5 robots.

For Competition Teams

The Problem Teams Face

You have 6 weeks until competition. Your mechanical design is done, but you still need to:

  • Calibrate encoder constants and drivetrain dimensions (frustrating trial-and-error)
  • Tune PID controllers for drive, arm, and intake (takes days of testing)
  • Design autonomous routines that actually score points (figuring out optimal paths manually)
  • Test everything without destroying your robot (risky hardware testing)

How RoboControl Solves It

Visual Path Designer: Draw your autonomous routines directly in the RoboControl app. No code needed. Point and click to set waypoints, define intake/scorer actions, and visualize the robot's path in real-time.

Auto Code Generation: Click "Generate Code" and get PROS C++ code automatically generated from your visual path. Paste it into your project and it works. Cut development time from days to hours.

Simulation Before Hardware: Test your entire autonomous routine in the physics simulator. See if paths are feasible, if intake timing is correct, if you'll knock over cones. Find bugs in simulation, not at competition.

Key Features

Tracking Wheel Odometry
2-wheel and 3-wheel odometry with automatic orientation estimation using parallel tracking wheels.
Pure Pursuit Controller
Smooth path following using lookahead distance based steering for accurate autonomous movement.
Code Generation
Automatically generate PROS C++ code for autonomous skills from visual path designs.
Physics Simulator
Test and validate autonomous programs in a realistic virtual environment before deploying.

Getting Started with VEX

1. Connect Your V5 Brain

Connect your VEX V5 Brain via USB cable. RoboControl will automatically detect the connection.

Copy
// Auto-detection
var connection = new VexConnection();
await connection.AutoConnectAsync();

// Or specify port manually
await connection.TryConnectAsync("COM3");

2. Configure Odometry

Set up your tracking wheels and drivetrain dimensions for accurate position tracking.

Copy
var config = new OdometryConfig
{
    TrackWidth = 12.0,              // Distance between drive wheels (inches)
    WheelDiameter = 3.25,            // Wheel diameter (inches)
    EncoderResolution = 360,         // Counts per revolution
    TrackingConfiguration = TrackingConfig.ThreeWheel
};

var odometry = new VexOdometry(config);

// Update with encoder readings
odometry.Update(leftEnc, rightEnc, backEnc);

// Access position and heading
Console.WriteLine($"X: {odometry.X}, Y: {odometry.Y}");
Console.WriteLine($"Heading: {odometry.ThetaDegrees}°");

3. Path Planning

Create paths visually in the RoboControl app or programmatically.

Copy
// Create waypoints
var waypoints = new List<Vector2>
{
    new Vector2(12, 12),      // Start position
    new Vector2(36, 24),      // Intermediate waypoint
    new Vector2(60, 12),      // Final waypoint
};

// Configure path follower
var controller = new PurePursuitController(
    lookaheadDistance: 15.0,
    trackWidth: 12.0
);
controller.SetPath(waypoints, reversed: false);

// Main autonomous loop
while (matchRunning)
{
    odometry.Update(leftEnc, rightEnc, backEnc);
    
    var (leftPower, rightPower) = controller.Compute(
        odometry.X, 
        odometry.Y, 
        odometry.Theta, 
        maxVelocity: 100
    );
    
    driveLeft.Power = leftPower;
    driveRight.Power = rightPower;
}

4. PID Tuning

The interactive PID tuner helps optimize your controller gains in real-time.

Copy
var pid = new PidController(
    kp: 2.0,
    ki: 0.5,
    kd: 0.1
)
{
    OutputMin = -127,
    OutputMax = 127,
    DerivativeFilterTf = 0.01  // Low-pass filter for derivative
};

// In your control loop
double error = setpoint - measurement;
double output = pid.Compute(setpoint, measurement, dt: 0.01);

// Apply output to motor
motor.Power = (int)output;

5. Code Generation

Export your paths and configurations as PROS C++ code for deployment to the V5 Brain.

Copy
var generator = new ProsCodeGenerator();

// Generate main.cpp
string mainCode = generator.GenerateMainCpp(
    config: robotConfig,
    path: selectedPath,
    teamName: "Team 1234A",
    robotName: "Intake Bot"
);

// Generate config header
string configHeader = generator.GenerateConfigHeader(robotConfig);

// Save files
File.WriteAllText("src/main.cpp", mainCode);
File.WriteAllText("include/robot_config.hpp", configHeader);

Advanced Odometry Configuration

Tracking Wheel Placement

RoboControl supports multiple odometry configurations optimized for different robot chassis designs:

  • 2-Wheel Odometry: Left and right drive encoder-based tracking with gyroscope support for heading estimation. Best for differential drive robots with accurate encoders.
  • 3-Wheel Odometry: Two parallel wheels (left/right) plus one perpendicular wheel. Provides heading without external gyroscope, highest accuracy for X8 drivetrains.
  • Hybrid Odometry: Combines encoder-based tracking with IMU fusion for drift compensation. Automatically corrects for dead reckoning error accumulation.
Copy
// Advanced odometry with IMU fusion
var config = new OdometryConfig
{
    TrackWidth = 12.0,
    WheelDiameter = 3.25,
    EncoderResolution = 360,
    TrackingConfiguration = TrackingConfig.ThreeWheel,
    
    // IMU fusion parameters
    EnableGyroFusion = true,
    GyroTimeConstant = 0.5,  // How much to trust gyro vs encoders
    DriftCompensationRate = 0.001
};

var odometry = new VexOdometry(config);

// Periodic drift correction
odometry.CorrectForGyroHeading(imuHeading);
odometry.ApplyHeadingOffset(correctionFactor);

Path Following Algorithms

Pure Pursuit Advanced Features

The Pure Pursuit algorithm provides adaptive lookahead and velocity control:

Copy
var controller = new PurePursuitController(
    baseLoookaheadDistance: 15.0,
    trackWidth: 12.0
)
{
    // Adaptive lookahead based on velocity
    AdaptiveLoookahead = true,
    MinLookahead = 8.0,
    MaxLookahead = 24.0,
    
    // Velocity profile
    MaxLinearVelocity = 60.0,  // in/s
    MaxAngularVelocity = 180.0, // deg/s
    
    // Path following tolerance
    CrossTrackErrorTolerance = 1.5,  // inches
    HeadingTolerance = 5.0            // degrees
};

// Enable smooth velocity ramping
controller.EnableAccelerationLimiting(
    linearAccel: 120.0,  // in/s²
    angularAccel: 360.0   // deg/s²
);

Trajectory Following with Velocity Profiles

Generate smooth S-curve trajectories for optimal autonomous performance.

Copy
// Quintic (5th order) trajectory with velocity constraints
var trajectory = new TrajectoryGenerator()
    .SetStartState(position: 0, velocity: 0, acceleration: 0)
    .SetEndState(position: 100, velocity: 0, acceleration: 0)
    .SetDuration(5.0)
    .SetMaxVelocity(50.0)
    .SetMaxAcceleration(30.0)
    .SetMaxJerk(60.0)  // Rate of change of acceleration
    .Generate();

// Follow trajectory in autonomous
for (double t = 0; t <= trajectory.Duration; t += 0.01)
{
    double targetPos = trajectory.GetPosition(t);
    double targetVel = trajectory.GetVelocity(t);
    
    // PID feedback control to track trajectory
    double error = targetPos - currentPos;
    double power = pidController.Calculate(error);
    
    drivetrain.SetPower(power);
}

Autonomous Skills Development

Skills Optimizer

Automatically optimize autonomous routines for maximum point scoring in competition.

Copy
var skillsOptimizer = new VexSkillsOptimizer();

skillsOptimizer.RegisterSkill("Mogo Rush", async (robot) =>
{
    await robot.DriveToAsync(60, 0);
    await robot.ClampAsync();
    await robot.DriveToAsync(0, 0);  // Return
});

skillsOptimizer.RegisterSkill("Corner Load", async (robot) =>
{
    await robot.DriveToAsync(30, 60);
    await robot.IntakePiecesAsync(3);
    await robot.DriveToAsync(60, 120);
});

// Optimization finds best skill sequence
var sequence = await skillsOptimizer.OptimizeAsync(
    availableTime: 45.0,  // seconds
    optimization: OptimizationMode.MaximizeScore
);

Console.WriteLine($"Estimated Score: {sequence.EstimatedScore}");
Console.WriteLine($"Execution Time: {sequence.TotalTime}s");

Code Generation for PROS

Auto-Generate PROS C++ Code

Design paths visually in the RoboControl editor and generate optimized PROS-compatible C++ code automatically.

Copy
// Auto-generated from visual path designer
void autonomous() {
    // Autonomous routine generated at: 2026-01-28 14:32:00

    // Drive forward and intake
    chassis.moveToPoint(60, 0, 50, true);  // x, y, speed, async
    intake.spin(fwd, 100, pct);

    // Turn to alliance stake
    chassis.turnToHeading(90, 50);
    
    // Score alliance stake
    arm.moveTo(ALLIANCE_STAKE_HEIGHT);
    arm.waitUntilSettled();

    // Return to start
    chassis.moveToPoint(0, 0, 50, false);
    
    intake.stop();
    arm.moveTo(HOME_POSITION);
}

// Raw waypoint data (for custom fine-tuning)
// Waypoints: {{0,0}, {30,15}, {60,0}, {90,30}}
// Total Time: 12.4s
// Path Signature: 0xA3F2D8E9

PID Gain Auto-Tuning

Automatically tune PID controllers using Ziegler-Nichols method or manual gain selection.

Copy
// Automatic PID tuning
var tuner = new PidTuner(motorController);

// Method 1: Ziegler-Nichols
var gains = await tuner.TuneZieglerNicholsAsync(
    setpoint: 50.0,
    settlingTime: 2.0
);

motorController.SetGains(gains);

// Method 2: Manual tuning with live feedback
var pidConfig = new PidConfig
{
    Kp = 0.45,
    Ki = 0.12,
    Kd = 0.08,
    
    // Anti-windup for integral
    MaxIntegralAccumulation = 100.0,
    
    // Derivative filter to reduce noise
    DerivativeFilterConstant = 0.1
};

motorController.Configure(pidConfig);

Sensor Monitoring & Diagnostics

Real-time sensor health monitoring with anomaly detection and logging.

Copy
// Motor health monitoring
var motorDiagnostics = new MotorDiagnostics(motor);

// Detect stalls, overheat, or electrical issues
motorDiagnostics.OnAnomalyDetected += (anomaly) =>
{
    Console.WriteLine($"Alert: {anomaly.Type}");
    Console.WriteLine($"  Current: {anomaly.CurrentDraw}A");
    Console.WriteLine($"  Temperature: {anomaly.Temperature}°C");
    
    // Auto-disable if dangerous
    if (anomaly.Severity == SeverityLevel.Critical)
    {
        motor.Stop();
        logger.LogError("Motor disabled due to critical anomaly");
    }
};

// Track performance over time
var stats = motorDiagnostics.GetStatistics();
Console.WriteLine($"Encoder Drift: {stats.EncoderDrift}");
Console.WriteLine($"Temperature Peak: {stats.MaxTemperature}°C");
Console.WriteLine($"Stall Count: {stats.StallCount}");

Robot Simulation

Test autonomous programs without physical hardware using physics-based simulation.

Copy
var simulator = new RobotSimulator(
    leftMotorCount: 3,
    rightMotorCount: 3
);

simulator.Reset(x: 12, y: 12, heading: 0);

// Simulation loop
for (int i = 0; i < 1000; i++)
{
    simulator.SetMotorPower(leftPower: 80, rightPower: 80);
    simulator.Step();  // Advance physics
    
    var state = simulator.State;
    Console.WriteLine($"Sim X: {state.X}, Y: {state.Y}");
}

Skills Optimizer

Automatically optimize autonomous skill sequences for maximum points.

Copy
var skillsOptimizer = new SkillsOptimizer();
skillsOptimizer.AddSkill(skillName: "goal_rush", points: 5, timeSeconds: 8);
skillsOptimizer.AddSkill(skillName: "ring_stack", points: 3, timeSeconds: 12);
skillsOptimizer.AddSkill(skillName: "wall_stack", points: 4, timeSeconds: 10);

var optimalSequence = skillsOptimizer.OptimizeForMaxPoints(totalTime: 60);
foreach (var skill in optimalSequence)
{
    Console.WriteLine($"{skill.Name}: {skill.Points} pts");
}
⚠ Safety Reminder
Always keep the emergency stop button within reach when testing autonomous programs on physical robots. Use simulation mode first to verify your logic.

Common Tasks

Monitor Motor Health

Track motor temperature, power consumption, and efficiency during matches.

foreach (var motor in robot.Motors)
{
    double tempC = motor.Temperature;
    double powerW = motor.Voltage * motor.Current;
    double efficiency = (motor.AngularVelocity * motor.Torque) / powerW;
    
    if (tempC > 50) // Warning threshold
        Console.WriteLine("Motor overheat risk!");
}

Sensor Integration

Integrate vision systems, distance sensors, and other peripherals.

// Vision-based target tracking
var visionSensor = robot.Vision1;
var targets = visionSensor.GetObjects(signature: 1);

if (targets.Count > 0)
{
    var largestTarget = targets.OrderByDescending(t => t.Width).First();
    double horizontalError = largestTarget.CenterX - 158;  // Center of 316x212 image
    
    // Feed to PID controller for tracking
    double steeringOutput = visionPid.Compute(0, horizontalError, dt);
}

Next Steps

Learn more about motion planning and control theory:

Motion Planning Math API Control Theory