# Programming Mecanum - Refined

How a Mecanum Drivetrain is programmed largely depends on the driver's preference for how the controller is configured.

In our provided example, the left joystick controls forward/back and strafe then the right joystick controls turning. This code is based on the sample provided by *FIRST* for Blocks (BasicOmniOpMode) available in the [Robot Controller Console](https://docs.revrobotics.com/duo-control/hello-robot-blocks/where-to-program#rev-hardware-client).

## **Mecanum Configuration**

<table><thead><tr><th>Port Type</th><th width="132">Port Number</th><th width="224">Device Type</th><th>Name</th></tr></thead><tbody><tr><td>Motor</td><td>0</td><td>REV Robotics Ultraplanetary HD Hex Motor</td><td>frontLeft</td></tr><tr><td>Motor</td><td>1</td><td>REV Robotics Ultraplanetary HD Hex Motor</td><td>backLeft</td></tr><tr><td>Motor</td><td>2</td><td>REV Robotics Ultraplanetary HD Hex Motor</td><td>frontRight</td></tr><tr><td>Motor</td><td>3</td><td>REV Robotics Ultraplanetary HD Hex Motor</td><td>backRight</td></tr></tbody></table>

### Mecanum Example Code

{% file src="<https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FkDjTckkF2Gu3uwbIRn7M%2FmecanumFull.blk?alt=media&token=0647b8ca-fc5d-4bcb-94a8-b3077a773873>" %}

## Mecanum Code Breakdown <a href="#mecanum-code-breakdown" id="mecanum-code-breakdown"></a>

{% hint style="info" %}
Before diving into mecanum, double check the direction your motors and wheels are spinning. They may need to be reversed if you're experiencing jittering or inverted controls!

Adjust the  ![](https://docs.revrobotics.com/~gitbook/image?url=https%3A%2F%2F268621232-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-MHCAE012xNfg1h3SM9v%252Fuploads%252Fsd50OrsprUDav0TPnrSt%252Fimage.png%3Falt%3Dmedia%26token%3Dca1e5857-bb4c-48c3-a2e2-54044e9fc94b\&width=300\&dpr=4\&quality=100\&sign=d3125b20\&sv=1) block to change the set direction during initialization.
{% endhint %}

This example makes use of [functions](https://docs.revrobotics.com/duo-control/hello-robot-blocks/part-4-going-beyond/exploring-functions) to help organize the code!

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2Fu5O5BvJBDecZwVNNKGRo%2Fimage.png?alt=media&#x26;token=b26d327a-ee61-42e7-a00f-228ec9970147" alt="" width="463"><figcaption><p>With functions are main loop appears simplified</p></figcaption></figure>

At the very beginning of our program, our MOTOR\_SETTINGS function is called. Within it the drivetrain motors are set to RUN\_WITHOUT\_ENCODER and are set to run the appropriate direction.&#x20;

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2Fq2FzulvhGrjHLgGr1dFB%2Fimage.png?alt=media&#x26;token=aa703d31-7c92-4bd6-ac7c-42c029192096" alt="" width="563"><figcaption><p>Setting our motor settings within the function</p></figcaption></figure>

### Establishing Variables

Next, we need to create some new variables in order to use mecanum.&#x20;

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FsCNlRHArDWqPEbN6oMzD%2Fimage.png?alt=media&#x26;token=6f7e1a74-6ba1-409b-9d4c-4fe5fd5a6d65" alt="" width="377"><figcaption><p>All our variables for mecanum</p></figcaption></figure>

Let's break those down first:

| Variable        | Purpose                          |
| --------------- | -------------------------------- |
| forwardBack     | Moving forward and backwards     |
| strafe          | Strafing side to side            |
| turn            | Turning left and right           |
| leftFrontPower  | Sets the front left motor power  |
| rightFrontPower | Sets the front right motor power |
| leftBackPower   | Sets the back left motor power   |
| rightBackPower  | Sets the back right motor power  |

### Calculating Motor Movement with the Gamepad

At the beginning of the MECANUM\_DRIVE function, our variables for each movement direction are being set to the value generated by the movement of the matching joystick axis.

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FpZaQ070vPSAiDU6N7ZNK%2Fimage.png?alt=media&#x26;token=1fd953a7-26f1-4645-8d52-8e2caf182db8" alt="" width="459"><figcaption><p>Our variables are set to their appropriate joystick movement</p></figcaption></figure>

Since we now have four motors in play, our equation for setting the needed power to each motor gets a little more complicated.

Our robot first needs to determine the combined movement of the gamepads's left joystick:

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FfYbKyM3xw1XANcuEfDDR%2Fimage.png?alt=media&#x26;token=c84a0b12-695d-4796-ae40-9823da06358f" alt="" width="470"><figcaption><p>Motor power being calculated with the left joystick movement</p></figcaption></figure>

&#x20;Then calculate with the right stick's value:

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FyaJRnhzD1X2CwmU2m5Vh%2Fimage.png?alt=media&#x26;token=255e7c71-931d-4245-a624-77d3dadaf597" alt="" width="563"><figcaption><p>Motor power being calculated with both joysticks</p></figcaption></figure>

All our calculations together allows for movement when the left joystick is moved at an angle, such as for strafing along a diagonal!

### Quick Check! - Understanding Motor Power

Let's take a closer look at how our motor power is being determined. For example, our leftFrontPower variable will equal:

$$
leftFrontPower = (forwardBack + strafe) + turn
$$

So what if we move our left joystick all the way to the left side along the X-axis. To our robot, our equation will read something like this:

$$
leftFrontPower = (0 + -1)+ 0
$$

Take a moment to think: What would be the power of our other motors?

<details>

<summary>What would be the power of our other motors?</summary>

Our other motor power would look like the following:&#x20;

* rightFrontPower = (0 - (-1)) + 0
* leftBackPower = (0 - (-1)) - 0
* rightBackPower = (0 + -1) - 0

Or simplified:&#x20;

* leftFrontPower = -1
* rightFrontPower = 1
* leftBackPower = 1
* rightBackPower = -1

As we can see our motors are spinning the same direction as their diagonal partner, meaning the robot will strafe left!&#x20;

</details>

What about a more complicated example? What if we had the left joystick at an angle, all the way to the left and halfway towards the top? Or had our left stick forward and right stick all the way right?

<details>

<summary>What about a more complicated example?</summary>

Looking at our leftFrontPower again as an example the robot might calculate the following:

What if we had the left joystick at an angle, all the way to the left and halfway towards the top?

* leftFrontPower = (0.5 + -1) + 0&#x20;

In this situation, our leftFront motor would set the power to -0.5!

Or had our left stick forward and right stick all the way right?

* leftFrontPower = (1 + 0) + 1&#x20;

In this case, while our equation equals to 2, our motor cannot power higher than 1 so will cap out at full power! We'll discuss [normalizing motor values](#normalizing-input-values) to remain within range below.

Adding telemetry to your program, as seen below, can help to see the values the motors are assigned during different scenarios:

![](https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2Fq8dAdhBDBbxvUPUPdOHz%2Fimage.png?alt=media\&token=23696092-84bd-4d03-8d79-4bfc54c7d595)

</details>

### Setting Motor Power

For our last step, our robot sets the power of each pair of motors based on all our calculations!

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2F7VujisZC5Eh5MecoCMML%2Fimage.png?alt=media&#x26;token=2b4943b9-b9cf-4424-9ffb-cbf91f4a791f" alt="" width="414"><figcaption><p>Setting each motor's power to their variable</p></figcaption></figure>

## Normalizing Input Values

{% hint style="info" %}
This section of code is not within the [provided copy of the mecanum code](#mecanum-example-code) used in this tutorial. Follow the steps below to add it!
{% endhint %}

While driving, there's a possibility a value may fall outside the range of the motor's power (-1 to 1). To help make sure no inputs are lost because of this, we can use a technique called "normalizing".

What normalizing does is take all of our calculated values and scales them appropriately to remain inside the intended range.

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FqlKYUtzdquo0nNXUCVzq%2Fimage.png?alt=media&#x26;token=48d180e2-c955-4e58-8d63-1d0d2bcd4f71" alt=""><figcaption><p>Normalizing the motor power values</p></figcaption></figure>

### Creating a Max Variable

First we need to create a new variable called "max".&#x20;

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FtAUQivx6mBECWC6c5SOP%2Fimage.png?alt=media&#x26;token=d3bb6a2e-0a96-4b5d-83bb-6ef1e5255751" alt="" width="93"><figcaption><p>Creating a new variable</p></figcaption></figure>

In Blocks, we use something called a "list", also known as an "array" to store a set of numbers. In this case, we will be storing all of our motor powers.&#x20;

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FVAb38yBdyXoTexTvEwRf%2Fimage.png?alt=media&#x26;token=fe0fe865-b5c8-436a-9788-42dc61d4c978" alt="" width="335"><figcaption><p>Creating a list in Blocks</p></figcaption></figure>

But first, we need to add a ![](https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FqBkR165GYhHqFF15J2Ka%2Fimage.png?alt=media\&token=347d767f-e573-427c-a8d7-f627fcfea623) block from our "Math" menu. We will change this using the dropdown to "max", meaning it is returning the largest value from our list of motor powers.&#x20;

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2F68oH3uuSTLBNbcBOnEOW%2Fimage.png?alt=media&#x26;token=7e100b7a-4b39-4a38-940c-2e1ce650970c" alt="" width="398"><figcaption><p>Setting our variable to the highest motor value</p></figcaption></figure>

Since our motor power will sometimes be negative, such as when turning in reverse, we want to make sure we're using the absolute value of our motor powers.&#x20;

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2Fb9yDvpytinvk60UXuPM3%2Fimage.png?alt=media&#x26;token=131e92c0-f8cc-4ad2-a7c1-543a430b10ee" alt="" width="236"><figcaption><p>Finding the "absolute" block in the "Math" menu</p></figcaption></figure>

### Creating the If/Else Statement

Next, we will set up our[ If/Else](https://docs.revrobotics.com/duo-control/part-1/programming-servos/using-a-gamepad-with-a-servo#introducing-if-else-statements) to check if our "max" is higher than 1 and therefore outside the motor's range.&#x20;

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FZPqpI4Nxf9fCUodGkS8F%2Fimage.png?alt=media&#x26;token=54c1d5b5-6edd-4536-b83b-0f88cb502167" alt="" width="240"><figcaption><p>Our max variable if/else statement</p></figcaption></figure>

Using this statement, we'll readjust each of our motor's power back to be within range proportionally by dividing each by the max value.&#x20;

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FIA4vND8eitpIlaQwdb7v%2Fimage.png?alt=media&#x26;token=8ce417b9-1267-44da-9bfd-4add7f6f624c" alt="" width="521"><figcaption><p>Full If/Else statement</p></figcaption></figure>

Now our full drivetrain function will look like the following:

<figure><img src="https://1359443677-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUOOiQ4S2QcMWmVoSmeQ8%2Fuploads%2FeffFgHj50E6Rha4JTUn6%2Fimage.png?alt=media&#x26;token=2b67fea8-3a0a-42cc-a5b8-b1171ec38e66" alt="" width="416"><figcaption><p>Full mecanum drivetrain program with normalizing</p></figcaption></figure>
