- Introduction
- Prerequisites
- Install StepIt on the Microcontroller
- Install StepIt on the Local Computer
- Running the Application
- How to run GitHub Actions locally
StepIt is a project to control stepper motors with a Teensy microcontroller and ROS2. Watch this video
To run StepIt, we need a computer with Ubuntu 24.04. The preferred way to run it is inside a Docker container.
If you want to run StepIt on your host machine, you must install ROS2. Please refer to the document Install ROS2 Jazzy on Ubuntu.
By default, StepIt runs in simulation mode so we do not an need actual hardware to play around with it.
For a real application, we recommend attaching the stepper motors to a Teensy microcontroller 4.0 or 4.1. We can hook the motors in many different ways but we suggest the following hardware configuration.
- 1 x Teensy 4.1 or Teensy 4.0.
- 1 x PiBot multi-stepper motor driver board rev2.3
- 5 x TMC2208
The Teensy is connected to a computer using a USB cable. For a portable application, we can use a Raspberry PI 4.
This step is only required if you use a real hardware, otherwise skip to the following section.
We developed code for the Teensy microcontroller using Visual Studio Code because it provides very good tools to format and validate the code. To achieve this goal, we must install PlatformIO extension which supports different microcontrollers including Arduino. Installing Arduino IDE is not required.
If PlatformIO cannot find the Python interpreter, install the following:
sudo apt install python3-venv
To connect StepIt to a Teensy, you must install a udev rule on your host first. Without this rule, non-root users generally can't access the Teensy's HID interface that the loader/programmer needs.
cd /tmp
wget https://www.pjrc.com/teensy/00-teensy.rules
sudo cp /tmp/00-teensy.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm triggerIf necessary, unplug/replug the Teensy.
To flash the microcontroller code into the Teensy:
- Open VSCode
- Install the extension PlarformIO
- Open the subfolder
stepit_mcuin VSCode - Select the correct device and flash it
The microcontroller is usually shown as /dev/ttyACM0. Remember to update your ROS2 control configuration in stepit.ros2_control.xacro and disable use_dummy.
<hardware>
<plugin>stepit_driver/StepitHardware</plugin>
<param name="use_dummy">false</param>
<param name="usb_port">/dev/ttyACM0</param>
<param name="baud_rate">9600</param>
<param name="timeout">0.2</param>
</hardware>Check out this git repository, including all required submodules.
git clone --recurse-submodules git@github.com:kineticsystem/stepit.git
If you missed the switch --recurse-submodules, you can clone all dependencies with the following commands:
cd stepit
git submodule update --init --recursive
Remember to enable recursion for relevant git commands, such that regular commands recurse into submodules by default.
git config --global submodule.recurse true
Additionally, you should install git pre-commit hooks using the following command:
pre-commit install
The preferred way to build and run StepIt is to use a Docker container. It is defined in docker/docker-compose.yml and driven by the docker/dock.sh script. See docker/README.md for more details.
Important
The docker container provides a default user developer with password developer. That user may run sudo without being asked for it, so that the scripts in bin also work from a non-interactive shell, e.g.
docker exec stepit update.sh.
Build the image and create the container. The script always mounts the repo it belongs to, so it can be called from anywhere:
./docker/dock.sh stepit build
This is also how you pick up a change to the Dockerfile: it rebuilds only the layers that changed, so there is no need to clean first.
Start the container with an interactive shell:
./docker/dock.sh stepit start
The commands below assume you are inside the container (or, if you prefer not to use Docker, directly on a host machine with Ubuntu 24.04 and ROS 2 Jazzy installed).
Inside the container the scripts in bin are on the PATH and aliased, so they can be called from any directory: they always act on the workspace root. Outside the container, call them by their path instead, e.g. ./bin/update.sh.
Install all required dependencies.
update
Run Colcon to build the project.
build
Execute all tests.
test
By default, the application runs with fake motors and a default active trajectory controller. Run the following commands to start StepIt. This will also start up RViz.
source ~/ws/install/setup.bash
ros2 launch robot_bringup launch.py
Open a different terminal (if using Docker, attach to the same running container with ./docker/dock.sh stepit start) and run the following command to rotate joint1 by 6.28 rad clockwise:
ros2 topic pub -1 /joint_trajectory_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory "{
joint_names: [joint1],
points: [
{
positions: [-6.28],
time_from_start: {
sec: 2
}
}
]
}"
To control a trajectory with a sequence of positions and velocities run
ros2 topic pub -1 /joint_trajectory_controller/joint_trajectory trajectory_msgs/msg/JointTrajectory "{
joint_names: ["joint1", "joint2", "joint3", "joint4", "joint5"],
points: [
{
positions: [0, 0, 0, 0, 0],
velocities: [0, 0, 0, 0, 0],
time_from_start: {
sec: 0,
nanosec: 0
}
},
{
positions: [31.4159265358979,37.6991118430775,43.9822971502571,50.2654824574367,56.5486677646163],
velocities: [0, 0, 0, 0, 0],
time_from_start: {
sec: 10,
nanosec: 0
}
},
{
positions: [0, 0, 0, 0, 0],
velocities: [0, 0, 0, 0, 0],
time_from_start: {
sec: 12,
nanosec: 0
}
},
{
positions: [-31.4159265358979,-37.6991118430775,-43.9822971502571,-50.2654824574367,-56.5486677646163],
velocities: [0, 0, 0, 0, 0],
time_from_start: {
sec: 17,
nanosec: 0
}
},
{
positions: [0, 0, 0, 0, 0],
velocities: [0, 0, 0, 0, 0],
time_from_start: {
sec: 20,
nanosec: 0
}
},
]
}"
The trajectory is a list of waypoints, each of them containing the desired position and velocity of each joint at a given time.
Important
Only one controller must be active at a time: velocity_controller, position_controller, or joint_trajectory_controller.
To use the velocity controller, deactivate the current controller before activating another one:
ros2 control set_controller_state joint_trajectory_controller inactive -c /controller_manager
ros2 control set_controller_state velocity_controller active -c /controller_manager
Then run the following commands:
ros2 topic pub -1 /velocity_controller/commands std_msgs/msg/Float64MultiArray "data: [6.28,-6.28,0,0,0]"
Each value is the target velocity, in rad/s, for the corresponding joint listed under velocity_controller.joints in controllers.yaml (currently joint1 through joint5), so the array must have exactly one value per joint.
The controller position_controller is also loaded but inactive. Deactivate any previous controller as per previous note.
ros2 control set_controller_state velocity_controller inactive -c /controller_manager
ros2 control set_controller_state position_controller active -c /controller_manager
ros2 topic pub -1 /position_controller/commands std_msgs/msg/Float64MultiArray "data: [6.28, 6.28, 6.28, 6.28, 6.28]"
At each commit, the GitHub repository runs all available tests using GitHub actions and Industrial CI.
A GitHub action fires up a docker container with Ubuntu 24.04 and ROS2 Jazzy, checks out and builds the code inside the docker container and runs all tests.
Sometimes, it may be desirable to execute the Continuous Integration pipeline locally. This is possible by using Nektos.
First of all, we must create a GitHub token to access the repository. Then, we
must install Nektos act command in the user folder ~/bin as explained in Nektos README.md file. We need an .env file at the root of the repository to define a few global variables required by Industrial CI. Finally, we can run the following command from the same folder:
~/bin/act pull_request --workflows ./.github/workflows/industrial_ci.yml -s GITHUB_TOKEN
