One of the biggest changes in our new rover controller code is the goal of managing all ten rover chassis motors together, starting to think of the rover as a single unit instead of ten individual things.
This logic is centered in roverchassis.py, which is be responsible for calculating Ackermann angles for all steerable wheels in the rover, as well as calculating the desired travel velocity for each wheel. In order to make this code as flexible as we can, we offload details of rover chassis into configuration files and make our Python math as generic as possible running calculations based on configuration file values. This meant we could support rovers with different geometries without editing source code. This feature began with a desire to have flexible wheelbase and track dimensions of our rover chassis, but eventually extended to supporting similar but different configurations such as two-wheel differential drive.
Another goal was to support different types of motors and motor controllers. We appreciated all the features in the RoboClaw motor controller we started with, but we also thought about trading off some of these features for lower cost. In preparation for this flexibility, we kept roverchassis.py focused on general Ackermann-related math and kept motor-specific code in a separate class. In the first draft, this meant pulling all RoboClaw related code into roboclaw_wrapper.py which translates general concepts from roverchassis.py into specific commands in Ion Motion Control’s public domain API roboclaw.py. Later on we validated this flexibility by steering a single wheel with a RC servo followed by adding support for LewanSoul serial bus servos.
This was all possible using a flexible syntax in config_roverchassis.json that allows us to adjust wheel dimensions as well as switch out individual wheel travel or steering motors for different motor controllers.