Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/ccpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ on:
pull_request:
branches:
- master
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v4
with:
submodules: true
- name: Install dependencies from APT
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/format-checker.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
name: Check Formatting

on: [pull_request]
on:
pull_request:
workflow_dispatch:

jobs:
check-format:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v4
with:
submodules: true
- name: Install dependencies from APT
Expand Down
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,15 @@ Some of our dependencies are team-managed, including the CAN library and the H26
Our codebase is developed for an NVIDIA Jetson TX2, which runs Ubuntu Linux; as such, much
of our code will be Unix-specific.

> ⚠️ The only supported platform is Ubuntu 20.04 LTS. Other versions/distros/platforms may work, but if you want as easy as possible, go with this version.
> ⚠️ The only supported platform is Ubuntu 22.04 LTS. Other versions/distros/platforms may work, but if you want as easy as possible, go with this version.

**Windows users:** You should use either [Windows Subsystem for
Linux](https://docs.microsoft.com/en-us/windows/wsl/about) or a VM with a Linux
distribution installed (Ubuntu recommended). Either should work fine. Whichever you use, install either the VM or WSL2 and follow the Linux instructions. As noted above, **use Ubuntu 20.04**.
distribution installed (Ubuntu recommended). Either should work fine. Whichever you use, install either the VM or WSL2 and follow the Linux instructions. As noted above, **use Ubuntu 22.04**.

**Mac users:** We do not make any effort to support Mac systems. You *may* be able to get things working, but if you try you'll be on your own. It's **highly recommended** for Mac users to use a Linux VM.
**Mac users:** We recommend running an Ubuntu virtual machine via [UTM](https://mac.getutm.app/). After installing the app, set up your VM using [UTM's Ubuntu image](https://mac.getutm.app/gallery/ubuntu-20-04). Please note that UTM only supports the latest version of Ubuntu (22.04).

> ⚠️ For Mac users, we recommend running a Ubuntu virtual machine via [UTM](https://mac.getutm.app/). After installing the app, set up your VM using [UTM's Ubuntu image](https://mac.getutm.app/gallery/ubuntu-20-04). Please note that UTM only supports the latest version of Ubuntu (22.04). Since the codebase is based on an older version of Ubuntu, there may be package errors that you need to manually resolve. For the sake of convenience, we also recommend SSHing into UTM via VSCode's Remote SSH feature. [More info can be found here](https://arteen.linux.ucla.edu/ssh-into-utm-vm.html).

**From here on out, the installation instructions will assume you are using Ubuntu 20.04 LTS**. Windows users should run commands in either their Linux VM or their WSL
**From here on out, the installation instructions will assume you are using Ubuntu 22.04 LTS**. Windows users should run commands in either their Linux VM or their WSL
terminal. For Linux users, we'll assume you're running Ubuntu; users of another
distribution may need to change some instructions (e.g. package managers) depending on
your distro.
Expand All @@ -41,6 +39,14 @@ cd <place to put repository>
git clone https://github.com/huskyroboticsteam/Resurgence/
```

> You may need to set up a SSH key to clone the repo. You can follow the steps below or find more information [here](https://docs.github.com/en/authentication/connecting-to-github-with-ssh)

> Inside your VM, check if there are existing SSH keys by running `ls -al ~/.ssh`, which will list all files inside your .ssh directory, if they exist. Existing public keys are (by default) one of the following: *id_rsa.pub*, *id_ecdsa.pub*, *id_ed25519.pub*.

> To create a new SSH key, run the following command with your Github email address: `ssh-keygen -t ed25519 -C "github_email@example.com"`. You can accept all of the default configurations.

> To add the SSH key to your GitHub account, run the following command, substituting in for your .pub file: `gh ssh-key add ~/.ssh/<file>.pub -t "UTM Linux" --type signing`

Install dependencies in one go:
```bash
cd Resurgence
Expand All @@ -65,6 +71,8 @@ a) Develop within the VM, in which case see "Native Linux" above.
b) Create a shared folder (shared between your computer and VM) and clone the project there. Then use an editor to edit the files on your machine and run them within the VM.

c) Set up the VM as an ssh server (pretty easy) and run VSCode on your machine (not the VM) using the [remote development](https://code.visualstudio.com/docs/remote/ssh) feature.
> For the sake of convenience, we also recommend SSHing into UTM via VSCode's Remote SSH feature. [More info can be found here](https://arteen.linux.ucla.edu/ssh-into-utm-vm.html).
> Remember to run `sudo apt-get install -y openssh-server`.

Of these, (c) probably has the most convenient/usable setup, while (a) is probably the least work.

Expand Down Expand Up @@ -117,7 +125,7 @@ make -j Rover
Launch the appropriate simulator executable for your platform. Then, run the rover code, using the `p` flag to specify a peripheral:

```bash
./Rover -p {none|arm|science|lidar}
./Rover -p {none|arm|science}
```

The programs can be started in any order, it doesn't matter.
Expand Down
11 changes: 9 additions & 2 deletions easy_install.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
#!/bin/bash

sudo apt install -y curl wget
sudo curl -s --compressed "https://huskyroboticsteam.github.io/ubuntu-repo/KEY.gpg" | sudo apt-key add -

# Transfer key
sudo mkdir -p /etc/apt/keyrings/
sudo wget -P /etc/apt/keyrings/ "https://huskyroboticsteam.github.io/ubuntu-repo/KEY.gpg"
sudo gpg --no-default-keyring --keyring ./temp-keyring.gpg --import /etc/apt/keyrings/KEY.gpg
sudo gpg --no-default-keyring --keyring ./temp-keyring.gpg --export --output /etc/apt/keyrings/KEY.gpg --yes
sudo rm temp-keyring.gpg

sudo wget -P /etc/apt/sources.list.d "https://huskyroboticsteam.github.io/ubuntu-repo/husky_robotics.list"
./update_deps.sh

echo "Done installing Resurgence dependencies!"
echo "Done installing Resurgence dependencies!"
16 changes: 0 additions & 16 deletions enable_CAN.sh

This file was deleted.

1 change: 0 additions & 1 deletion rover-config/50-usb-hokuyo-lidar.rules

This file was deleted.

1 change: 0 additions & 1 deletion rover-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ filesystem.

| **File/Directory** | **Location on Rover** | **Description** |
| ----------------- | -------------------- | -------------- |
| `50-usb-hokuyo-lidar.rules` | `/etc/udev/rules.d/` | `udev` rules for making sure we have permissions to access the lidar over USB. |
| `50-rover-cameras.rules` | `/etc/udev/rules.d/` | `udev` rules for making sure cameras have stable IDs. |

# Directions
Expand Down
84 changes: 41 additions & 43 deletions src/CAN/CANMotor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,36 @@ using robot::types::LimitSwitchData;

namespace can::motor {

void initEncoder(deviceserial_t serial, bool invertEncoder, bool zeroEncoder,
int32_t pulsesPerJointRev,
void initEncoder(devicegroup_t group, deviceserial_t serial, bool invertEncoder,
bool zeroEncoder, int32_t pulsesPerJointRev,
std::optional<std::chrono::milliseconds> telemetryPeriod) {
auto motorGroupCode = static_cast<uint8_t>(devicegroup_t::motor);
auto groupCode = static_cast<uint8_t>(group);
CANPacket p;
AssembleEncoderInitializePacket(&p, motorGroupCode, serial, sensor_t::encoder,
invertEncoder, zeroEncoder);
AssembleEncoderInitializePacket(&p, groupCode, serial, sensor_t::encoder, invertEncoder,
zeroEncoder);
sendCANPacket(p);
std::this_thread::sleep_for(1000us);
AssembleEncoderPPJRSetPacket(&p, motorGroupCode, serial, pulsesPerJointRev);
AssembleEncoderPPJRSetPacket(&p, groupCode, serial, pulsesPerJointRev);
sendCANPacket(p);
std::this_thread::sleep_for(1000us);
if (telemetryPeriod) {
scheduleTelemetryPull(std::make_pair(devicegroup_t::motor, serial), telemtype_t::angle,
scheduleTelemetryPull(std::make_pair(group, serial), telemtype_t::angle,
telemetryPeriod.value());
}
}

void initPotentiometer(deviceserial_t serial, int32_t posLo, int32_t posHi, uint16_t adcLo,
uint16_t adcHi,
void initPotentiometer(devicegroup_t group, deviceserial_t serial, int32_t posLo,
int32_t posHi, uint16_t adcLo, uint16_t adcHi,
std::optional<std::chrono::milliseconds> telemetryPeriod) {
CANPacket packet;
auto group = static_cast<uint8_t>(devicegroup_t::motor);
AssemblePotHiSetPacket(&packet, group, serial, adcHi, posHi);
auto groupCode = static_cast<uint8_t>(group);
AssemblePotHiSetPacket(&packet, groupCode, serial, adcHi, posHi);
sendCANPacket(packet);
std::this_thread::sleep_for(1ms);
AssemblePotLoSetPacket(&packet, group, serial, adcLo, posLo);
AssemblePotLoSetPacket(&packet, groupCode, serial, adcLo, posLo);
sendCANPacket(packet);
if (telemetryPeriod) {
scheduleTelemetryPull(std::make_pair(devicegroup_t::motor, serial), telemtype_t::angle,
scheduleTelemetryPull(std::make_pair(group, serial), telemtype_t::angle,
telemetryPeriod.value());
}
}
Expand All @@ -61,26 +61,27 @@ void emergencyStopMotors() {
std::this_thread::sleep_for(1000us);
}

void initMotor(deviceserial_t serial) {
setMotorMode(serial, motormode_t::pwm);
void initMotor(devicegroup_t group, deviceserial_t serial) {
setMotorMode(group, serial, motormode_t::pwm);
std::this_thread::sleep_for(1000us);
}

void setLimitSwitchLimits(deviceserial_t serial, int32_t lo, int32_t hi) {
void setLimitSwitchLimits(devicegroup_t group, deviceserial_t serial, int32_t lo, int32_t hi) {
CANPacket p;
auto motorGroupCode = static_cast<uint8_t>(devicegroup_t::motor);
auto groupCode = static_cast<uint8_t>(group);

// 0 is low limit, 1 is high limit.
AssembleLimSwEncoderBoundPacket(&p, motorGroupCode, serial, 0, lo);
AssembleLimSwEncoderBoundPacket(&p, groupCode, serial, 0, lo);
sendCANPacket(p);
std::this_thread::sleep_for(1ms);
AssembleLimSwEncoderBoundPacket(&p, motorGroupCode, serial, 1, hi);
AssembleLimSwEncoderBoundPacket(&p, groupCode, serial, 1, hi);
sendCANPacket(p);
}

void setMotorPIDConstants(deviceserial_t serial, int32_t kP, int32_t kI, int32_t kD) {
void setMotorPIDConstants(devicegroup_t group, deviceserial_t serial, int32_t kP, int32_t kI,
int32_t kD) {
CANPacket p;
auto motorGroupCode = static_cast<uint8_t>(devicegroup_t::motor);
auto motorGroupCode = static_cast<uint8_t>(group);
AssemblePSetPacket(&p, motorGroupCode, serial, kP);
sendCANPacket(p);
std::this_thread::sleep_for(1ms);
Expand All @@ -92,62 +93,59 @@ void setMotorPIDConstants(deviceserial_t serial, int32_t kP, int32_t kI, int32_t
std::this_thread::sleep_for(1ms);
}

void setMotorMode(deviceserial_t serial, motormode_t mode) {
void setMotorMode(devicegroup_t group, deviceserial_t serial, motormode_t mode) {
CANPacket p;
AssembleModeSetPacket(&p, static_cast<uint8_t>(devicegroup_t::motor), serial,
static_cast<uint8_t>(mode));
AssembleModeSetPacket(&p, static_cast<uint8_t>(group), serial, static_cast<uint8_t>(mode));
sendCANPacket(p);
std::this_thread::sleep_for(1000us);
}

void setMotorPower(deviceserial_t serial, double power) {
void setMotorPower(devicegroup_t group, deviceserial_t serial, double power) {
power = std::min(std::max(power, -1.0), 1.0);
int powerInt = std::round(power * std::numeric_limits<int16_t>::max());
int16_t dutyCycle = static_cast<int16_t>(powerInt);
setMotorPower(serial, dutyCycle);
setMotorPower(group, serial, dutyCycle);
}

void setMotorPower(deviceserial_t serial, int16_t power) {
void setMotorPower(devicegroup_t group, deviceserial_t serial, int16_t power) {
CANPacket p;
AssemblePWMDirSetPacket(&p, static_cast<uint8_t>(devicegroup_t::motor), serial, power);
AssemblePWMDirSetPacket(&p, static_cast<uint8_t>(group), serial, power);
sendCANPacket(p);
}

void setMotorPIDTarget(deviceserial_t serial, int32_t target) {
void setMotorPIDTarget(devicegroup_t group, deviceserial_t serial, int32_t target) {
CANPacket p;
AssemblePIDTargetSetPacket(&p, static_cast<uint8_t>(devicegroup_t::motor), serial, target);
AssemblePIDTargetSetPacket(&p, static_cast<uint8_t>(group), serial, target);
sendCANPacket(p);
}

void setServoPos(deviceserial_t serial, uint8_t servoNum, int32_t angle) {
void setServoPos(devicegroup_t group, deviceserial_t serial, uint8_t servoNum, int32_t angle) {
CANPacket p;
AssemblePCAServoPacket(&p, static_cast<uint8_t>(devicegroup_t::motor), serial, servoNum,
angle);
AssemblePCAServoPacket(&p, static_cast<uint8_t>(group), serial, servoNum, angle);
sendCANPacket(p);
}

DataPoint<int32_t> getMotorPosition(deviceserial_t serial) {
return getDeviceTelemetry(std::make_pair(devicegroup_t::motor, serial),
telemtype_t::angle);
DataPoint<int32_t> getMotorPosition(devicegroup_t group, deviceserial_t serial) {
return getDeviceTelemetry(std::make_pair(group, serial), telemtype_t::angle);
}

void pullMotorPosition(deviceserial_t serial) {
pullDeviceTelemetry(std::make_pair(devicegroup_t::motor, serial), telemtype_t::angle);
void pullMotorPosition(devicegroup_t group, deviceserial_t serial) {
pullDeviceTelemetry(std::make_pair(group, serial), telemtype_t::angle);
}

callbackid_t addLimitSwitchCallback(
deviceserial_t serial,
const std::function<void(deviceserial_t serial,
devicegroup_t group, deviceserial_t serial,
const std::function<void(devicegroup_t group, deviceserial_t serial,
DataPoint<LimitSwitchData> limitSwitchData)>& callback) {
auto id = std::make_pair(devicegroup_t::motor, serial);
auto id = std::make_pair(group, serial);
// wrap callback in lambda to change signature
auto func = [callback](deviceid_t deviceID, telemtype_t,
DataPoint<telemetry_t> telemData) {
if (telemData) {
LimitSwitchData data = telemData.getData();
callback(deviceID.second, {telemData.getTime(), data});
callback(deviceID.first, deviceID.second, {telemData.getTime(), data});
} else {
callback(deviceID.second, {});
callback(deviceID.first, deviceID.second, {});
}
};
return addDeviceTelemetryCallback(id, telemtype_t::limit_switch, func);
Expand Down
Loading