Skip to content

Commit

Permalink
Webui port setup and usability fixes (#13)
Browse files Browse the repository at this point in the history
- allow changing the webui port with `webui.port` param
- support for namespaces in webui (using placeholders from caddy)
- creating `ros.env`, `ros_snap_args` and `manage_ros_env.sh` in `/var/snap/rosbot-xl/common/` for mirroring `rosbot-xl` snap ROS 2 setup to other snaps and to user's shell
- auto-determining the `/dev/ttyUSB*` device used by firmware flasher
- better `README.md`
  • Loading branch information
DominikN authored Jun 11, 2024
1 parent 57ab95c commit ae55d91
Show file tree
Hide file tree
Showing 38 changed files with 583 additions and 483 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.snap
squashfs-root
squashfs-root
test*
136 changes: 55 additions & 81 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,120 +14,98 @@ Install the snap as follows,
snap install rosbot-xl
```

## Setup

Upon installation, depending on your operating system,
you may have to manually connect the snap interface.
You can verify that with the following command,
## Parameters

```bash
# snap connections rosbot-xl
Interface Plug Slot Notes
content[ros-humble-ros-base] rosbot-xl:ros-humble-ros-base ros-humble-ros-base:ros-humble-ros-base -
network rosbot-xl:network :network -
network-bind rosbot-xl:network-bind :network-bind -
raw-usb rosbot-xl:raw-usb :raw-usb manual
shared-memory rosbot-xl:shm-plug rosbot-xl:shm-slot manual
$ sudo snap get rosbot-xl
Key Value
driver {...}
ros-domain-id 123
ros-localhost-only 0
serial-port auto
transport udp
webui {...}
```

The interface `ros-humble-ros-base` must be connected.
### ROS Driver

If it isn't, you can issue the following command,
Parameters for [rosbot_xl_ros](https://github.com/husarion/rosbot_xl_ros) ROS 2 driver available from the snap level are:

```bash
snap connect rosbot-xl:ros-humble-ros-base ros-humble-ros-base:ros-humble-ros-base
Key Value
driver.camera-model (unset)
driver.include-camera-mount True
driver.mecanum True
driver.lidar-model (unset)
driver.namesapce (unset)
```

### Parameters

#### ROS Driver

Depending on your robot hardware,
the snap can be configured through the following parameters:
which can be set as follows, e.g.,

- mecanum
- include-camera-mount
- camera-model
- lidar-model
```bash
snap set rosbot-xl driver.mecanum=True
```

which can be set as follows, e.g.,
### Web UI

```bash
snap set rosbot-xl mecanum=True
Key Value
webui.layout sensors
webui.port 8080
```

To start the ROSbot XL daemon:
The snap has a built-in Web UI that can be launched with:

```bash
sudo snap start --enable rosbot-xl
sudo rosbot-xl.start-web-ui
```

#### ROS envs
By default the UI is available under `http://<ROSBOT_IP>:8080/ui`.

To set `ROS_LOCALHOST_ONLY` and `ROS_DOMAIN_ID` envs use the following parameters:
- ros-localhost-only
- ros-domain-id
Built-in layouts are available here:
- `/var/snap/rosbot-xl/common/foxglove-default.json`
- `/var/snap/rosbot-xl/common/foxglove-sensors.json`

#### DDS Transport
If you want to save your own custom layout, save it in the same directory, eg. in `/var/snap/rosbot-xl/common/foxglove-myui.json` file.

The snap works with the following DDS configurations: `udp` (default), `shm` (shared memory) and `builtin`.
To select the layout run:

```bash
sudo snap set rosbot-xl transport=shm
sudo snap set rosbot-xl webui.layout=myui
```
## Working With Parameters

Shared memory communication is possible only between the instances of ROS 2 nodes launched by the same user. Because the `rosbot-xl` snap daemon runs as `root` to allow the host <> snap communication you need to:

1. Create `/usr/local/etc/shm-only.xml` file:

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>shm_transport</transport_id>
<type>SHM</type>
</transport_descriptor>
</transport_descriptors>

<participant profile_name="SHMParticipant" is_default_profile="true">
<rtps>
<userTransports>
<transport_id>shm_transport</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
</rtps>
</participant>
</profiles>
```
```bash
# set params in rosbot-xl snap
sudo snap set rosbot-xl transport=udp ros-domain-id=123 driver.namespace=abc

2. Run:
# mirror the setup for other snaps running ROS 2:
sudo snap set husarion-depthai $(cat /var/snap/rosbot-xl/common/ros_snap_args)
sudo snap set husarion-rplidar $(cat /var/snap/rosbot-xl/common/ros_snap_args)

```bash
sudo su
source /opt/ros/humble/setup.bash
export FASTRTPS_DEFAULT_PROFILES_FILE=/usr/local/etc/shm-only.xml
```
# to setup the current shell with the same configs:
source /var/snap/rosbot-xl/common/ros.env

and now you should be able to list ROSbot XL ROS 2 topics with:
# ... or install configs with
/var/snap/rosbot-xl/common/manage_ros_env.sh
# and after changing rosbot-xl params open a new terminal, or run:
source ~/.bashrc

```bash
ros2 topic list
ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args --remap __ns:=/${ROS_NAMESPACE}
```

#### DDS Transport (custom)
## Custom DDS Transport

If you want to use a custom FastDDS transport place it under the `/var/snap/rosbot-xl/common/` path (eg. `/var/snap/rosbot-xl/common/my-fastdds.xml`), and set the parameter:

```bash
sudo snap set rosbot-xl fastdds-default-profiles-file=my-fastdds.xml
sudo snap set rosbot-xl transport=my-fastdds
```

### STM32 Firmware flashing
## STM32 Firmware flashing

```bash
sudo snap connect rosbot-xl:raw-usb
sudo snap set rosbot-xl serial-port=/dev/ttyUSB0 # /dev/ttyUSBDB default - the serial port to which the digital board is connected
sudo snap set rosbot-xl serial-port=/dev/ttyUSB0 # 'auto' is default option - the serial port to which the digital board is connected
sudo rosbot-xl.flash
```

Expand All @@ -145,17 +123,13 @@ To display logs from a snap logger
journalctl -t rosbot-xl
```

## Use

The snap ships a daemon which is automatically started once the snap is installed and configured.
Therefore, there is nothing else to do than to start using your rosbot-xl.

> **Note**
> This snap is part of an integrated snaps deployment.
>
> Other recommended snaps to be installed are,
>
> - [sllidar-ros2](https://snapcraft.io/sllidar-ros2)
> - [husarion-rplidar](https://snapcraft.io/husarion-rplidar)
> - [husarion-depthai](https://snapcraft.io/husarion-depthai)
> - [rosbot-xl-teleop](https://snapcraft.io/rosbot-xl-teleop)
> - [rosbot-xl-nav](https://snapcraft.io/rosbot-xl-nav)
<!-- [sllidar-ros2](https://snapcraft.io/sllidar-ros2) -->
26 changes: 26 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,29 @@ teleop:
#!/bin/bash
# export FASTRTPS_DEFAULT_PROFILES_FILE=$(pwd)/shm-only.xml
ros2 run teleop_twist_keyboard teleop_twist_keyboard # --ros-args -r __ns:=/robot

iterate:
#!/bin/bash -e
start_time=$(date +%s)

echo "Starting script..."

sudo snap remove rosbot-xl
sudo rm -rf squashfs-root/
sudo rm -rf rosbot-xl*.snap
export SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=1
snapcraft clean
snapcraft
unsquashfs rosbot-xl*.snap
sudo snap try squashfs-root/
sudo snap connect rosbot-xl:raw-usb
sudo snap connect rosbot-xl:shm-plug rosbot-xl:shm-slot

end_time=$(date +%s)
duration=$(( end_time - start_time ))

hours=$(( duration / 3600 ))
minutes=$(( (duration % 3600) / 60 ))
seconds=$(( duration % 60 ))

printf "Script completed in %02d:%02d:%02d (hh:mm:ss)\n" $hours $minutes $seconds
19 changes: 4 additions & 15 deletions snap/hooks/configure
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
#!/bin/sh -e
#!/bin/bash -e

# The configure hook is called every time one the following actions happen:
# - initial snap installation
# - snap refresh
# - whenever the user runs snap set|unset to change a configuration option

# Define a function to log and echo messages
log_and_echo() {
local message="$1"
# Log the message with logger
logger -t "${SNAP_NAME}" "configure hook: $message"
# Echo the message to standard error
echo >&2 "$message"
}

log() {
local message="$1"
# Log the message with logger
logger -t "${SNAP_NAME}" "configure hook: $message"
}
source $SNAP/usr/bin/utils.sh

$SNAP/usr/bin/configure_hook_ros.sh

Expand Down Expand Up @@ -56,3 +43,5 @@ for service in daemon web-ui web-ws; do
log "Restarted ${SNAP_NAME}.${service}"
fi
done

# $SNAP/usr/bin/foxglove-set-namespace.sh
2 changes: 1 addition & 1 deletion snap/hooks/connect-plug-ros-humble-ros-base
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh -e
#!/bin/bash -e

# now we can start the service
# if snapctl services ${SNAP_NAME}.${SNAP_NAME} | grep -q inactive; then
Expand Down
2 changes: 1 addition & 1 deletion snap/hooks/disconnect-plug-ros-humble-ros-base
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh -e
#!/bin/bash -e

logger -t ${SNAP_NAME} "Plug 'ros-humble-ros-base' disconnected"
snapctl stop --disable ${SNAP_NAME}.daemon 2>&1 || true
13 changes: 6 additions & 7 deletions snap/hooks/install
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
#!/bin/sh -e
#!/bin/bash -e

# Define a function to log messages
log() {
local message="$1"
# Log the message with logger
logger -t "${SNAP_NAME}" "install hook: $message"
}
source $SNAP/usr/bin/utils.sh

$SNAP/usr/bin/install_hook_ros.sh

Expand All @@ -16,8 +12,11 @@ snapctl set driver.include-camera-mount=True
snapctl set driver.camera-model!
snapctl set driver.lidar-model!
snapctl set driver.namespace! # unset

snapctl set webui.layout=default
snapctl set serial-port="/dev/ttyUSBDB"
snapctl set webui.port=8080

snapctl set serial-port="auto"

if ! snapctl is-connected raw-usb; then
log "Plug 'raw-usb' isn't connected, please run:"
Expand Down
12 changes: 9 additions & 3 deletions snap/local/Caddyfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# file_server
# }

:80 {
:{$UI_PORT} {
# Enable HTTP/2 over clear text (h2c)
# protocols h2c

Expand All @@ -27,13 +27,19 @@

handle @ipv6Client {
vars full_host [{http.request.host}]
redir /ui /?ds=foxglove-websocket&ds.url=ws%3A%2F%2F%5B{http.request.host}%5D%2Fws
redir /ui /?ds=foxglove-websocket&ds.url=ws%3A%2F%2F%5B{http.request.host}%5D%3A{http.request.port}%2Fws
}

# Handle all other requests (from non-IPv6 clients)
handle {
vars full_host {http.request.host}
redir /ui /?ds=foxglove-websocket&ds.url=ws%3A%2F%2F{http.request.host}%2Fws
redir /ui /?ds=foxglove-websocket&ds.url=ws%3A%2F%2F{http.request.host}%3A{http.request.port}%2Fws
}

# Handle envs in foxglove templates
templates {
mime "text/html"
# mime "application/json" "text/plain" "text/html"
}

# Handle all requests
Expand Down
3 changes: 2 additions & 1 deletion snap/local/bridge_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ def generate_launch_description():
parameters=[{
'port': 8765,
'address': '127.0.0.1',
'capabilities': ['clientPublish', 'connectionGraph', 'assets']
'capabilities': ['clientPublish', 'parameters', 'parametersSubscribe', 'services', 'connectionGraph', 'assets']
# 'capabilities': ['clientPublish', 'connectionGraph', 'assets']
}],
output='screen'
)
Expand Down
2 changes: 1 addition & 1 deletion snap/local/bridge_launcher.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/bash
#!/bin/bash -e

# ros2 run foxglove_bridge foxglove_bridge --ros-args \
# -p port:=8766 \
Expand Down
20 changes: 12 additions & 8 deletions snap/local/caddy_launcher.sh
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
#!/usr/bin/bash
#!/bin/bash -e

# Define a function to log and echo messages
log_and_echo() {
local message="$1"
# Log the message with logger
logger -t "${SNAP_NAME}" "caddy_launcher: $message"
# Echo the message to standard error
echo >&2 "$message"
}
source $SNAP/usr/bin/utils.sh

# Define the source and destination directories
site_path="$SNAP/usr/local/www/"
site_tmp_path="$SNAP_DATA/www/"
layout="$(snapctl get webui.layout)"
# layout="layout"
export UI_PORT="$(snapctl get webui.port)"
log_and_echo "Using ${SNAP_COMMON}/foxglove-$layout.json"

# Ensure the destination directory exists
Expand All @@ -33,5 +29,13 @@ echo "${index_html_content/"$replace_pattern"/$replace_value}" > $index_html_pat
sed -i "s|<div id=\"root\"></div>|<script>\nlocalStorage.clear();sessionStorage.clear();\n</script>\n&|" $index_html_path

# Define a function to log and echo messages
# Retrieve the driver.namespace value
namespace=$(snapctl get driver.namespace)

# Check if the namespace is set and not empty
if [ -n "$namespace" ]; then
# Set the environment variable
export NAMESPACE="/$namespace"
fi
caddy run --config $SNAP/usr/share/$SNAP_NAME/config/Caddyfile --adapter caddyfile

Loading

0 comments on commit ae55d91

Please sign in to comment.