# Create a Modular Resource to Control a Rover like Intermode

Viam supports most rovers with builtin models. If your rover is not supported out of the box, this tutorial shows you how to add support for your rover or mobile robot.

To use a rover with the Viam platform, you have to [configure the rover’s components](https://docs.viam.com/tutorials/configure/configure-rover/). One of the components you need to configure is called a [base](https://docs.viam.com/reference/components/base/), which allows you to control a mobile robot using [commands](https://python.viam.dev/autoapi/viam/components/base/index.html#package-contents) like “move_straight”, “spin”, “set_velocity” and “stop”. You can think of the base component as an abstraction that coordinates the movement of the motors of your base for you so you can control the higher level object as a base.

For many robotic rovers you can use the [`wheeled`](https://docs.viam.com/reference/components/base/wheeled/) base model. Once you specify the circumference of the wheels and how far they are apart, you can then control your rover with the base component.

However, some rovers or other mobile robots do not expose direct motor control. For these types of machines, this tutorial shows you how to create a modular resource. Creating a modular resource for your robot allows you to issue commands using the same [`base` interface](https://docs.viam.com/reference/apis/components/base/#api) as you would with builtin Viam components. Once you have created the custom component, you can control both the Viam components and the modular resources using any of the [Viam SDKs](https://docs.viam.com/reference/apis/). Even if your modular resource is built in Golang, you can use the Python, C++, or any other Viam SDK to issue commands.

#### Tip

You can follow the tutorial for any rover or mobile robot, but the tutorial will specifically use the [Intermode rover](https://www.intermode.io/) as an example for creating a modular resource to control your rover.

**Intermode** aims to make the hardware aspects of a mobile-robot-based business simple and worry-free. This is a powerful pairing, since Viam simplifies the software aspects to revolutionize hardware.

The Intermode rover uses the [CAN bus](https://en.wikipedia.org/wiki/CAN_bus) protocol, a robust and prevalent vehicle communication standard used in most modern vehicles. This tutorial shows you how to leverage this protocol and abstract it into the Viam base interface, so that your rover can be controlled securely from anywhere with the programming language of your choice.

## Hardware requirements

The tutorial uses the following hardware:

- [Raspberry Pi with microSD card](https://a.co/d/bxEdcAT), with `viam-server` installed per [our Raspberry Pi setup guide](https://docs.viam.com/reference/device-setup/rpi-setup/).
- [An Intermode rover](https://www.intermode.io/)
- [PiCAN 2 - Canbus interface for Raspberry Pi](https://copperhilltech.com/pican-2-can-bus-interface-for-raspberry-pi/)
- [12V to 5V Buck Converter](https://www.amazon.com/dp/B01M03288J)
- [USB-C Male Plug to Pigtail Cable](https://www.amazon.com/Type-C-Cable-10inch-22AWG-Pigtail/dp/B09C7SLHFP)

## Setup

### Machine setup

Before you can use Viam on your device, you must ensure it has a supported operating system. See [Start a new machine](https://docs.viam.com/set-up-a-machine/first-machine/) for platform requirements and instructions.

Add a new machine on [Viam](https://app.viam.com/). On the machine’s page, follow the setup instructions to install `viam-server` on the computer you’re using for your project. Wait until your machine has successfully connected to Viam.

Next, install the PiCAN 2 driver software [following these instructions](https://copperhilltech.com/blog/pican2-pican3-and-picanm-driver-installation-for-raspberry-pi/).

#### Tip

If you restart your Pi, you need to bring up the CAN interface again, as the above linked instructions do not set this process up to automatically start on system start.

### Hardware

#### Caution

Always disconnect devices from power before plugging, unplugging or moving wires or otherwise modifying electrical circuits.

Power your Raspberry Pi off and attach the PiCAN 2 by aligning the 40 way connector and fitting it to the top of the Pi [using a spacer and a screw](https://copperhilltech.com/blog/pican2-pican3-and-picanm-driver-installation-for-raspberry-pi).

Next, with the Intermode rover powered down, connect the 6-wire amphenol connector that comes with the rover to the 4 screw terminal on PiCAN bus:

- Connect one of the 12V wires (red) to the +12V terminal
- Connect one of the ground wires (black) to the GND terminal
- Connect the CAN low wire (blue) to the CAN_L terminal
- Connect the CAN high wire (white) to the CAN_H terminal.

You have two remaining wires (12V and ground).

Connect the remaining two wires to the + (red) and - (black) **input** terminals on your buck converter. Attach the USB-C adapter wires to the **output** of your buck converter, and plug the other end of the USB-C adapter into your Pi. You can now power up the rover, which also provides power to your Pi and allows it to communicate with the rover using CAN bus!

## A modular resource for the Intermode base

The Viam platform provides [APIs](https://docs.viam.com/reference/apis/) for common component types within `viam-server`. For controlling a mobile robot’s movements, the [base component](https://docs.viam.com/reference/components/base/) exposes a useful interface.

In the rest of this tutorial, you’ll learn how to use this API to create your own custom modular resource. If you want to directly configure this modular resource code with your robot, skip to [using the intermode base resource](https://docs.viam.com/tutorials/custom/controlling-an-intermode-rover-canbus/#use-the-intermode-base-modular-resource).

### Create a custom model using the Viam RDK base API

The [base](https://docs.viam.com/reference/components/base/) component exposes an API for controlling a mobile robot’s movements. To use it for the Intermode rover, you must create a new model with its own implementation of each method.

Generally modular resources are made up of two parts:

- The first part is the entry point for the module. It creates the model and registers it with `viam-server` which makes it usable by the Viam SDKs.
- The second part implements the functionality for the API.

The full code for the modular resource is available on [GitHub](https://github.com/viam-labs/tutorial-intermode/blob/main/intermode-base/module.go). This is the code for the entry point:

```go

```

To support this new model of a base that you are creating, you need to give the model a name. This tutorial uses the namespace `viamlabs`, an (arbitrary) module-name called `tutorial` and lastly, the model name `intermode`. The complete triplet is:
`viamlabs:tutorial:intermode`.

The entry point code defines the model name and then registers it with `viam-server`. When registering it, the code also provides the API that the new model supports. That means in this case that the base should support the default [base API](https://docs.viam.com/reference/apis/components/base/#api) with methods such as `MoveStraight` and `Spin`.

The **API** of any Viam resource is also represented as colon-separated triplets where the first element is a namespace. Since you are using the default Viam API for a [base](https://docs.viam.com/reference/components/base/), the API namespace triplet is:
`rdk:component:base`. In the code this is specified on line 30 as `base.Subtype`.

### Implement base methods

Now that the modular resource code has registered the API it is using and its custom model, you can implement the methods provided by the base API. Since the Intermode rover’s commands are in the CAN bus format, you need the modular resource code to translate any commands sent from the base API, like _SetPower_, _SetVelocity_, or _Stop_ to [CAN bus frames](https://en.wikipedia.org/wiki/CAN_bus#Frames). For reference, Intermode provides documentation on how its [CAN frames](https://github.com/viam-labs/tutorial-intermode/blob/main/can_interface.pdf) are formatted.

At a high level, the [tutorial code](https://github.com/viam-labs/tutorial-intermode/blob/main/intermode-base/module.go) does the following:

1. The `SetPower` command implements the SetPower interface from the _rdk:component:base_ API
2. The parameters sent to `SetPower` are formatted as a _driveCommand_
3. The _driveCommand_ is converted to a CAN frame, and set as the next command
4. _publishThread_ runs a loop continuously, sending the current command every 10ms (the Intermode base will otherwise time out)

```go
// this struct describes intermode base drive commands
type driveCommand struct {
    Accelerator   float64
    Brake         float64
    SteeringAngle float64
    Gear          byte
    SteerMode     byte
}

func (base *interModeBase) setNextCommand(ctx context.Context, cmd modalCommand) error {
    if err := ctx.Err(); err != nil {
        return err
    }
    select {
    case <-ctx.Done():
        return ctx.Err();
    case base.nextCommandCh <- cmd.toFrame(base.logger):
    }
    return nil
}

// toFrame convert the drive command to a CANBUS data frame.
func (cmd *driveCommand) toFrame(logger logging.Logger) canbus.Frame {
    frame := canbus.Frame{
        ID:   driveId,
        Data: make([]byte, 0, 8),
        Kind: canbus.SFF,
    }
    frame.Data = append(frame.Data, calculateAccelAndBrakeBytes(cmd.Accelerator)...)
    frame.Data = append(frame.Data, calculateSteeringAngleBytes(cmd.SteeringAngle)...);

if cmd.Accelerator < 0 {
        cmd.Gear = gears[gearReverse]
    }
    frame.Data = append(frame.Data, cmd.Gear, cmd.SteerMode);

logger.Debugw("frame", "data", frame.Data);

return frame;
}

func (base *interModeBase) SetPower(ctx context.Context, linear, angular r3.Vector, extra map[string]interface{}) error {
    return base.setNextCommand(ctx, &driveCommand{
        Accelerator:   linear.Y * 100,  // the base API provides linear.Y between -1 (full reverse) and 1 (full forward)
        Brake:         0,
        SteeringAngle: angular.Z * 100, // the base API provides angular.Z between -1 (full left) and 1 (full right)
        Gear:          gears[gearDrive],
        SteerMode:     steerModes[steerModeFourWheelDrive],
    })
}
```

With this code, the intermode base can receive and execute `SetPower` commands using any Viam SDK.

### Leaving some methods unimplemented

In some cases, you may not want to implement specific methods provided by the resource type’s API. For example, some hardware may not support specific functionality. When you want to leave a method unimplemented you must still create that method, but return an appropriate error message.

In this tutorial, the code leaves the _IsMoving_ method unimplemented (for illustrative purposes).

```go

```

## Use the Intermode base modular resource

### Copy the modular resource binary

This tutorial’s modular resource code leverages libraries (specifically a [CAN bus library](https://github.com/go-daq/canbus)) that run on Linux and interface with the PiCAN socket on your Raspberry Pi. The tutorial repository includes a [compiled binary](https://github.com/viam-labs/tutorial-intermode/blob/main/intermode-base/intermode-model) that is ready to run on 64-bit [Raspberry Pi OS](https://www.raspberrypi.com/software/). If you make changes to the tutorial code, you’ll need to re-compile to create a new binary.

To run the modular resource, first copy the module binary to your Raspberry Pi.

### Configure the Intermode base resource

You will now configure your base. Go to the [machine you added during setup](https://docs.viam.com/tutorials/custom/controlling-an-intermode-rover-canbus/#machine-setup). To make your module accessible to `viam-server`, add it as a local module:

1. Navigate to the **CONFIGURE** tab of your machine’s page.
2. Click the **+** (Create) icon next to your machine part in the left-hand menu and select **Local module**, then **Local module**.
3. Enter a **Name** for this instance of your modular resource, for example `my-custom-base-module`.
4. Enter the module’s [executable path](https://docs.viam.com/build-modules/write-a-driver-module/#3-test-locally). This path must be the absolute path to the executable on your machine’s filesystem. Add the path to where you downloaded the [compiled binary](https://github.com/viam-labs/tutorial-intermode/blob/main/intermode-base/intermode-model).
5. Then, click the **Create** button, and click **Save** in the upper right corner to save your config.

Now that `viam-server` can find the module, you can add the base component it provides for your Intermode base:

1. On the **CONFIGURE** tab of your machine’s page:

- Click the **+** (Create) icon next to your machine part in the left-hand menu and select **Local module**.
   - Then, select **Local component**.
2. On the **Create** menu for a **Local component**:

- Select the type of modular resource provided by your module: [base](https://docs.viam.com/reference/components/base/), from the dropdown menu.
   - Select or enter the model namespace triplet of your modular resource’s model: `viamlabs:tutorial:intermode`.
   - Enter a name for this instance of your base, for example `base-1`. This name must be different from the module name.
3. Click **Create** to create the modular resource provided by the local module.

4. Click **Save** in the top right corner.

For more information on modules and how they work, see the [Create a module](https://docs.viam.com/build-modules/write-a-driver-module/).

### Control the rover

After you configured the base, go to the [**CONTROL**](https://docs.viam.com/monitor/default-interface/#web-ui) tab and expand the base component to view the controls to enable keyboard or discrete control over your machine’s movement.

#### Caution

Be careful, the Intermode is a large and powerful rover - make sure you have the shutoff key in hand for emergencies and make sure your rover has sufficient space to drive around without hitting anyone or anything.

On the **Keyboard** tab, you can toggle the keyboard control to active. With the **Keyboard** toggle active, use **W** and **S** to go forward and back, and **A** and **D** to arc and spin.

Try driving your base around using the WASD keyboard controls.

If you navigate to the **Discrete** tab, you can use movement modes such as `Straight` and `Spin` and different movement types such as `Continuous` and `Discrete` and directions such as `Forwards` and `Backwards`.

If you do not see the base card in the **CONTROL** tab, check the **LOGS** tab for possible setup or configuration errors.

## Full code for the Intermode base modular resource

Check out this [GitHub repository](https://github.com/viam-labs/tutorial-intermode) for the working modular resource implementation example which we use in this tutorial.

## Next steps

Now that you have integrated your rover or mobile base with Viam, you can use the [Viam SDKs](https://docs.viam.com/reference/sdks/) to operate your rover. If your rover has a [`camera`](https://docs.viam.com/reference/components/camera/) or a [`movement_sensor`](https://docs.viam.com/reference/components/movement-sensor/), you can try the following tutorials:

[There should have been a video here but your browser does not seem to support it.\
\
Drive your rover\
\
Use a Viam SDK to program a rover to move in a square.](https://docs.viam.com/try/viam-rover/drive-rover/)

[There should have been a video here but your browser does not seem to support it.\
\
Colored Object Follower\
\
Instructions for detecting and following a colored object with a rover, like a SCUTTLE robot.](https://docs.viam.com/tutorials/services/color-detection-scuttle/)
