Skip to content

Commit 4e09113

Browse files
committedDec 31, 2024
Feat: creat get_servo_info service using PyLX-16A lib
1 parent e9173d6 commit 4e09113

7 files changed

+171
-4
lines changed
 

‎CMakeLists.txt

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
project(ros2_lx16a_driver)
3+
4+
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
5+
add_compile_options(-Wall -Wextra -Wpedantic)
6+
endif()
7+
8+
# find dependencies
9+
find_package(ament_cmake REQUIRED)
10+
find_package(rosidl_default_generators REQUIRED)
11+
find_package(rclpy REQUIRED)
12+
13+
# Generate interfaces
14+
rosidl_generate_interfaces(${PROJECT_NAME}
15+
"srv/GetServoInfo.srv"
16+
)
17+
18+
# Install Python modules
19+
ament_python_install_package(src)
20+
21+
# Install entry points (Python scripts)
22+
install(
23+
PROGRAMS
24+
src/lx16a_node.py
25+
DESTINATION lib/${PROJECT_NAME}
26+
)
27+
28+
if(BUILD_TESTING)
29+
find_package(ament_lint_auto REQUIRED)
30+
# the following line skips the linter which checks for copyrights
31+
# comment the line when a copyright and license is added to all source files
32+
set(ament_cmake_copyright_FOUND TRUE)
33+
# the following line skips cpplint (only works in a git repo)
34+
# comment the line when this package is in a git repo and when
35+
# a copyright and license is added to all source files
36+
set(ament_cmake_cpplint_FOUND TRUE)
37+
ament_lint_auto_find_test_dependencies()
38+
endif()
39+
40+
ament_package()

‎README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://github.com/srmainwaring/curio/blob/baec5d6d82454d7f4859479c7d481657b1890d09/curio_base/src/lx16a_driver.cpp
2+
3+
https://github.com/ethanlipson/PyLX-16A/blob/master/documentation.md

‎package.xml

100755100644
+5-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
<license>BSD3</license>
99

1010
<buildtool_depend>ament_cmake</buildtool_depend>
11+
<buildtool_depend>rosidl_default_generators</buildtool_depend>
12+
<build_depend>rosidl_default_generators</build_depend>
13+
<build_depend>rclpy</build_depend>
14+
<exec_depend>rosidl_default_runtime</exec_depend>
1115
<exec_depend>rclpy</exec_depend>
12-
<exec_depend>serial</exec_depend>
1316

14-
<export>
15-
<build_type>ament_python</build_type>
16-
</export>
17+
<member_of_group>rosidl_interface_packages</member_of_group>
1718
</package>

‎src/__init__.py

Whitespace-only changes.

‎src/lx16a_node.py

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env python3
2+
import rclpy
3+
from rclpy.node import Node
4+
from pylx16a.lx16a import LX16A
5+
from ros2_lx16a_driver.srv import GetServoInfo
6+
7+
class LX16AController(Node):
8+
def __init__(self):
9+
super().__init__('lx16a_controller')
10+
11+
# Initialisation du bus LX-16A
12+
try:
13+
LX16A.initialize("/dev/ttyUSB0") # Remplacez par votre port série
14+
self.servos = {}
15+
except Exception as e:
16+
self.get_logger().error(f"Erreur d'initialisation de la communication : {e}")
17+
self.destroy_node()
18+
return
19+
20+
# Création du service GetServoInfo
21+
self.srv = self.create_service(GetServoInfo, '/get_servo_info', self.handle_get_servo_info)
22+
23+
self.get_logger().info('Nœud LX-16A prêt.')
24+
25+
def get_servo(self, servo_id):
26+
"""Retourne une instance de servo donnée, la crée si nécessaire."""
27+
if servo_id not in self.servos:
28+
try:
29+
self.servos[servo_id] = LX16A(servo_id)
30+
self.get_logger().info(f"Servo {servo_id} ajouté.")
31+
except Exception as e:
32+
self.get_logger().error(f"Erreur lors de l'ajout du servo {servo_id} : {e}")
33+
return None
34+
return self.servos[servo_id]
35+
36+
def handle_get_servo_info(self, request, response):
37+
"""Service pour obtenir les informations détaillées d'un servo."""
38+
servo_id = int(request.id) # ID du servo demandé
39+
servo = self.get_servo(servo_id)
40+
41+
if servo is None:
42+
self.get_logger().error(f"Servo {servo_id} non disponible.")
43+
return response # Laisse la réponse vide si le servo n'est pas trouvé
44+
45+
try:
46+
# Récupération des informations du servo
47+
response.angle_offset = int(servo.get_angle_offset())
48+
response.angle_min = int(servo.get_angle_limits()[0])
49+
response.angle_max = int(servo.get_angle_limits()[1])
50+
response.voltage_min = float(servo.get_vin_limits()[0])
51+
response.voltage_max = float(servo.get_vin_limits()[1])
52+
response.temperature_limit = float(servo.get_temp_limit())
53+
motor_mode = servo.is_motor_mode(poll_hardware=True)
54+
response.motor_mode = motor_mode
55+
if motor_mode:
56+
response.motor_speed = servo.get_motor_speed()
57+
response.torque_enabled = servo.is_torque_enabled()
58+
response.led_enabled = servo.is_led_power_on()
59+
response.led_error_temp = servo.get_led_error_triggers()[0]
60+
response.led_error_voltage = servo.get_led_error_triggers()[1]
61+
response.led_error_locked = servo.get_led_error_triggers()[1]
62+
response.current_temperature = float(servo.get_temp())
63+
response.input_voltage = float(servo.get_vin())
64+
if not motor_mode:
65+
response.physical_angle = servo.get_physical_angle()
66+
response.commanded_angle = servo.get_commanded_angle()
67+
68+
self.get_logger().info(f"Informations du servo {servo_id} récupérées.")
69+
except Exception as e:
70+
self.get_logger().error(f"Erreur lors de la récupération des infos du servo {servo_id} : {e}")
71+
# Réponse vide si une erreur se produit
72+
return response
73+
74+
return response
75+
76+
77+
def main(args=None):
78+
rclpy.init(args=args)
79+
node = LX16AController()
80+
81+
try:
82+
rclpy.spin(node)
83+
except KeyboardInterrupt:
84+
node.get_logger().info('Arrêt du nœud.')
85+
finally:
86+
node.destroy_node()
87+
rclpy.shutdown()
88+
89+
if __name__ == '__main__':
90+
main()

‎srv/GetServoInfo.srv

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
int32 id
2+
---
3+
int32 angle_offset
4+
int32 angle_min
5+
int32 angle_max
6+
float32 voltage_min
7+
float32 voltage_max
8+
float32 temperature_limit
9+
bool motor_mode
10+
float32 motor_speed
11+
bool torque_enabled
12+
bool led_enabled
13+
bool led_error_temp
14+
bool led_error_voltage
15+
bool led_error_locked
16+
float32 current_temperature
17+
float32 input_voltage
18+
float32 physical_angle
19+
float32 commanded_angle

‎srv/SetServoInfo.srv

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
int32 id
2+
int32 angle_offset
3+
int32 angle_min
4+
int32 angle_max
5+
float32 voltage_min
6+
float32 voltage_max
7+
float32 temperature_limit
8+
bool motor_mode
9+
float32 motor_speed
10+
bool torque_enabled
11+
bool led_enabled
12+
int32 led_flash_condition
13+
---
14+
bool success

0 commit comments

Comments
 (0)
Please sign in to comment.