People's platform for robots on ROS

The article is written for only those who are part of ROS itself and who need to build a real robot for training or performing real tasks.







When you start learning ROS, you usually want to work with physical platforms, and not with models in a simulator. In fact, Gazebo is enough to study just motion algorithms or just teach ROS itself, but working with a real platform immediately makes it possible to understand all the problems with wheel movement in practice. Well, and often the platform is needed simply as a prerequisite for the project.



For the future, it is better to start with a round one, because for obvious reasons, such a configuration can turn around the axis without taking into account the size of the protruding part. The U-turn rectangle is much less convenient, for example, in narrow corridors - sometimes it becomes necessary to unfold 3 or more tricks, I think motorists will understand.



Buying ready-made platforms



There are not many ready-made platforms on the market, they are listed on the ROS website .



At the same time, their cost in Russia is high enough to start work; the cheapest option is Turtlebot Burger 3 - $ 549. We found resellers directly in Russia for about 90,000 rubles.







In China, you can buy for 45-50 tr ... In any case, these will be platforms of small size and carrying capacity, not capable of performing real tasks.



You can build the platform yourself, there are a lot of different guides and configurations. But on average, it turns out something like:



  • Slamtech A1-A2 class lidar
  • Cheap wheels based on collector motors with gearboxes
  • , PWM , UART + rosserial.
  • Single Board Computer β€” Raspberry, Jetson Nano
  • 2
  • gmapping + amcl/rosbot_ekf + move_base






We did not like the collector motors because they are noisy, have a high consumption and a gearbox is needed. Here I must say that the platforms are considered quite heavy - i.e. interlocked gearboxes + motors something like the motor from the photo will not work.



Accordingly, BLDC wheel motors were chosen as movers. The most affordable option at the moment is the 6.5 hoverboard wheels. It remains only to manage them from ROS.



But then one problem surfaced: even when working with golf robots , a significant problem was noticed with the rotation of such a platform at low speed - the robot turned around rather jerky.



The reasons for this behavior are simple: sliding friction forces play an essential role in the resistance to movement in the turn. And they have a peculiarity - the resistance depends on the mass and nature of the surfaces themselves - that is why a small bolt holds large structures with the first 2-3 turns.



Therefore, making the wheels narrow in the center so that it turns around becomes rather pointless - the resistance will change very little. The rubber wheel rubs against the grass and soil, which are not at all even and the force can change dramatically, as a result, something like a gearbox was made - at low speed we control the moment on the wheel, and with direct movement - the speed itself.





It would seem that when driving on parquet or linoleum, the situation should be better, but alas, the coefficient of friction is almost the same (remember that anti-slip shoes are also made of rubber).







And as a result, a robot weighing 10-15 kilograms is already starting to unfold with tangible jerks.



The second part of the problem is added by the ROS diff_drive package in combination with rather weak SBC boards.



Here is a list of what I managed to understand



Management is carried out using a real-time implementation, but it does not take into account that other packages should expect this approach when working with management.



Here we must remember that real-time is not an instant reaction to an event, but a guarantee that the event will be processed at guaranteed intervals of physical time. Those. conditional hydroelectric power station, regulated every minute (necessarily every) is also a real-time system.

There is a chance that messages will clog the route planner topics, and for positioning and route planning subsystems, this behavior usually leads to either stopping and restarting the flow, or trying to adjust the process on the fly.







As a result, on weak SBCs a situation arises with a continuous recalculation of the path , or the search for localization eats up a sufficiently large processor time - and the more attempts are made to keep up with the RT component, the more time run-up accumulates. In its pure form, positive feedback, which in this case is not needed at all.



In addition to this, gmapping does not start working very quickly with abrupt changes in the platform position and a weak lidar - there were pauses of up to half a second, which also greatly puzzles the route planner.



The motors are controlled separately, so when using SBC and a naive implementation of drivers, the wheels will be controlled with some delay.



Here the problem is even simpler - we need to control 2-4 wheels through the communication channel, which. Accordingly, control signals line up and begin to be transmitted one after another - left wheel, right wheel, left wheel, right wheel.



As a result, the wheels themselves, and even worse, the positions of the wheels from the encoders begin to contribute to the formation of the PIC between planning the path and controlling the motors.



Built-in odometry is very simplistic.



As we were not looking for a simple way to synchronize the command and the return of odometry - I could not find it. Synchronization is always associated with waiting for some commands at the input, but they are not regular in time and as a result, odometry starts to linger at the output. Perhaps readers will suggest an easy way - here we do not consider ourselves a guru in ROS.



We did not succeed in ensuring that such an assembly behaved well. More precisely, it was possible to underestimate the acceleration of displacement to 0.05-0.1 m / s ^ 2 and the angular velocity to 0.03 rad / s.



I thought it would be nice to have:



  • Cheap platform
  • Synchronous wheel steering
  • Odometry calculation based on wheel behavior and handling
  • Turn-motion modes with different controls
  • Different restrictions in different modes


What happened in the end



The controller was taken from the gyro-scooter boards and the wheel control was written in such a way that torque control was used when starting the movement and turning. And if the cart is going straight and accelerated to a certain speed, then the speed control mode is activated. In both modes, the data from the encoders are processed inside the controller, taking into account the speed and mode, and data is output with some prediction ahead of 10-15 ms.



Encoders are always read in the controller, accumulate in a buffer of 2-3 elements and are transmitted with a delay. The bottom line is that when control is received, the response goes only after the command is executed - i.e. the buffer is blocked until the changed encoder values ​​are received. But the odometry is being issued, it just uses the last value already transmitted.



Because All of the above problems boiled down to the fact that it is necessary in any case to synchronize the control on synchronous receive-transmit from the UART port, then we considered it unreasonable to introduce a forced synchronizer into the diff_drive package, so we wrote our own control package.



It is located here github.com/Shadowru/hoverboard_driver and is currently being actively developed:



launch :



<node name="hoverboard_driver" pkg="hoverboard_driver" type="node" output="screen">
        <param name="uart" value="{ }"/>
        <param name="baudrate" value="115200"/>
        <param name="wheel_radius" value="0.116"/>
        <param name="base_width”  value="0.43"/>
        <param name="odom_frame”  value="odom"/>
        <param name="base_frame”  value="base_link"/>
    </node>
      
      





The uart port itself must be with the appropriate access rights, on some platforms it does not always have access for the user. As an example - for the Jetson Nano in the hoverboard_driver / scripts / jetson_nano_serial.sh directory, a script is attached that sets the rights when the OS starts.



The packet itself contains reading the data stream from the controller and issuing the relevant information to the topics:



hoverboard_driver / hoverboard_msg with a packet like hoverboard_msg



The message structure is as follows:



int16 state1 - internal information on wheel 1

int16 state2 - internal information on wheel 2

int16 speed1 - instantaneous speed of wheel 1

int16 speed2 - instantaneous speed of wheel 2

int16 batVoltage - battery voltage

int16 boardTemp - controller temperature

int16 error1 - wheel 1 error

int16 error2 - wheel 2 error

int32 pulseCount1 - wheel 1 encoder counter

int32 pulseCount2 - wheel 2 encoder counter



In addition, a typical message nav_msgs :: Odometry is output to the hoverboard_driver / odometry topic



The position is calculated as follows:



Based on the parameters wheel_radius - the radius of the wheel in meters, base_width - the distance between the centers of the wheels, we calculate how much each wheel has moved during the time between the previous position and the readout.



double curr_wheel_L_ang_pos = getAngularPos((double) feedback.pulseCount1);
double curr_wheel_R_ang_pos = getAngularPos((double) feedback.pulseCount2);

double dtime = (current_time - last_time).toSec();

double delta_L_ang_pos = curr_wheel_L_ang_pos - raw_wheel_L_ang_pos;
double delta_R_ang_pos = -1.0 * (curr_wheel_R_ang_pos - raw_wheel_R_ang_pos);
      
      





Then we calculate the acceleration of each of the wheels



wheel_L_ang_vel = delta_L_ang_pos / (dtime);
wheel_R_ang_vel = delta_R_ang_pos / (dtime);
      
      





Next, we calculate the linear acceleration of the robot along each of the axes



robot_angular_vel = (((wheel_R_ang_pos - wheel_L_ang_pos) * wheel_radius / base_width) - robot_angular_pos) / dtime;
robot_angular_pos = (wheel_R_ang_pos - wheel_L_ang_pos) * wheel_radius / base_width;

robot_x_vel = ((wheel_L_ang_vel * wheel_radius + robot_angular_vel * (base_width / 2.0)) * cos(robot_angular_pos));
robot_y_vel = ((wheel_L_ang_vel * wheel_radius + robot_angular_vel * (base_width / 2.0)) * sin(robot_angular_pos));
      
      





As a result, a complete set is obtained - linear acceleration, angular acceleration and multiplying them by time - the displacement of the robot's position.



robot_x_pos = robot_x_pos + robot_x_vel * dtime;
robot_y_pos = robot_y_pos + robot_y_vel * dtime;
      
      





After that, the odometry message is sent, plus a tf translation between the odometry frame and the base.



The controller at the input is controlled by one packet with 2 parameters - speed and turn, the packet is transmitted from twist almost natively - the speed is divided by the circumference and turns are obtained.



double v = vel.linear.x;
double rps = v / rpm_per_meter;
double rpm = rps * 60;
int16_t speed = static_cast(rpm);

      
      





and the angular acceleration is converted into the difference in wheel speeds in the form of multiplication by a coefficient, further recalculation will be added taking into account the wheel base, but in practice this is only necessary for sufficiently large and heavy robots.



double w = vel.angular.z;
int16_t steer = static_cast<int>(-1 * w * 30);

      
      





As a result, it was possible to achieve very stable trolley control on cheap components.







We create robots, like the vast majority of you. We have our main product, which we are actively developing. Pilot tested and ready for production. This is a robot for collecting golf balls.



We develop custom robots and derivative solutions. Sometimes this is work from technical assignment and sketch to the finished product, sometimes part of the work.







In most cases, the robot needs wheels to interact with the outside world. Most often these are brushless motors, due to the ability to accurately control speed and position.



For small robots, wheels from a gyro scooter are often used, this is justified due to the mass production and the price of this solution. Anyone who has seen the price list for Russian engines understands the importance of mass production.







As for the controller, most often these are model esc, vesc, odrive, BLD-300B, or homemade solutions.



For easy entry into making real robots and breaking the Gazebo curse, most developers need a whale for easy entry. Much in the real world is different from the ideal.



Sometimes unpredictable things happen, sensors noisy, real-time, buffer overflow. On this video device, which we previously tested with a contactor and a remote kilswitch.





We offer something that would help us save nerves in due time, this is a kit for assembling the case (parallelepiped and cylinder), two motor-wheels, a battery, a charger and a flashed controller that gives odometry and works with our ROS package out of the box for 19.000 rub. It is cheaper than milling cutting, the cost of composite material, fasteners and a cushioned swivel wheel.







Call us or apply for a platform for ROS online . Let's make robots together. We will tell you



more about the platform at the Robot Operating System meetup on December 5. Registration for participants is already open.



β†’ Registration for viewers



All Articles