Skip to content

Commit ecfde80

Browse files
committed
Feat: services to get and set servos params and subsciber to position
1 parent 9d6cb06 commit ecfde80

6 files changed

+109
-16
lines changed

CMakeLists.txt

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
55
add_compile_options(-Wall -Wextra -Wpedantic)
66
endif()
77

8-
# find dependencies
98
find_package(ament_cmake REQUIRED)
10-
find_package(rosidl_default_generators REQUIRED)
119
find_package(rclpy REQUIRED)
10+
find_package(std_msgs REQUIRED)
11+
find_package(sensor_msgs REQUIRED)
12+
find_package(rosidl_default_generators REQUIRED)
1213

1314
# Generate interfaces
1415
rosidl_generate_interfaces(${PROJECT_NAME}
15-
"srv/GetServoInfo.srv"
16+
"srv/GetLX16AInfo.srv"
17+
"srv/SetLX16AParams.srv"
18+
"srv/SetLX16ATorqueLed.srv"
1619
)
1720

1821
# Install Python modules

package.xml

+10-5
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@
77
<maintainer email="[email protected]">florisjousselin</maintainer>
88
<license>BSD3</license>
99

10+
<depend>rclpy</depend>
11+
<depend>std_msgs</depend>
12+
<depend>sensor_msgs</depend>
13+
1014
<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>
15-
<exec_depend>rclpy</exec_depend>
15+
<build_depend>ament_cmake</build_depend>
16+
<exec_depend>ament_cmake</exec_depend>
1617

1718
<member_of_group>rosidl_interface_packages</member_of_group>
19+
20+
<export>
21+
<build_type>ament_cmake</build_type>
22+
</export>
1823
</package>

src/lx16a_node.py

+84-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import rclpy
33
from rclpy.node import Node
44
from pylx16a.lx16a import LX16A
5-
from ros2_lx16a_driver.srv import GetServoInfo
5+
from ros2_lx16a_driver.srv import GetLX16AInfo, SetLX16AParams, SetLX16ATorqueLed
66
from std_msgs.msg import Float32MultiArray # Message utilisé pour la commande de position
77

88
class LX16AController(Node):
@@ -18,8 +18,10 @@ def __init__(self):
1818
self.destroy_node()
1919
return
2020

21-
# Création du service GetServoInfo
22-
self.srv = self.create_service(GetServoInfo, '/get_servo_info', self.handle_get_servo_info)
21+
# Création des services
22+
self.srv_get = self.create_service(GetLX16AInfo, '/lx16a_get_info', self.handle_get_info)
23+
self.srv_set_params = self.create_service(SetLX16AParams, '/lx16a_set_params', self.handle_set_params)
24+
self.srv_set_torque_led = self.create_service(SetLX16ATorqueLed, '/lx16a_set_torque_led', self.handle_set_torque_led)
2325

2426
# Création du subscriber pour la commande de position
2527
self.position_subscriber = self.create_subscription(
@@ -42,7 +44,7 @@ def get_servo(self, servo_id):
4244
return None
4345
return self.servos[servo_id]
4446

45-
def handle_get_servo_info(self, request, response):
47+
def handle_get_info(self, request, response):
4648
"""Service pour obtenir les informations détaillées d'un servo."""
4749
servo_id = int(request.id) # ID du servo demandé
4850
servo = self.get_servo(servo_id)
@@ -82,6 +84,82 @@ def handle_get_servo_info(self, request, response):
8284

8385
return response
8486

87+
def handle_set_params(self, request, response):
88+
"""Service pour définir les paramètres d'un servo."""
89+
servo_id = int(request.id)
90+
servo = self.get_servo(servo_id)
91+
92+
if servo is None:
93+
self.get_logger().error(f"Servo {servo_id} non disponible.")
94+
response.success = False
95+
return response
96+
97+
# default_values = {
98+
# 'new_id': 0,
99+
# 'angle_offset': 0,
100+
# 'angle_min': 0,
101+
# 'angle_max': 240,
102+
# 'voltage_min': 4500.0,
103+
# 'voltage_max': 12000.0,
104+
# 'temperature_limit': 85.0,
105+
# 'motor_mode': False,
106+
# 'motor_speed': 0.0,
107+
# 'torque_enabled': True,
108+
# 'led_enabled': True,
109+
# 'led_flash_condition': 1
110+
# }
111+
112+
try:
113+
# Appliquer les paramètres reçus
114+
servo.set_id(request.new_id)
115+
servo.set_angle_offset(request.angle_offset)
116+
servo.set_angle_limits(request.angle_min, request.angle_max)
117+
servo.set_vin_limits(int(request.voltage_min), int(request.voltage_max))
118+
servo.set_temp_limit(int(request.temperature_limit))
119+
# print(request.motor_mode)
120+
# if request.motor_mode:
121+
# servo.motor_mode(1000)
122+
# else:
123+
# servo.servo_mode()
124+
servo.set_led_error_triggers(request.led_error_temp,request.led_error_voltage,request.led_error_locked)
125+
126+
self.get_logger().info(f"Paramètres du servo {servo_id} mis à jour.")
127+
response.success = True
128+
except Exception as e:
129+
self.get_logger().error(f"Erreur lors de la mise à jour des paramètres du servo {servo_id} : {e}")
130+
response.success = False
131+
132+
return response
133+
134+
def handle_set_torque_led(self, request, response):
135+
"""Service pour définir le torque et controller la led d'un servo."""
136+
servo_id = int(request.id)
137+
servo = self.get_servo(servo_id)
138+
139+
if servo is None:
140+
self.get_logger().error(f"Servo {servo_id} non disponible.")
141+
response.success = False
142+
return response
143+
144+
try:
145+
# Appliquer les paramètres reçus
146+
if request.torque_enabled:
147+
servo.enable_torque()
148+
else:
149+
servo.disable_torque()
150+
if request.led_enabled:
151+
servo.led_power_on()
152+
else:
153+
servo.led_power_off()
154+
155+
self.get_logger().info(f"Paramètres du servo {servo_id} mis à jour.")
156+
response.success = True
157+
except Exception as e:
158+
self.get_logger().error(f"Erreur lors de la mise à jour des paramètres du servo {servo_id} : {e}")
159+
response.success = False
160+
161+
return response
162+
85163
def handle_position_command(self, msg):
86164
"""Callback pour gérer la commande de position des servos."""
87165
if len(msg.data) == 0:
@@ -90,7 +168,7 @@ def handle_position_command(self, msg):
90168

91169
# Appliquer la commande de position à chaque servo
92170
for i, position in enumerate(msg.data):
93-
servo = self.get_servo(i + 1) # Récupère le servo correspondant à l'index (1 basé)
171+
servo = self.get_servo(i)
94172
if servo is not None:
95173
try:
96174
servo.move(position) # Méthode pour déplacer le servo à la position donnée
@@ -113,3 +191,4 @@ def main(args=None):
113191
if __name__ == '__main__':
114192
main()
115193

194+
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
int32 id
2+
int32 new_id
23
int32 angle_offset
34
int32 angle_min
45
int32 angle_max
56
float32 voltage_min
67
float32 voltage_max
78
float32 temperature_limit
8-
bool motor_mode
9-
float32 motor_speed
109
bool torque_enabled
1110
bool led_enabled
12-
int32 led_flash_condition
11+
bool led_error_temp
12+
bool led_error_voltage
13+
bool led_error_locked
1314
---
1415
bool success

srv/SetLX16ATorqueLed.srv

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
int32 id
2+
bool torque_enabled
3+
bool led_enabled
4+
---
5+
bool success

0 commit comments

Comments
 (0)