Hello, I’m using a substitute sensor for Intel RealSense D435 and while resting today, I set both OA_ and AVOID_ params. I gave a local position setpoint for it to go to. It seems to be going to the goal but it is not avoiding obstacles. Should I be only giving OA_ and disable AVOID_?
Hey Evens,
I’m actually looking at this at the moment.
I’ve found that only 2D OA works reliably at the moment, not 3D. Bendy will only search in one plane, either vertical or horizontal, but not both.
Here are my parameters. The distances I have set are not optimal, as I’m working on something that is not exactly real-world. That being said, these settings do work in SITL, but only in Auto, Loiter, and Guided.
PRX1_TYPE 2
PRX1_MIN 2
PRX_LOG_RAW 1
AVOID_ENABLE 2
AVOID_MARGIN 2
OA_TYPE 1
OA_MARGIN_MAX 2
OA_BR_LOOKAHEAD 50
OA_BR_TYPE 1
OA_BR_CONT_RATIO 1.3
OA_BR_CONT_ANGLE 50
OA_DB_SIZE 1500
OA_DB_EXPIRE 5
OA_DB_BEAM_WIDTH 5
OA_DB_QUEUE_SIZE 150
OA_DB_RADIUS_MIN 0.05
FENCE_ENABLE 0
FENCE_TYPE 0
I’m doing some investigations into expanding Bendy into a full 3D search pattern, and increasing the look-ahead to a 3–5 step ranked system, rather than the current first-found single-step approach it uses now.
Let me know if you’d like me to keep you updated.
Is AVOID_MARGIN the threshold distance from obstacles?
Lookahead is just the radius below which all obstacles are stored in the database for future avoidance?
AVOID_MARGIN — yes, it’s the minimum distance the drone tries to maintain from obstacles. It’s used by AC_Avoid
(the 400Hz velocity limiter) to create a “buffer zone.” When the drone gets within AVOID_MARGIN of an obstacle,
AC_Avoid starts limiting velocity toward that obstacle.
OA_BR_LOOKAHEAD — not a storage radius. It’s how far ahead BendyRuler probes when testing directions. It projects
a line segment from the drone’s current position out to LOOKAHEAD meters in each test direction and checks if that
path clips any obstacles. Longer lookahead = sees obstacles earlier = deflects sooner, but also means narrow
streets get flagged as blocked because the probe overshoots past the clear zone.
The database storage radius is actually OA_DB_DIST_MAX — obstacles beyond that distance are discarded from the OA
database entirely.
So the chain is:
-
OA_DB_DIST_MAX — how far out obstacles are stored
-
OA_BR_LOOKAHEAD — how far ahead BendyRuler probes for path planning (1Hz)
-
OA_MARGIN_MAX — obstacles beyond this are ignored by BendyRuler’s margin check
-
AVOID_MARGIN — the hard buffer zone enforced by AC_Avoid (400Hz velocity limiting)
I am using a RealSense object avoidance equivalent replacing the RealSense with a 60 deg FOV ESP32-CAM and monocular depth estimation. In this case, PRX type is mavlink and what do you suggest the beam angel parameter be?
I’m currently working on Bendy in a branch of ArduCopter, and it touches on a few of the issues you’ve raised.
I don’t have anyone’s blessing from ArduPilot at this stage, so I may well be getting ahead of myself here. But the aim is to improve path routing by making it more 3D-aware and by making the re-routing more robust over longer distances.
At this stage, I’m only testing in SITL, not on a real aircraft, so it may or may not help your use case. The work is being designed with 360-degree lidar awareness in mind, and my intent is to get the most out of it before heading down the path of a Companion Computer.
but I have managed to address most of the issues you raised.
Whether it would work with your forward-looking depth sensor, I’d say probably, but I can’t say that with confidence yet.
Whether ArduPilot would ever accept my code into the official fork, I have no idea. Some pics of my progress.
For a 60° FOV monocular depth camera on ESP32-CAM:
PRX_LOG_RAW = 1 (for debugging)
PRX1_TYPE = 2 (MAVLink)
PRX1_ORIENT = 0 (forward, assuming front-mounted)
PRX1_MIN = 0.5 (monocular depth is unreliable under 0.5m)
PRX1_MAX = 10 (monocular depth on ESP32 — realistic max is maybe 8-12m depending on the model. MiDaS/DepthAnything
on ESP32 won’t be accurate at range)
OA_DB_BEAM_WIDTH = 60 — this is the key one. It’s the sensor’s FOV. ArduPilot uses this to calculate the obstacle
radius in the database — wider beam = larger obstacle radius because the bearing is less precise. With 60° FOV
divided across however many sectors he’s sending in OBSTACLE_DISTANCE (are you sending 12 sectors, each is 5°
wide, use 5. If sending as a single reading, use 60).
If OBSTACLE_DISTANCE with increment_f:
- OA_DB_BEAM_WIDTH = his increment (e.g., if 60° FOV / 12 readings = 5° per sector, use 5)
If DISTANCE_SENSOR:
- OA_DB_BEAM_WIDTH = 60 (full sensor FOV since it’s one reading)
For BendyRuler specifically:
-
OA_TYPE = 1 (BendyRuler)
-
OA_BR_LOOKAHEAD = 10 (match his max sensor range — no point looking further than the sensor can see)
-
OA_MARGIN_MAX = 3 (wider than sensor uncertainty)
-
AVOID_MARGIN = 2
-
OA_BR_TYPE = 1 (horizontal, since he only has a forward-facing 60° camera — no vertical coverage)
monocular depth is noisy and relative, not absolute. MiDaS/DepthAnything output
relative depth maps that need scaling. If his depth-to-meters calibration is off by 2x, the drone will think
obstacles are twice as far as they really are. validate against a known distance (tape measure to a
wall) before trusting it for avoidance. A RealSense gives centimeter-accurate depth — a monocular estimator on
ESP32 might be off by 30-50%.
Also 60° FOV means 300° of blind spots. BendyRuler might deflect into an obstacle it can’t see. He should consider
Thanks, for the explanation.
Actually DepthAnythingV2 has metric depth. I made a blog recently of autonomous navigation using that.
