Skip to content

Commit 3e173e9

Browse files
committed
Potential faster solution, see if stable on action runner
1 parent 96163ef commit 3e173e9

1 file changed

Lines changed: 79 additions & 87 deletions

File tree

radio/tests/helpers.py

Lines changed: 79 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -133,97 +133,89 @@ def set_params(params: List[tuple[str, Number, int]]) -> None:
133133
if droneStatus.drone is None:
134134
raise RuntimeError("No drone connected to set parameters on.")
135135

136-
for param in params:
137-
param_name, param_value, param_type = param
138-
max_retries = 7
139-
retry_count = 0
140-
param_set_successfully = False
141-
142-
while retry_count < max_retries and not param_set_successfully:
143-
try:
144-
# Clear any pending messages first to avoid stale responses
145-
droneStatus.drone.master.recv_match(
146-
type="PARAM_VALUE", blocking=False, timeout=0.1
147-
)
148-
149-
# Send parameter set command
150-
logger.debug(
151-
f"Attempt {retry_count + 1}: Setting {param_name} to {param_value} (type: {param_type})"
152-
)
153-
droneStatus.drone.master.mav.param_set_send(
154-
droneStatus.drone.master.target_system,
155-
droneStatus.drone.master.target_component,
156-
param_name.encode("utf-8"),
157-
param_value,
158-
param_type,
159-
)
160-
161-
# Wait for ACK with exponential backoff timeout
162-
base_timeout = 2 + (retry_count * 0.5) # Increase timeout with retries
163-
start_time = time.time()
164-
165-
while time.time() - start_time < base_timeout:
166-
message = droneStatus.drone.master.recv_match(
167-
type="PARAM_VALUE", blocking=False, timeout=0.1
136+
MAX_RETRIES = 7
137+
TIMEOUT = 2.0
138+
139+
def drain_all():
140+
"""Drain the entire buffer"""
141+
while True:
142+
msg = droneStatus.drone.master.recv_match(blocking=False)
143+
if msg is None:
144+
break
145+
146+
pending = {
147+
param_name: (param_value, param_type)
148+
for param_name, param_value, param_type in params
149+
}
150+
retries = {name: 0 for name, _, _ in params}
151+
152+
logger.debug(f"Setting {len(params)} params")
153+
154+
drain_all()
155+
156+
while pending:
157+
# Send all the pending params at once
158+
for param_name, (param_value, param_type) in pending.items():
159+
droneStatus.drone.master.mav.param_set_send(
160+
droneStatus.drone.master.target_system,
161+
droneStatus.drone.master.target_component,
162+
param_name.encode("utf-8"),
163+
param_value,
164+
param_type,
165+
)
166+
167+
start_time = time.time()
168+
169+
while time.time() - start_time < TIMEOUT and pending:
170+
msg = droneStatus.drone.master.recv_match(blocking=False)
171+
172+
if msg is None:
173+
time.sleep(0.005)
174+
continue
175+
176+
if msg.get_type() != "PARAM_VALUE":
177+
continue
178+
179+
param_name = msg.param_id
180+
if isinstance(param_name, bytes):
181+
param_name = param_name.decode("utf-8").strip("\x00")
182+
183+
if param_name in pending:
184+
param_value, param_type = pending[param_name]
185+
received_value = msg.param_value
186+
187+
if (
188+
abs(received_value - param_value) < 0.001
189+
): # Allow for floating point precision
190+
logger.info(
191+
f"Successfully set {param_name} to {param_value} (confirmed: {received_value})"
168192
)
169193

170-
if message is not None:
171-
# Check if it's the parameter we're looking for
172-
if message.param_id == param_name:
173-
# Verify the value was actually set correctly
174-
received_value = message.param_value
175-
if (
176-
abs(received_value - param_value) < 0.001
177-
): # Allow for floating point precision
178-
logger.info(
179-
f"Successfully set {param_name} to {param_value} (confirmed: {received_value})"
180-
)
181-
# Keep cached params coherent with direct MAVLink writes used in tests.
182-
droneStatus.drone.paramsController.saveParam(
183-
param_name,
184-
received_value,
185-
param_type,
186-
)
187-
param_set_successfully = True
188-
break
189-
else:
190-
logger.warning(
191-
f"Parameter {param_name} was set but value mismatch: expected {param_value}, got {received_value}"
192-
)
193-
else:
194-
# Got a different parameter response, keep waiting
195-
logger.debug(
196-
f"Received PARAM_VALUE for {message.param_id}, waiting for {param_name}"
197-
)
198-
199-
time.sleep(0.02) # Reduced polling interval for faster response
200-
201-
if not param_set_successfully:
202-
# Timeout occurred
203-
retry_count += 1
204-
if retry_count < max_retries:
205-
backoff_delay = 0.2 * (2**retry_count) # Exponential backoff
206-
logger.warning(
207-
f"Timeout setting {param_name}, retrying in {backoff_delay:.1f}s... ({retry_count}/{max_retries})"
208-
)
209-
time.sleep(backoff_delay)
210-
else:
211-
error_msg = (
212-
f"Failed to set {param_name} after {max_retries} attempts"
213-
)
214-
raise RuntimeError(error_msg)
215-
except Exception as e:
216-
retry_count += 1
217-
if retry_count < max_retries:
218-
backoff_delay = 0.2 * (2**retry_count)
219-
logger.warning(
220-
f"Error setting {param_name}: {e}, retrying in {backoff_delay:.1f}s... ({retry_count}/{max_retries})"
194+
# Keep cached params coherent with direct MAVLink writes used in tests.
195+
droneStatus.drone.paramsController.saveParam(
196+
param_name,
197+
received_value,
198+
param_type,
221199
)
222-
time.sleep(backoff_delay)
200+
201+
del pending[param_name]
202+
223203
else:
224-
error_msg = f"Failed after {max_retries} attempts: {e}"
225-
raise RuntimeError(error_msg)
204+
logger.warning(
205+
f"Parameter {param_name} was set but value mismatch: expected {param_value}, got {received_value}"
206+
)
207+
208+
# Retry only missing
209+
if pending:
210+
for param_name in list(pending.keys()):
211+
retries[param_name] += 1
212+
if retries[param_name] > MAX_RETRIES:
213+
raise RuntimeError(
214+
f"Failed to set {param_name} after {MAX_RETRIES} attempts"
215+
)
216+
217+
logger.warning(f"Retrying: {list(pending.keys())}")
226218

227-
time.sleep(0.1)
219+
drain_all()
228220

229221
logger.info(f"Successfully set all {len(params)} parameters")

0 commit comments

Comments
 (0)