mobipick-labs-docker-gui 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mobipick_labs_docker_gui-0.1.0/MANIFEST.in +2 -0
- mobipick_labs_docker_gui-0.1.0/PKG-INFO +202 -0
- mobipick_labs_docker_gui-0.1.0/README.md +176 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/__init__.py +7 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/__main__.py +9 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/ansi.py +58 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/cli.py +53 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/config.py +206 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/log_widget.py +74 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/main_window.py +3257 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/process_tab.py +118 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/__init__.py +0 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/clean.bash +102 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/config/docker_cp_image_tag.yaml +30 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/config/gui_settings.yaml +59 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/config/worlds.yaml +1 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/docker-compose.yml +57 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/scripts/.gitkeep +0 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/PKG-INFO +202 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/SOURCES.txt +25 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/dependency_links.txt +1 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/entry_points.txt +2 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/not-zip-safe +1 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/requires.txt +5 -0
- mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/top_level.txt +1 -0
- mobipick_labs_docker_gui-0.1.0/pyproject.toml +45 -0
- mobipick_labs_docker_gui-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mobipick-labs-docker-gui
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: PyQt5 desktop controller for the Mobipick Labs Docker simulation
|
|
5
|
+
Author: Mobipick Labs
|
|
6
|
+
License: Proprietary
|
|
7
|
+
Project-URL: Homepage, https://github.com/openai/mobipick_labs_docker_gui
|
|
8
|
+
Keywords: mobipick,docker,gui,ros,simulation
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: Other/Proprietary License
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
20
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: PyQt5>=5.15
|
|
24
|
+
Requires-Dist: PyYAML>=6.0
|
|
25
|
+
Requires-Dist: importlib-resources>=5.0; python_version < "3.9"
|
|
26
|
+
|
|
27
|
+
# Mobipick Labs Docker GUI
|
|
28
|
+
|
|
29
|
+
The Mobipick Labs Docker GUI is a PyQt5 desktop application that orchestrates the
|
|
30
|
+
Docker-based Mobipick Labs robotics simulation. Instead of manually invoking
|
|
31
|
+
`docker compose` yourself, you launch the `mobipick-labs-docker-gui` command (or
|
|
32
|
+
`python -m mobipick_gui`) and drive the bring-up,
|
|
33
|
+
monitoring, and shutdown of the simulation through an interactive interface.
|
|
34
|
+
The GUI reads the bundled configuration files, runs Docker commands on your
|
|
35
|
+
behalf, and streams live logs so you can follow what is happening in each
|
|
36
|
+
container.
|
|
37
|
+
|
|
38
|
+
<img src="doc/mobipick_labs_docker_gui.png" alt="mobipick tables sim and real" width="420">
|
|
39
|
+
|
|
40
|
+
## Repository layout
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
├── gui.py # Legacy CLI shim that forwards to the packaged entry point
|
|
44
|
+
├── mobipick_gui/
|
|
45
|
+
│ ├── resources/ # Bundled compose file, default configs, helper scripts
|
|
46
|
+
│ └── … # PyQt5 widgets, process orchestration, and helpers
|
|
47
|
+
├── MANIFEST.in # Source distribution manifest
|
|
48
|
+
└── pyproject.toml # Packaging metadata for PyPI distribution
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The compose file is **not** intended to be executed directly. The GUI manages it
|
|
52
|
+
for you by spawning `docker compose` subprocesses, supervising their lifecycle,
|
|
53
|
+
and performing cleanup logic when you close the application.
|
|
54
|
+
|
|
55
|
+
## Prerequisites
|
|
56
|
+
|
|
57
|
+
* Ubuntu Linux (tested on versions 20.04, 22.04, and 24.04)
|
|
58
|
+
* Python 3.8+ with PyQt5 available (e.g. `pip install PyQt5`).
|
|
59
|
+
* Docker Engine and the Docker Compose plugin accessible to your user.
|
|
60
|
+
* Access to the Mobipick Labs image repository (for example
|
|
61
|
+
`ozkrelo/mobipick_labs:noetic`).
|
|
62
|
+
* An X11 server that allows the containers to create GUI windows. The GUI
|
|
63
|
+
issues the required `xhost` commands automatically when needed.
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
- Install Docker Engine (`docker.io`) and ensure it is running.
|
|
68
|
+
```bash
|
|
69
|
+
sudo apt update && sudo apt install docker.io
|
|
70
|
+
sudo systemctl enable docker
|
|
71
|
+
sudo systemctl start docker
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- Configure Docker to run without sudo:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
sudo usermod -aG docker $USER
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Then log out and back in.
|
|
81
|
+
|
|
82
|
+
- Install the Mobipick Labs GUI from PyPI (this also installs the package dependencies):
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install mobipick-labs-docker-gui
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- Install the Docker Compose plugin and pull the Mobipick Labs image.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
sudo apt install docker-compose-plugin
|
|
92
|
+
# Verify that the Compose plugin is available
|
|
93
|
+
docker compose version
|
|
94
|
+
# pull mobipick labs docker image from docker hub
|
|
95
|
+
docker pull ozkrelo/mobipick_labs:noetic
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- Optional but strongly recommended if you have an NVIDIA graphics card: install [nvidia-docker2](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/nvidia-docker.html). After installation, restart Docker and test with:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
docker run --rm --gpus all nvidia/cuda:12.4.1-base nvidia-smi
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Note: If you run Mobipick Labs on the CPU, the simulation will be very slow.
|
|
105
|
+
|
|
106
|
+
## Launching the GUI
|
|
107
|
+
|
|
108
|
+
1. Clone the repository *or* install the package from PyPI.
|
|
109
|
+
1. Start the application:
|
|
110
|
+
```bash
|
|
111
|
+
mobipick-labs-docker-gui
|
|
112
|
+
```
|
|
113
|
+
1. When the window opens, use the top row of buttons to bring up ROS core,
|
|
114
|
+
start or stop the simulator, toggle RViz/RQt, or open a Docker-backed
|
|
115
|
+
terminal. The GUI ensures the correct container sequence is followed.
|
|
116
|
+
|
|
117
|
+
You can interrupt the GUI with <kbd>Ctrl</kbd>+<kbd>C</kbd> in the launch
|
|
118
|
+
terminal; the application traps the signal, stops the running containers, and
|
|
119
|
+
then exits gracefully.
|
|
120
|
+
|
|
121
|
+
### Command-line options
|
|
122
|
+
|
|
123
|
+
The CLI accepts a single verbosity switch that controls how much diagnostic
|
|
124
|
+
information the GUI prints to its log tabs and the launch terminal:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
mobipick-labs-docker-gui --verbose # Same as -v or --v
|
|
128
|
+
mobipick-labs-docker-gui -v 3 # Maximum verbosity
|
|
129
|
+
mobipick-labs-docker-gui -v 1 # Quietest mode (default)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
You can also pass through any Qt-specific arguments (for example `-platform`)
|
|
133
|
+
after the GUI options; they are forwarded automatically to `QApplication`.
|
|
134
|
+
|
|
135
|
+
## Understanding the GUI workflow
|
|
136
|
+
|
|
137
|
+
* **Process supervision:** Each button spawns a `QProcess` that executes a
|
|
138
|
+
Docker command (`docker compose up`, `docker compose exec`, `docker cp`, etc.).
|
|
139
|
+
Environment variables from `mobipick_gui/resources/config/gui_settings.yaml` ensure the commands run
|
|
140
|
+
with consistent settings (for example `COMPOSE_IGNORE_ORPHANS=1`).
|
|
141
|
+
* **State polling:** Timers defined in `config/gui_settings.yaml` periodically
|
|
142
|
+
inspect Docker to reflect whether the ROS core, simulator, RViz, or RQt
|
|
143
|
+
containers are alive before updating the button states.
|
|
144
|
+
* **Log streaming:** Every subprocess pipes its stdout/stderr into a dedicated
|
|
145
|
+
tab, colourised via `mobipick_gui/ansi.py` so you can tail the container logs
|
|
146
|
+
without leaving the GUI.
|
|
147
|
+
* **Graceful shutdown:** When you exit, the GUI stops active containers in a
|
|
148
|
+
safe order, runs `clean.bash` (bundled in `mobipick_gui/resources/`) to remove
|
|
149
|
+
temporary resources, and only then closes the window.
|
|
150
|
+
|
|
151
|
+
## Configuring the GUI
|
|
152
|
+
|
|
153
|
+
All customisation lives in the `mobipick_gui/resources/config/` directory. You
|
|
154
|
+
can copy these files and adapt them to your workflow. When running from an
|
|
155
|
+
installed package the directory is read-only; export the environment variable
|
|
156
|
+
`MOBIPICK_GUI_DATA_ROOT` and point it at a writable copy of the resources if you
|
|
157
|
+
need to override the defaults.
|
|
158
|
+
|
|
159
|
+
* **`config/gui_settings.yaml`** – Controls UI behaviour such as window geometry
|
|
160
|
+
and log styling, defines timer intervals, button colours, terminal launcher
|
|
161
|
+
settings, and Docker environment variables. Most keys mirror the defaults
|
|
162
|
+
declared in `mobipick_gui/config.py` so you can override just the values you
|
|
163
|
+
need.
|
|
164
|
+
* **`config/worlds.yaml`** – Lists the world configurations that populate the
|
|
165
|
+
drop-down selector when launching the simulator. Edit or append entries to
|
|
166
|
+
expose additional Gazebo worlds shipped in your Mobipick Labs Docker image.
|
|
167
|
+
* **`config/docker_cp_image_tag.yaml`** – Declares optional `docker cp`
|
|
168
|
+
synchronisation rules keyed by image name. Host-to-container copies run
|
|
169
|
+
automatically after the container starts, while container-to-host copies are
|
|
170
|
+
triggered by the "Execute Docker cp" button inside the GUI.
|
|
171
|
+
|
|
172
|
+
## Working with the compose file
|
|
173
|
+
|
|
174
|
+
Although `docker-compose.yml` lives in the repository, the GUI is responsible for
|
|
175
|
+
translating user actions into compose commands. Typical sequences are:
|
|
176
|
+
|
|
177
|
+
1. **ROS core toggle:** `docker compose up roscore` starts the lightweight
|
|
178
|
+
orchestration container. The GUI remembers the container name and watches for
|
|
179
|
+
it to become healthy before enabling the simulator button.
|
|
180
|
+
2. **Simulator toggle:** `docker compose up mobipick-run` launches the main
|
|
181
|
+
Gazebo environment. When you stop it, the GUI optionally synchronises files
|
|
182
|
+
defined in `docker_cp_image_tag.yaml` and then calls `docker compose stop`
|
|
183
|
+
with a configurable timeout.
|
|
184
|
+
3. **Visualization tools:** RViz and RQt are launched with `docker compose run`
|
|
185
|
+
so each tool receives its own tabbed log stream.
|
|
186
|
+
|
|
187
|
+
Because the GUI tracks container state, you should avoid running the compose
|
|
188
|
+
file manually in parallel—it can confuse the state machine and lead to orphaned
|
|
189
|
+
containers. If you need a manual clean slate, run `mobipick_gui/resources/clean.bash`
|
|
190
|
+
with the GUI closed to remove stopped containers and networks.
|
|
191
|
+
|
|
192
|
+
## Tips and troubleshooting
|
|
193
|
+
|
|
194
|
+
* Verify that Docker commands succeed from your shell before launching the GUI;
|
|
195
|
+
it executes the same binaries with your current user.
|
|
196
|
+
* If the GUI cannot discover your Mobipick Labs image, adjust the
|
|
197
|
+
`images.discovery_filters` list in `mobipick_gui/resources/config/gui_settings.yaml`.
|
|
198
|
+
* When experimenting with new Gazebo worlds or launch files, consider adding a
|
|
199
|
+
custom button tab via `mobipick_gui/process_tab.py` so you can track logs in
|
|
200
|
+
the same window.
|
|
201
|
+
* Logs are retained up to `log.max_block_count` lines per tab. Lower the value
|
|
202
|
+
if you experience sluggishness on resource-constrained machines.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Mobipick Labs Docker GUI
|
|
2
|
+
|
|
3
|
+
The Mobipick Labs Docker GUI is a PyQt5 desktop application that orchestrates the
|
|
4
|
+
Docker-based Mobipick Labs robotics simulation. Instead of manually invoking
|
|
5
|
+
`docker compose` yourself, you launch the `mobipick-labs-docker-gui` command (or
|
|
6
|
+
`python -m mobipick_gui`) and drive the bring-up,
|
|
7
|
+
monitoring, and shutdown of the simulation through an interactive interface.
|
|
8
|
+
The GUI reads the bundled configuration files, runs Docker commands on your
|
|
9
|
+
behalf, and streams live logs so you can follow what is happening in each
|
|
10
|
+
container.
|
|
11
|
+
|
|
12
|
+
<img src="doc/mobipick_labs_docker_gui.png" alt="mobipick tables sim and real" width="420">
|
|
13
|
+
|
|
14
|
+
## Repository layout
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
├── gui.py # Legacy CLI shim that forwards to the packaged entry point
|
|
18
|
+
├── mobipick_gui/
|
|
19
|
+
│ ├── resources/ # Bundled compose file, default configs, helper scripts
|
|
20
|
+
│ └── … # PyQt5 widgets, process orchestration, and helpers
|
|
21
|
+
├── MANIFEST.in # Source distribution manifest
|
|
22
|
+
└── pyproject.toml # Packaging metadata for PyPI distribution
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The compose file is **not** intended to be executed directly. The GUI manages it
|
|
26
|
+
for you by spawning `docker compose` subprocesses, supervising their lifecycle,
|
|
27
|
+
and performing cleanup logic when you close the application.
|
|
28
|
+
|
|
29
|
+
## Prerequisites
|
|
30
|
+
|
|
31
|
+
* Ubuntu Linux (tested on versions 20.04, 22.04, and 24.04)
|
|
32
|
+
* Python 3.8+ with PyQt5 available (e.g. `pip install PyQt5`).
|
|
33
|
+
* Docker Engine and the Docker Compose plugin accessible to your user.
|
|
34
|
+
* Access to the Mobipick Labs image repository (for example
|
|
35
|
+
`ozkrelo/mobipick_labs:noetic`).
|
|
36
|
+
* An X11 server that allows the containers to create GUI windows. The GUI
|
|
37
|
+
issues the required `xhost` commands automatically when needed.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
- Install Docker Engine (`docker.io`) and ensure it is running.
|
|
42
|
+
```bash
|
|
43
|
+
sudo apt update && sudo apt install docker.io
|
|
44
|
+
sudo systemctl enable docker
|
|
45
|
+
sudo systemctl start docker
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- Configure Docker to run without sudo:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
sudo usermod -aG docker $USER
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Then log out and back in.
|
|
55
|
+
|
|
56
|
+
- Install the Mobipick Labs GUI from PyPI (this also installs the package dependencies):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install mobipick-labs-docker-gui
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- Install the Docker Compose plugin and pull the Mobipick Labs image.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
sudo apt install docker-compose-plugin
|
|
66
|
+
# Verify that the Compose plugin is available
|
|
67
|
+
docker compose version
|
|
68
|
+
# pull mobipick labs docker image from docker hub
|
|
69
|
+
docker pull ozkrelo/mobipick_labs:noetic
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- Optional but strongly recommended if you have an NVIDIA graphics card: install [nvidia-docker2](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/nvidia-docker.html). After installation, restart Docker and test with:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
docker run --rm --gpus all nvidia/cuda:12.4.1-base nvidia-smi
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Note: If you run Mobipick Labs on the CPU, the simulation will be very slow.
|
|
79
|
+
|
|
80
|
+
## Launching the GUI
|
|
81
|
+
|
|
82
|
+
1. Clone the repository *or* install the package from PyPI.
|
|
83
|
+
1. Start the application:
|
|
84
|
+
```bash
|
|
85
|
+
mobipick-labs-docker-gui
|
|
86
|
+
```
|
|
87
|
+
1. When the window opens, use the top row of buttons to bring up ROS core,
|
|
88
|
+
start or stop the simulator, toggle RViz/RQt, or open a Docker-backed
|
|
89
|
+
terminal. The GUI ensures the correct container sequence is followed.
|
|
90
|
+
|
|
91
|
+
You can interrupt the GUI with <kbd>Ctrl</kbd>+<kbd>C</kbd> in the launch
|
|
92
|
+
terminal; the application traps the signal, stops the running containers, and
|
|
93
|
+
then exits gracefully.
|
|
94
|
+
|
|
95
|
+
### Command-line options
|
|
96
|
+
|
|
97
|
+
The CLI accepts a single verbosity switch that controls how much diagnostic
|
|
98
|
+
information the GUI prints to its log tabs and the launch terminal:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
mobipick-labs-docker-gui --verbose # Same as -v or --v
|
|
102
|
+
mobipick-labs-docker-gui -v 3 # Maximum verbosity
|
|
103
|
+
mobipick-labs-docker-gui -v 1 # Quietest mode (default)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
You can also pass through any Qt-specific arguments (for example `-platform`)
|
|
107
|
+
after the GUI options; they are forwarded automatically to `QApplication`.
|
|
108
|
+
|
|
109
|
+
## Understanding the GUI workflow
|
|
110
|
+
|
|
111
|
+
* **Process supervision:** Each button spawns a `QProcess` that executes a
|
|
112
|
+
Docker command (`docker compose up`, `docker compose exec`, `docker cp`, etc.).
|
|
113
|
+
Environment variables from `mobipick_gui/resources/config/gui_settings.yaml` ensure the commands run
|
|
114
|
+
with consistent settings (for example `COMPOSE_IGNORE_ORPHANS=1`).
|
|
115
|
+
* **State polling:** Timers defined in `config/gui_settings.yaml` periodically
|
|
116
|
+
inspect Docker to reflect whether the ROS core, simulator, RViz, or RQt
|
|
117
|
+
containers are alive before updating the button states.
|
|
118
|
+
* **Log streaming:** Every subprocess pipes its stdout/stderr into a dedicated
|
|
119
|
+
tab, colourised via `mobipick_gui/ansi.py` so you can tail the container logs
|
|
120
|
+
without leaving the GUI.
|
|
121
|
+
* **Graceful shutdown:** When you exit, the GUI stops active containers in a
|
|
122
|
+
safe order, runs `clean.bash` (bundled in `mobipick_gui/resources/`) to remove
|
|
123
|
+
temporary resources, and only then closes the window.
|
|
124
|
+
|
|
125
|
+
## Configuring the GUI
|
|
126
|
+
|
|
127
|
+
All customisation lives in the `mobipick_gui/resources/config/` directory. You
|
|
128
|
+
can copy these files and adapt them to your workflow. When running from an
|
|
129
|
+
installed package the directory is read-only; export the environment variable
|
|
130
|
+
`MOBIPICK_GUI_DATA_ROOT` and point it at a writable copy of the resources if you
|
|
131
|
+
need to override the defaults.
|
|
132
|
+
|
|
133
|
+
* **`config/gui_settings.yaml`** – Controls UI behaviour such as window geometry
|
|
134
|
+
and log styling, defines timer intervals, button colours, terminal launcher
|
|
135
|
+
settings, and Docker environment variables. Most keys mirror the defaults
|
|
136
|
+
declared in `mobipick_gui/config.py` so you can override just the values you
|
|
137
|
+
need.
|
|
138
|
+
* **`config/worlds.yaml`** – Lists the world configurations that populate the
|
|
139
|
+
drop-down selector when launching the simulator. Edit or append entries to
|
|
140
|
+
expose additional Gazebo worlds shipped in your Mobipick Labs Docker image.
|
|
141
|
+
* **`config/docker_cp_image_tag.yaml`** – Declares optional `docker cp`
|
|
142
|
+
synchronisation rules keyed by image name. Host-to-container copies run
|
|
143
|
+
automatically after the container starts, while container-to-host copies are
|
|
144
|
+
triggered by the "Execute Docker cp" button inside the GUI.
|
|
145
|
+
|
|
146
|
+
## Working with the compose file
|
|
147
|
+
|
|
148
|
+
Although `docker-compose.yml` lives in the repository, the GUI is responsible for
|
|
149
|
+
translating user actions into compose commands. Typical sequences are:
|
|
150
|
+
|
|
151
|
+
1. **ROS core toggle:** `docker compose up roscore` starts the lightweight
|
|
152
|
+
orchestration container. The GUI remembers the container name and watches for
|
|
153
|
+
it to become healthy before enabling the simulator button.
|
|
154
|
+
2. **Simulator toggle:** `docker compose up mobipick-run` launches the main
|
|
155
|
+
Gazebo environment. When you stop it, the GUI optionally synchronises files
|
|
156
|
+
defined in `docker_cp_image_tag.yaml` and then calls `docker compose stop`
|
|
157
|
+
with a configurable timeout.
|
|
158
|
+
3. **Visualization tools:** RViz and RQt are launched with `docker compose run`
|
|
159
|
+
so each tool receives its own tabbed log stream.
|
|
160
|
+
|
|
161
|
+
Because the GUI tracks container state, you should avoid running the compose
|
|
162
|
+
file manually in parallel—it can confuse the state machine and lead to orphaned
|
|
163
|
+
containers. If you need a manual clean slate, run `mobipick_gui/resources/clean.bash`
|
|
164
|
+
with the GUI closed to remove stopped containers and networks.
|
|
165
|
+
|
|
166
|
+
## Tips and troubleshooting
|
|
167
|
+
|
|
168
|
+
* Verify that Docker commands succeed from your shell before launching the GUI;
|
|
169
|
+
it executes the same binaries with your current user.
|
|
170
|
+
* If the GUI cannot discover your Mobipick Labs image, adjust the
|
|
171
|
+
`images.discovery_filters` list in `mobipick_gui/resources/config/gui_settings.yaml`.
|
|
172
|
+
* When experimenting with new Gazebo worlds or launch files, consider adding a
|
|
173
|
+
custom button tab via `mobipick_gui/process_tab.py` so you can track logs in
|
|
174
|
+
the same window.
|
|
175
|
+
* Logs are retained up to `log.max_block_count` lines per tab. Lower the value
|
|
176
|
+
if you experience sluggishness on resource-constrained machines.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""ANSI escape code utilities."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import html
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
SGR_RE = re.compile(r'\x1b\[((?:\d+;)*\d*)m')
|
|
8
|
+
OSC_SEQ_RE = re.compile(r'\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)')
|
|
9
|
+
CSI_SEQ_RE = re.compile(r'\x1b\[[0-9;?]*[ -/]*[@-~]')
|
|
10
|
+
|
|
11
|
+
COLOR_MAP = {
|
|
12
|
+
30: '#000000', 31: '#ff5555', 32: '#50fa7b', 33: '#f1fa8c',
|
|
13
|
+
34: '#bd93f9', 35: '#ff79c6', 36: '#8be9fd', 37: '#bbbbbb',
|
|
14
|
+
90: '#666666', 91: '#ff6e6e', 92: '#69ff94', 93: '#ffffa5',
|
|
15
|
+
94: '#d6acff', 95: '#ff92df', 96: '#a4ffff', 97: '#ffffff'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def ansi_to_html(chunk: str) -> str:
|
|
20
|
+
"""Convert ANSI escape sequences to HTML."""
|
|
21
|
+
text = html.escape(chunk)
|
|
22
|
+
span_stack, out = [], []
|
|
23
|
+
i = 0
|
|
24
|
+
for m in SGR_RE.finditer(text):
|
|
25
|
+
out.append(text[i:m.start()])
|
|
26
|
+
params = m.group(1) or '0'
|
|
27
|
+
if params == '0':
|
|
28
|
+
while span_stack:
|
|
29
|
+
out.append('</span>')
|
|
30
|
+
span_stack.pop()
|
|
31
|
+
i = m.end()
|
|
32
|
+
continue
|
|
33
|
+
styles = []
|
|
34
|
+
for p in params.split(';'):
|
|
35
|
+
try:
|
|
36
|
+
code = int(p)
|
|
37
|
+
except ValueError:
|
|
38
|
+
continue
|
|
39
|
+
if code == 1:
|
|
40
|
+
styles.append('font-weight:bold')
|
|
41
|
+
elif code in COLOR_MAP:
|
|
42
|
+
styles.append(f'color:{COLOR_MAP[code]}')
|
|
43
|
+
elif code == 39:
|
|
44
|
+
styles.append('color:#ffffff')
|
|
45
|
+
elif code == 22:
|
|
46
|
+
styles.append('font-weight:normal')
|
|
47
|
+
if styles:
|
|
48
|
+
out.append(f"<span style=\"{' ;'.join(styles)}\">")
|
|
49
|
+
span_stack.append('</span>')
|
|
50
|
+
i = m.end()
|
|
51
|
+
out.append(text[i:])
|
|
52
|
+
while span_stack:
|
|
53
|
+
out.append(span_stack.pop())
|
|
54
|
+
res = ''.join(out)
|
|
55
|
+
return res.replace('\r\n', '\n').replace('\r', '\n').replace('\n', '<br>')
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
__all__ = ['ansi_to_html', 'CSI_SEQ_RE', 'OSC_SEQ_RE']
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Command-line entry points for the Mobipick Labs GUI."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import signal
|
|
6
|
+
import sys
|
|
7
|
+
from typing import Sequence
|
|
8
|
+
|
|
9
|
+
from PyQt5.QtWidgets import QApplication
|
|
10
|
+
|
|
11
|
+
from . import MainWindow, trigger_sigint
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
15
|
+
parser = argparse.ArgumentParser(description='Mobipick Labs Control GUI')
|
|
16
|
+
parser.add_argument(
|
|
17
|
+
'-v',
|
|
18
|
+
'--v',
|
|
19
|
+
'--verbose',
|
|
20
|
+
dest='verbosity',
|
|
21
|
+
nargs='?',
|
|
22
|
+
const=3,
|
|
23
|
+
default=1,
|
|
24
|
+
type=int,
|
|
25
|
+
choices=[1, 2, 3],
|
|
26
|
+
help='Verbosity level (1=min, 3=max). If no value provided defaults to 3.',
|
|
27
|
+
)
|
|
28
|
+
return parser
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
32
|
+
"""Run the Qt application."""
|
|
33
|
+
|
|
34
|
+
if argv is None:
|
|
35
|
+
argv = sys.argv[1:]
|
|
36
|
+
|
|
37
|
+
parser = _build_parser()
|
|
38
|
+
parsed_args, qt_args = parser.parse_known_args(list(argv))
|
|
39
|
+
verbosity = parsed_args.verbosity or 1
|
|
40
|
+
|
|
41
|
+
app = QApplication([sys.argv[0]] + qt_args)
|
|
42
|
+
window = MainWindow(verbosity=verbosity)
|
|
43
|
+
window.show()
|
|
44
|
+
|
|
45
|
+
def _handle_sigint(_sig, _frame):
|
|
46
|
+
trigger_sigint()
|
|
47
|
+
|
|
48
|
+
signal.signal(signal.SIGINT, _handle_sigint)
|
|
49
|
+
|
|
50
|
+
return app.exec_()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
__all__ = ['main']
|