One of the advantages of ROS is “If you can dream it, some smart people have already built it”. One of the problems of ROS is discovering what they called it, and how to configure it to your robot.
Example - My ROS 2 GoPiGo3 node (derived from Japon’s ROS derivation of Christian Rauch’s ROS GoPiGo3 node) has some high level capabilities, such as computing a heading from the encoder values, and directly accepts “twist” topics containing robot drive speed and robot rotation speed requests and converts them into wheel speeds, and then counts on the GoPiGo3 to implement straight driving at the requested robot speed.
Many (perhaps even most) robots are implemented with more basic functionality and utilise a “Robot_Control” package commands the robot with individual wheel speeds, and adjusts the individual wheel speed requests to make the robot drive straight based on the entirety of sensor information available. This is a more complex architecture that is also more powerful:
This “topic” is now left for the reader.