hackerbot 0.2.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.
- hackerbot-0.2.0/LICENSE +21 -0
- hackerbot-0.2.0/PKG-INFO +67 -0
- hackerbot-0.2.0/README.md +53 -0
- hackerbot-0.2.0/pyproject.toml +44 -0
- hackerbot-0.2.0/setup.cfg +4 -0
- hackerbot-0.2.0/src/hackerbot/__init__.py +33 -0
- hackerbot-0.2.0/src/hackerbot/arm/__init__.py +77 -0
- hackerbot-0.2.0/src/hackerbot/arm/gripper.py +55 -0
- hackerbot-0.2.0/src/hackerbot/base/__init__.py +223 -0
- hackerbot-0.2.0/src/hackerbot/base/maps.py +147 -0
- hackerbot-0.2.0/src/hackerbot/core.py +120 -0
- hackerbot-0.2.0/src/hackerbot/examples/keyboard_teleop_examples/AI_ELITE_teleop.py +219 -0
- hackerbot-0.2.0/src/hackerbot/examples/keyboard_teleop_examples/AI_PRO_teleop.py +180 -0
- hackerbot-0.2.0/src/hackerbot/examples/keyboard_teleop_examples/arm_teleop.py +230 -0
- hackerbot-0.2.0/src/hackerbot/examples/keyboard_teleop_examples/base_teleop.py +206 -0
- hackerbot-0.2.0/src/hackerbot/examples/keyboard_teleop_examples/head_teleop.py +170 -0
- hackerbot-0.2.0/src/hackerbot/head/__init__.py +61 -0
- hackerbot-0.2.0/src/hackerbot/head/eyes.py +41 -0
- hackerbot-0.2.0/src/hackerbot/utils/hackerbot_helper.py +142 -0
- hackerbot-0.2.0/src/hackerbot/utils/serial_helper.py +156 -0
- hackerbot-0.2.0/src/hackerbot.egg-info/PKG-INFO +67 -0
- hackerbot-0.2.0/src/hackerbot.egg-info/SOURCES.txt +23 -0
- hackerbot-0.2.0/src/hackerbot.egg-info/dependency_links.txt +1 -0
- hackerbot-0.2.0/src/hackerbot.egg-info/requires.txt +2 -0
- hackerbot-0.2.0/src/hackerbot.egg-info/top_level.txt +1 -0
hackerbot-0.2.0/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Hackerbot Industries LLC
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
hackerbot-0.2.0/PKG-INFO
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: hackerbot
|
3
|
+
Version: 0.2.0
|
4
|
+
Summary: This module contains the setup for the hackerbot python package.
|
5
|
+
Author-email: Allen Chien <allen71090@gmail.com>
|
6
|
+
License-Expression: MIT
|
7
|
+
Project-URL: Homepage, https://github.com/hackerbotindustries/hackerbot-python-package
|
8
|
+
Requires-Python: >=3.11
|
9
|
+
Description-Content-Type: text/markdown
|
10
|
+
License-File: LICENSE
|
11
|
+
Requires-Dist: pyserial
|
12
|
+
Requires-Dist: pytest
|
13
|
+
Dynamic: license-file
|
14
|
+
|
15
|
+
|
16
|
+
# Hackerbot Python Package
|
17
|
+
|
18
|
+
Hackerbot python package (`hackerbot-python-package`) is a project that includes modules for controlling and managing the Hackerbot system.
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Follow these steps to clone the repository and set up the required dependencies.
|
23
|
+
|
24
|
+
### 1. Clone the Repository
|
25
|
+
Use SSH to clone the repository:
|
26
|
+
```bash
|
27
|
+
https://github.com/hackerbotindustries/hackerbot-python-package.git
|
28
|
+
```
|
29
|
+
This will create a directory named `hackerbot-python-package` and download all necessary files.
|
30
|
+
|
31
|
+
### 2. Navigate to the Modules Directory
|
32
|
+
Move into the `hackerbot_modules` directory:
|
33
|
+
```bash
|
34
|
+
cd hackerbot-python-package/
|
35
|
+
```
|
36
|
+
|
37
|
+
### 3. Install Dependencies
|
38
|
+
Install the `hackerbot` package using `pip`:
|
39
|
+
```bash
|
40
|
+
pip install .
|
41
|
+
```
|
42
|
+
This will install the package locally for your Python environment.
|
43
|
+
|
44
|
+
## Usage
|
45
|
+
Once installed, you can import `hackerbot` in your Python scripts:
|
46
|
+
```python
|
47
|
+
import hackerbot
|
48
|
+
```
|
49
|
+
|
50
|
+
### 4. Testing
|
51
|
+
To run the unit tests run:
|
52
|
+
```bash
|
53
|
+
cd tests/unit_tests
|
54
|
+
pytest
|
55
|
+
```
|
56
|
+
|
57
|
+
## Troubleshooting
|
58
|
+
If you run into issues with the installation, try the following:
|
59
|
+
- Ensure you're using a virtual environment:
|
60
|
+
```bash
|
61
|
+
python3 -m venv venv
|
62
|
+
source venv/bin/activate
|
63
|
+
```
|
64
|
+
- Upgrade `pip` before installation:
|
65
|
+
```bash
|
66
|
+
pip install --upgrade pip
|
67
|
+
```
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
# Hackerbot Python Package
|
3
|
+
|
4
|
+
Hackerbot python package (`hackerbot-python-package`) is a project that includes modules for controlling and managing the Hackerbot system.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Follow these steps to clone the repository and set up the required dependencies.
|
9
|
+
|
10
|
+
### 1. Clone the Repository
|
11
|
+
Use SSH to clone the repository:
|
12
|
+
```bash
|
13
|
+
https://github.com/hackerbotindustries/hackerbot-python-package.git
|
14
|
+
```
|
15
|
+
This will create a directory named `hackerbot-python-package` and download all necessary files.
|
16
|
+
|
17
|
+
### 2. Navigate to the Modules Directory
|
18
|
+
Move into the `hackerbot_modules` directory:
|
19
|
+
```bash
|
20
|
+
cd hackerbot-python-package/
|
21
|
+
```
|
22
|
+
|
23
|
+
### 3. Install Dependencies
|
24
|
+
Install the `hackerbot` package using `pip`:
|
25
|
+
```bash
|
26
|
+
pip install .
|
27
|
+
```
|
28
|
+
This will install the package locally for your Python environment.
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
Once installed, you can import `hackerbot` in your Python scripts:
|
32
|
+
```python
|
33
|
+
import hackerbot
|
34
|
+
```
|
35
|
+
|
36
|
+
### 4. Testing
|
37
|
+
To run the unit tests run:
|
38
|
+
```bash
|
39
|
+
cd tests/unit_tests
|
40
|
+
pytest
|
41
|
+
```
|
42
|
+
|
43
|
+
## Troubleshooting
|
44
|
+
If you run into issues with the installation, try the following:
|
45
|
+
- Ensure you're using a virtual environment:
|
46
|
+
```bash
|
47
|
+
python3 -m venv venv
|
48
|
+
source venv/bin/activate
|
49
|
+
```
|
50
|
+
- Upgrade `pip` before installation:
|
51
|
+
```bash
|
52
|
+
pip install --upgrade pip
|
53
|
+
```
|
@@ -0,0 +1,44 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2025 Hackerbot Industries LLC
|
3
|
+
#
|
4
|
+
# This source code is licensed under the MIT license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
#
|
7
|
+
# Created By: Allen Chien
|
8
|
+
# Created: April 2025
|
9
|
+
# Updated: 2025.04.01
|
10
|
+
#
|
11
|
+
# This module contains the setup details for the hackerbot python package.
|
12
|
+
#
|
13
|
+
# Special thanks to the following for their code contributions to this codebase:
|
14
|
+
# Allen Chien - https://github.com/AllenChienXXX
|
15
|
+
################################################################################
|
16
|
+
|
17
|
+
|
18
|
+
[project]
|
19
|
+
name = "hackerbot"
|
20
|
+
version = "0.2.0"
|
21
|
+
description = "This module contains the setup for the hackerbot python package."
|
22
|
+
authors = [
|
23
|
+
{ name = "Allen Chien", email = "allen71090@gmail.com" }
|
24
|
+
]
|
25
|
+
license = "MIT"
|
26
|
+
readme = "README.md"
|
27
|
+
requires-python = ">=3.11"
|
28
|
+
dependencies = [
|
29
|
+
"pyserial",
|
30
|
+
"pytest",
|
31
|
+
]
|
32
|
+
|
33
|
+
[project.urls]
|
34
|
+
Homepage = "https://github.com/hackerbotindustries/hackerbot-python-package"
|
35
|
+
|
36
|
+
[build-system]
|
37
|
+
requires = ["setuptools>=61.0"]
|
38
|
+
build-backend = "setuptools.build_meta"
|
39
|
+
|
40
|
+
[tool.setuptools]
|
41
|
+
package-dir = {"" = "src"}
|
42
|
+
|
43
|
+
[tool.setuptools.packages.find]
|
44
|
+
where = ["src"]
|
@@ -0,0 +1,33 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2025 Hackerbot Industries LLC
|
3
|
+
#
|
4
|
+
# This source code is licensed under the MIT license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
#
|
7
|
+
# Created By: Allen Chien
|
8
|
+
# Created: April 2025
|
9
|
+
# Updated: 2025.04.08
|
10
|
+
#
|
11
|
+
# This is the file for the hackerbot package. It imports
|
12
|
+
# and initialized the sub components
|
13
|
+
#
|
14
|
+
# Special thanks to the following for their code contributions to this codebase:
|
15
|
+
# Allen Chien - https://github.com/AllenChienXXX
|
16
|
+
################################################################################
|
17
|
+
|
18
|
+
|
19
|
+
from .core import Core
|
20
|
+
from .base import Base
|
21
|
+
from .head import Head
|
22
|
+
from .arm import Arm
|
23
|
+
from .utils.hackerbot_helper import HackerbotHelper
|
24
|
+
|
25
|
+
class Hackerbot(HackerbotHelper):
|
26
|
+
def __init__(self, port=None, board=None, model=None,verbose_mode=False):
|
27
|
+
super().__init__(port, board, verbose_mode)
|
28
|
+
# Share self (which is a HackerbotHelper) with subsystems
|
29
|
+
self.core = Core(controller=self)
|
30
|
+
self.base = Base(controller=self)
|
31
|
+
self.head = Head(controller=self)
|
32
|
+
self.arm = Arm(controller=self)
|
33
|
+
# TODO based on model decide which subsystems to initialize
|
@@ -0,0 +1,77 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2025 Hackerbot Industries LLC
|
3
|
+
#
|
4
|
+
# This source code is licensed under the MIT license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
#
|
7
|
+
# Created By: Allen Chien
|
8
|
+
# Created: April 2025
|
9
|
+
# Updated: 2025.04.07
|
10
|
+
#
|
11
|
+
# This module contains the Arm component of the hackerbot
|
12
|
+
#
|
13
|
+
# Special thanks to the following for their code contributions to this codebase:
|
14
|
+
# Allen Chien - https://github.com/AllenChienXXX
|
15
|
+
################################################################################
|
16
|
+
|
17
|
+
|
18
|
+
from hackerbot.utils.hackerbot_helper import HackerbotHelper
|
19
|
+
from .gripper import Gripper
|
20
|
+
|
21
|
+
class Arm():
|
22
|
+
def __init__(self, controller: HackerbotHelper):
|
23
|
+
self._controller = controller
|
24
|
+
self.idle_mode = True
|
25
|
+
|
26
|
+
self.setup()
|
27
|
+
self.gripper = Gripper(self._controller)
|
28
|
+
|
29
|
+
def setup(self):
|
30
|
+
if not self._controller._arm_attached:
|
31
|
+
self._controller.log_warning("Arm not attached, can't control arm.")
|
32
|
+
|
33
|
+
def move_joint(self, joint_id, angle, speed):
|
34
|
+
"""
|
35
|
+
Moves a single joint of the robotic arm to a specified angle at a given speed.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
joint_id (int): Joint number from 1 to 6. Joint 1 is the base and is in order moving up the arm.
|
39
|
+
angle (float): Angle for the specified joint. Valid range is -165.0 to 165.0 degrees for joints 1 to 5 and -175.0 to 175.0 for joint 6.
|
40
|
+
speed (int): Speed at which the arm moves to the new position. Valid range is 0 to 100.
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
bool: True if the movement command was successfully sent, False if an error occurred.
|
44
|
+
"""
|
45
|
+
try:
|
46
|
+
self._controller.send_raw_command(f"A_ANGLE,{joint_id},{angle},{speed}")
|
47
|
+
# Not fetching json response since machine mode not implemented
|
48
|
+
return True
|
49
|
+
except Exception as e:
|
50
|
+
self._controller.log_error(f"Error in arm:move_joint: {e}")
|
51
|
+
return False
|
52
|
+
|
53
|
+
def move_joints(self, j_agl_1, j_agl_2, j_agl_3, j_agl_4, j_agl_5, j_agl_6, speed):
|
54
|
+
"""
|
55
|
+
Moves all six joints of the robotic arm to specified angles at a given speed.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
j_agl_1 (float): Angle for joint 1, base joint. Valid range is -165.0 to 165.0 degrees.
|
59
|
+
j_agl_2 (float): Angle for joint 2. Valid range is -165.0 to 165.0 degrees.
|
60
|
+
j_agl_3 (float): Angle for joint 3. Valid range is -165.0 to 165.0 degrees.
|
61
|
+
j_agl_4 (float): Angle for joint 4. Valid range is -165.0 to 165.0 degrees.
|
62
|
+
j_agl_5 (float): Angle for joint 5. Valid range is -165.0 to 165.0 degrees.
|
63
|
+
j_agl_6 (float): Angle for joint 6. Valid range is -175.0 to 175.0 degrees.
|
64
|
+
speed (int): Speed at which the arm moves to the new positions. Valid range is 0 to 100.
|
65
|
+
|
66
|
+
Returns:
|
67
|
+
bool: True if the movement command was successfully sent, False if an error occurred.
|
68
|
+
"""
|
69
|
+
try:
|
70
|
+
self._controller.send_raw_command(f"A_ANGLES,{j_agl_1},{j_agl_2},{j_agl_3},{j_agl_4},{j_agl_5},{j_agl_6},{speed}")
|
71
|
+
# Not fetching json response since machine mode not implemented
|
72
|
+
return True
|
73
|
+
except Exception as e:
|
74
|
+
self._controller.log_error(f"Error in arm:move_joints: {e}")
|
75
|
+
return False
|
76
|
+
|
77
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2025 Hackerbot Industries LLC
|
3
|
+
#
|
4
|
+
# This source code is licensed under the MIT license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
#
|
7
|
+
# Created By: Allen Chien
|
8
|
+
# Created: April 2025
|
9
|
+
# Updated: 2025.04.07
|
10
|
+
#
|
11
|
+
# This module contains the Gripper component of the hackerbot
|
12
|
+
#
|
13
|
+
# Special thanks to the following for their code contributions to this codebase:
|
14
|
+
# Allen Chien - https://github.com/AllenChienXXX
|
15
|
+
################################################################################
|
16
|
+
|
17
|
+
|
18
|
+
from hackerbot.utils.hackerbot_helper import HackerbotHelper
|
19
|
+
|
20
|
+
class Gripper(HackerbotHelper):
|
21
|
+
def __init__(self, controller: HackerbotHelper):
|
22
|
+
self._controller = controller
|
23
|
+
|
24
|
+
def calibrate(self):
|
25
|
+
"""
|
26
|
+
Calibrates the gripper by sending a raw calibration command.
|
27
|
+
|
28
|
+
Returns:
|
29
|
+
bool: True if the calibration command was successfully sent, False if an error occurred.
|
30
|
+
"""
|
31
|
+
try:
|
32
|
+
self._controller.send_raw_command("A_CAL")
|
33
|
+
# Not fetching json response since machine mode not implemented
|
34
|
+
return True
|
35
|
+
except Exception as e:
|
36
|
+
self._controller.log_error(f"Error in gripper:calibrate: {e}")
|
37
|
+
return False
|
38
|
+
|
39
|
+
def open(self):
|
40
|
+
try:
|
41
|
+
self._controller.send_raw_command("A_OPEN")
|
42
|
+
# Not fetching json response since machine mode not implemented
|
43
|
+
return True
|
44
|
+
except Exception as e:
|
45
|
+
self._controller.log_error(f"Error in gripper:open: {e}")
|
46
|
+
return False
|
47
|
+
|
48
|
+
def close(self):
|
49
|
+
try:
|
50
|
+
self._controller.send_raw_command("A_CLOSE")
|
51
|
+
# Not fetching json response since machine mode not implemented
|
52
|
+
return True
|
53
|
+
except Exception as e:
|
54
|
+
self._controller.log_error(f"Error in gripper:close: {e}")
|
55
|
+
return False
|
@@ -0,0 +1,223 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2025 Hackerbot Industries LLC
|
3
|
+
#
|
4
|
+
# This source code is licensed under the MIT license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
#
|
7
|
+
# Created By: Allen Chien
|
8
|
+
# Created: April 2025
|
9
|
+
# Updated: 2025.04.08
|
10
|
+
#
|
11
|
+
# This module contains the Base component of the hackerbot
|
12
|
+
#
|
13
|
+
# Special thanks to the following for their code contributions to this codebase:
|
14
|
+
# Allen Chien - https://github.com/AllenChienXXX
|
15
|
+
################################################################################
|
16
|
+
|
17
|
+
|
18
|
+
from hackerbot.utils.hackerbot_helper import HackerbotHelper
|
19
|
+
from .maps import Maps
|
20
|
+
import time
|
21
|
+
|
22
|
+
class Base():
|
23
|
+
def __init__(self, controller: HackerbotHelper):
|
24
|
+
"""
|
25
|
+
Initialize Core component with HackerbotHelper object
|
26
|
+
|
27
|
+
:param controller: HackerbotHelper object
|
28
|
+
"""
|
29
|
+
self._controller = controller
|
30
|
+
self.initialize() # Call before any action is done on the base
|
31
|
+
|
32
|
+
self.maps = Maps(controller)
|
33
|
+
|
34
|
+
self._future_completed = False
|
35
|
+
self._docked = True # Default to true, assume always start from charger
|
36
|
+
|
37
|
+
|
38
|
+
def initialize(self):
|
39
|
+
try:
|
40
|
+
self._controller.send_raw_command("B_INIT")
|
41
|
+
self._controller._base_init = True
|
42
|
+
# Not fetching json response since machine mode not implemented
|
43
|
+
return True
|
44
|
+
except Exception as e:
|
45
|
+
self._controller.log_error(f"Error in base:initialize: {e}")
|
46
|
+
raise Exception(f"Error in initialize: {e}")
|
47
|
+
|
48
|
+
def set_mode(self, mode):
|
49
|
+
try:
|
50
|
+
self._controller.send_raw_command(f"B_MODE,{mode}")
|
51
|
+
# Not fetching json response since machine mode not implemented
|
52
|
+
return True
|
53
|
+
except Exception as e:
|
54
|
+
self._controller.log_error(f"Error in base:set_mode: {e}")
|
55
|
+
return False
|
56
|
+
|
57
|
+
def status(self):
|
58
|
+
try:
|
59
|
+
self._controller.send_raw_command("B_STATUS")
|
60
|
+
time.sleep(0.1)
|
61
|
+
response = self._controller.get_json_from_command("status")
|
62
|
+
if response is None:
|
63
|
+
raise Exception("Status command failed")
|
64
|
+
|
65
|
+
if response.get("left_set_speed") == 0 and response.get("right_set_speed") == 0:
|
66
|
+
self._future_completed = True
|
67
|
+
else:
|
68
|
+
self._future_completed = False
|
69
|
+
|
70
|
+
# Parse and return relevant fields
|
71
|
+
parsed_data = {
|
72
|
+
"timestamp": response.get("timestamp"),
|
73
|
+
"left_encoder": response.get("left_encoder"),
|
74
|
+
"right_encoder": response.get("right_encoder"),
|
75
|
+
"left_speed": response.get("left_speed"),
|
76
|
+
"right_speed": response.get("right_speed"),
|
77
|
+
"left_set_speed": response.get("left_set_speed"),
|
78
|
+
"right_set_speed": response.get("right_set_speed"),
|
79
|
+
"wall_tof": response.get("wall_tof"),
|
80
|
+
}
|
81
|
+
return parsed_data
|
82
|
+
except Exception as e:
|
83
|
+
self._controller.log_error(f"Error in base:status: {e}")
|
84
|
+
return None
|
85
|
+
|
86
|
+
def start(self, block=True):
|
87
|
+
try:
|
88
|
+
self._controller.send_raw_command("B_START")
|
89
|
+
# Not fetching json response since machine mode not implemented
|
90
|
+
self._controller._driver_mode = True
|
91
|
+
if self._docked:
|
92
|
+
time.sleep(2)
|
93
|
+
self._docked = False
|
94
|
+
self._wait_until_completed(block=block)
|
95
|
+
|
96
|
+
return True
|
97
|
+
except Exception as e:
|
98
|
+
self._controller.log_error(f"Error in base:start: {e}")
|
99
|
+
return False
|
100
|
+
|
101
|
+
def quickmap(self, block=True):
|
102
|
+
"""
|
103
|
+
Start the quick mapping process.
|
104
|
+
|
105
|
+
This function sends a command to the base to initiate the quick mapping process.
|
106
|
+
It first checks the system status to ensure all components are ready. If
|
107
|
+
the quick mapping command is successfully sent, the function returns True.
|
108
|
+
In case of any errors, it logs the error message and returns False.
|
109
|
+
|
110
|
+
:return: True if the quick mapping command is successful, False otherwise.
|
111
|
+
"""
|
112
|
+
try:
|
113
|
+
self._controller.send_raw_command("B_QUICKMAP")
|
114
|
+
time.sleep(0.1)
|
115
|
+
# Not fetching json response since machine mode not implemented
|
116
|
+
self._wait_until_completed(block=block)
|
117
|
+
return True
|
118
|
+
except Exception as e:
|
119
|
+
self._controller.log_error(f"Error in base:quickmap: {e}")
|
120
|
+
return False
|
121
|
+
|
122
|
+
def dock(self, block=True):
|
123
|
+
"""
|
124
|
+
Dock the base to the docking station.
|
125
|
+
|
126
|
+
This function sends a command to the base to initiate the docking process.
|
127
|
+
It first checks the system status to ensure all components are ready. If
|
128
|
+
the docking command is successfully sent, the function returns True.
|
129
|
+
In case of any errors, it logs the error message and returns False.
|
130
|
+
|
131
|
+
:return: True if the docking command is successful, False otherwise.
|
132
|
+
"""
|
133
|
+
try:
|
134
|
+
self._controller.send_raw_command("B_DOCK")
|
135
|
+
time.sleep(3)
|
136
|
+
# Not fetching json response since machine mode not implemented
|
137
|
+
self._wait_until_completed(block=block)
|
138
|
+
self._docked = True
|
139
|
+
self._controller._driver_mode = False
|
140
|
+
return True
|
141
|
+
except Exception as e:
|
142
|
+
self._controller.log_error(f"Error in base:dock: {e}")
|
143
|
+
return False
|
144
|
+
|
145
|
+
|
146
|
+
def kill(self):
|
147
|
+
"""
|
148
|
+
Kill the base's movement. This is a blocking call and will not return until the base is stopped.
|
149
|
+
After calling this method, the base will not be able to move until start() is called again.
|
150
|
+
:return: True if successful, False otherwise.
|
151
|
+
"""
|
152
|
+
try:
|
153
|
+
self._controller.send_raw_command("B_KILL")
|
154
|
+
self._controller._base_init = False
|
155
|
+
# Not fetching json response since machine mode not implemented
|
156
|
+
return True
|
157
|
+
except Exception as e:
|
158
|
+
self._controller.log_error(f"Error in base:kill: {e}")
|
159
|
+
return False
|
160
|
+
|
161
|
+
def trigger_bump(self, left, right):
|
162
|
+
"""
|
163
|
+
Trigger the bump sensors on the base.
|
164
|
+
|
165
|
+
:param left: 0 or 1 to disable or enable the left bump sensor.
|
166
|
+
:param right: 0 or 1 to disable or enable the right bump sensor.
|
167
|
+
:return: True if the command is successful, False if it fails.
|
168
|
+
"""
|
169
|
+
left = 1 if True else 0
|
170
|
+
right = 1 if True else 0
|
171
|
+
try:
|
172
|
+
self._controller.send_raw_command("B_BUMP, {0}, {1}".format(left, right))
|
173
|
+
# Not fetching json response since machine mode not implemented
|
174
|
+
return True
|
175
|
+
except Exception as e:
|
176
|
+
self._controller.log_error(f"Error in base:trigger_bump: {e}")
|
177
|
+
return False
|
178
|
+
|
179
|
+
def drive(self, l_vel, a_vel, block=True):
|
180
|
+
"""
|
181
|
+
Set the base velocity.
|
182
|
+
|
183
|
+
:param l_vel: Linear velocity in mm/s. Positive is forward, negative is backward.
|
184
|
+
:param a_vel: Angular velocity in degrees/s. Positive is counterclockwise, negative is clockwise.
|
185
|
+
:return: True if the command is successful, False if it fails.
|
186
|
+
"""
|
187
|
+
try:
|
188
|
+
if not self._controller._driver_mode:
|
189
|
+
self.start()
|
190
|
+
self._controller.send_raw_command(f"B_DRIVE,{l_vel},{a_vel}")
|
191
|
+
time.sleep(0.1)
|
192
|
+
response = self._controller.get_json_from_command("drive")
|
193
|
+
if response is None:
|
194
|
+
raise Exception("Drive command failed")
|
195
|
+
self._wait_until_completed(block=block)
|
196
|
+
return True
|
197
|
+
except Exception as e:
|
198
|
+
self._controller.log_error(f"Error in base:drive: {e}")
|
199
|
+
return False
|
200
|
+
|
201
|
+
def _wait_until_completed(self, block=True):
|
202
|
+
if not block:
|
203
|
+
return
|
204
|
+
while not self._future_completed:
|
205
|
+
self.status()
|
206
|
+
# print(self.status())
|
207
|
+
self._future_completed = False
|
208
|
+
|
209
|
+
def destroy(self, auto_dock=False):
|
210
|
+
"""
|
211
|
+
Clean up and shut down the base.
|
212
|
+
|
213
|
+
This method kills the base's movement and optionally docks it before
|
214
|
+
destroying the controller. If `auto_dock` is set to True, the base will
|
215
|
+
dock before the destruction process.
|
216
|
+
|
217
|
+
:param auto_dock: If True, the base will dock before being destroyed. Defaults to False.
|
218
|
+
"""
|
219
|
+
self.kill()
|
220
|
+
if auto_dock:
|
221
|
+
time.sleep(3.0)
|
222
|
+
self.dock(block=False)
|
223
|
+
self._controller.destroy()
|