How-to obtain a BNO085 IMU’s attitude and visualize it via ROS

Pika Spark is an Arduino Portenta X8 based micro robot control system combining an unprecedented amount of computing power and interfaces within an extremely small form factor. Additionally, the Pika Spark contains a BNO085 9-DoF IMU which provides both raw access to the internal gyroscope, accelerometer and magnetometer data as well as performs on-chip attitude estimation for directly providing its orientation in quaternion form.

This tutorials explains how to use Pika Spark's onboard BNO805 IMU which exchanges data with the Yocto-Linux-running IMX8 application processor of the Arduino Portenta X8 via SPI and GPIOs such as nCS (for the chip-select signal of the SPI interface), nRST (for resetting the BNO085) and nIRQ (for signalling events from the IMU to the application processor.

An open-source BNO085 user space device driver called pika-spark-bno085-driver is used for both configuring and obtaining measurement data from the BNO085 as well as streaming the received IMU data via ROS messages (sensor_msgs/Imu) for further processing by other ROS nodes. In this tutorial we'll use Rviz2 - a swiss-army knife for visualizing ROS data - for displaying the current orientation of the IMU onboard the Pika Spark.


Rviz2 showing the current orientation of Pika Spark's BNO085 IMU leveraging the rviz_imu_plugin


The preferred way of getting anything done on the Arduino Portenta X8 is by using Docker. So let's start by creating a Dockerfile that builds and installs the pika-spark-bno085-driver in a Docker image that already contains a ROS base image.

FROM docker.io/arm64v8/ros:humble-ros-base

RUN apt-get update && \
    apt-get install -y git && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN mkdir -p /tmp/colcon_ws/src
WORKDIR /tmp/colcon_ws/src
RUN git clone --recursive https://github.com/pika-spark/pika-spark-bno085-driver

WORKDIR /tmp/colcon_ws
RUN . /opt/ros/humble/setup.sh && colcon build --symlink-install

COPY start.sh /
RUN chmod ugo+x /start.sh
ENTRYPOINT ['/start.sh']

As can be seen from the Dockerfile a simple start script (start.sh) is copied into the image which serves to navigate to the location of the BNO085 driver within the container and to run it.

#!/bin/sh
cd /tmp/colcon_ws
. /opt/ros/humble/setup.sh
. install/setup.sh
echo 'Starting pika-spark-bno085-driver ...'
ros2 launch pika_spark_bno085_driver imu.py

In the next step a Docker image shall be built from the Dockerfile using docker build.

docker build --pull --no-cache --tag pika_spark_bno085_driver .

Now its time to enable the GPIOs and SPI interface used for communication between the Arduino Portenta X8's IMX8 application processor and the BNO085 IMU.

GPIO_NIRQ_NUM=131
GPIO_NRST_NUM=86
GPIO_NBOOT_NUM=87

echo $GPIO_NIRQ_NUM > /sys/class/gpio/export
echo $GPIO_NRST_NUM > /sys/class/gpio/export
echo $GPIO_NBOOT_NUM > /sys/class/gpio/export

modprobe spidev
chmod ugo+rw /dev/spidev0.0

As a final step run (docker run) the newly created pika_spark_bno085_driver container passing the SPI interface via --device /dev/spidev0.0 and passing the GPIO interface via mapping the sysfs GPIO interface into the container. If you want to stream network data out of the container (and we do want that, since we want to visualize it via Rviz2 on our development computer) ensure that the X8s network stack is not isolated from the container by passing --network host.

sudo -u fio docker run -it \
  --ulimit nofile=1024:1024 \
  --rm \
  -u 0 --privileged \
  --device /dev/spidev0.0 \
  -v /sys/class/gpio:/sys/class/gpio \
  --network host \
  pika_spark_bno085_driver

You can verify that data is being received on your development PC by checking the output of ros2 topic list and ros2 topic echo /imu.

ros2 topic echo

/imu
/parameter_events
/rosout
ros2 topic echo /imu

header:
stamp:
sec: 1706075938
nanosec: 99494097
frame_id: imu
orientation:
x: -0.00286865234375
y: -0.007080078125
z: -0.46429443359375
w: 0.88568115234375
orientation_covariance:
...

In order to visualize data contained in the /imu topic via Rviz2 first the rviz_imu_plugin needs to be installed.

sudo apt-get install ros-humble-imu-tools

Finally it's time to run Rviz2 with a configuration already tailored for visualizing IMU data.

wget https://raw.githubusercontent.com/pika-spark/pika-spark-bno085-driver/main/config/view_imu.rviz
source /opt/ros/humble/setup.bash
rviz2 -d view_imu.rviz


TL;DR:

In order to simplify running the Pika Spark's IMU and visualizing its data via Rviz2 ready-made bash scripts with integrated error handling and convenience features have been prepared.

On the Arduino Portenta X8 run:

git clone https://github.com/pika-spark/pika-spark-containers
cd pika-spark-containers/ros-imu-bno085
./docker-build.sh
sudo ./docker-run.sh

On your development PC first run:

cd my_colcon_ws/src
git clone --recursive https://github.com/pika-spark/pika-spark-bno085-driver
cd my_colcon_ws
source /opt/ros/humble/setup.bash
colcon build --packages-select pika_spark_bno085_driver

followed by:

sudo apt-get install ros-humble-imu-tools
cd my_colcon_ws
. install/setup.bash
ros2 launch pika_spark_bno085_driver rviz2.py

All the best integrating Pika Spark's IMU data in your application!