dotbot/dotbot_simulator: add logic to load custom C based control loop function#222
dotbot/dotbot_simulator: add logic to load custom C based control loop function#222aabadie wants to merge 16 commits intoDotBots:mainfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #222 +/- ##
==========================================
- Coverage 69.25% 68.79% -0.47%
==========================================
Files 40 40
Lines 3789 3829 +40
==========================================
+ Hits 2624 2634 +10
- Misses 1165 1195 +30 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Very interesting! Just confirming I understood: with this we can copy/paste the If so, would it make sense to also provide an example C file (and Makefile) in the examples folder? |
The idea is to compile the source that is located in dotbot-firmware (or libs). There's no code to copy. The output library (.so or dylib) can be anywhere. The path to the .so/dylib is set in the simulator configuration file. I indeed plan to provide a helper Makefile or CMake project to compile the library and I'll probably move the .h/.c code in a segger library under DotBot-libs so it can be reused in dotbot-swarmit as well. |
d29227e to
4d7f39e
Compare
a3b4499 to
63ed07e
Compare
…tible with simulator
| self.pwm_left = self.custom_robot_control.pwm_left | ||
| self.pwm_right = self.custom_robot_control.pwm_right | ||
|
|
||
| if self.custom_robot_control.waypoint_idx >= len(self.waypoints): |
There was a problem hiding this comment.
Shouldn't this check be before the
self.custom_robot_control.waypoint_x = int(
self.waypoints[self.custom_robot_control.waypoint_idx].pos_x
)
self.custom_robot_control.waypoint_y = int(
self.waypoints[self.custom_robot_control.waypoint_idx].pos_y
)a couple lines earlier? It will break a couple lines back if self.custom_robot_control.waypoint_idx >= len(self.waypoints)
| output_lines.append(f"direction = {direction}") | ||
| if control_loop_library_path is not None: | ||
| output_lines.append( | ||
| f'control_loop_library_path = "{control_loop_library_path}"' |
There was a problem hiding this comment.
This is generating a .TOML right? but latter the toml read looks for this field:
custom_control_loop_library: Path = None. it doesn't match
| # Call the custom control loop function from the shared library | ||
| self.custom_control_loop_library.update_control( | ||
| ctypes.byref(self.custom_robot_control) | ||
| ) |
There was a problem hiding this comment.
I didn't knew what this does, so I asked chatGPT and he said this:
Without argtypes/restype, ctypes assumes restype=c_int and performs no argument validation. On x86-64 Linux this often "works" by accident, but on other platforms (macOS ARM, Windows) or
with different calling conventions, wrong assumptions corrupt the stack. The C function update_control almost certainly returns void.
Fix: After loading the CDLL, declare the signature:
self.custom_control_loop_library.update_control.argtypes = [ctypes.POINTER(RobotControl)]
self.custom_control_loop_library.update_control.restype = None
| ("waypoint_threshold", ctypes.c_uint32), | ||
| ("pwm_left", ctypes.c_int8), | ||
| ("pwm_right", ctypes.c_int8), | ||
| ] |
There was a problem hiding this comment.
I dont know how it is in python, but in rust we have to use #[repr(C)] . Do we have to align with the C code?
In simulator_init_state.toml, just add to each robot configuration the option
custom_control_loop_libraryto specify the custom control loop library to use. Example:The control loop is set per robot so each robot in the swarm can use its own control loop library. The default is to use the Python based version already available in the code base.