Hacking a robot

Previous post have summarized “THE HACKATHON” in TouK. Today we will present one of the projects in greater detail – “Lidar/ROS.org based robot”. Our team wanted to either transport sandwiches or monitor WiFi quality in the office. Not deciding on the final goal we immediately saw that mobile robot platform will be needed in both cases.

Analysis

Some of our coworkers own Xiaomi vacuum cleaners. Such robot can be managed from mobile app which displays accurate map of your premises and allows to select areas that need cleaning. Xiaomi robot looked promising but two problems arose. First, the price is significant. Second, the communication protocol is not open. There are libraries on GitHub which try to reverse engineer the details but quick analysis has shown that we may end up stuck on some irritating problem and fail to realise our goals.

Closer examination of Xiaomi robot has revealed the core piece that allows it to automatically navigate around the house. It is LIDAR – laser distance measurement device. Another brand of Roomba vacuum cleaners relies on camera-like sensor instead. As computer vision seemed more difficult to approach we have decided on using LIDAR to build two-dimensional map of robot’s surroundings and navigate around the office.

Hardware

LIDAR technology is not as cheap as simple ultrasonic distance sensors but we have found two promising solutions on the market: YDLIDAR and RPLIDAR. Both brands are lines of different products with increasing capabilities and prices but the basic ones were within our budget. Quick comparison has shown that parameters of respective lowest-end models are similiar so we decided to order YDLIDAR because it was the quickest to ship from Amazon to Poland.

One thing to note is that core LIDAR component can be acquired for even lower price but such device will have fixed line of sight. Our chosen model, just like the one built into Xiaomi, has full 360 degree rotating head. It makes 5 to 10 rotations per second scanning 5 thousand points in that time. The output data stream contains angle and distance for each measured point.

For our robot we needed a mobile base. Common choice is base with two motorized wheels plus one or two support wheels that freely rotate in all directions giving minimal friction. We discarded that option because such simple bases for amateur constructions have weak motors and we had quite a load to put on top. Professional bases with two powerful motors are expensive. In the end we bought four-wheeled base with independent low-grade DC motors driving each wheel. The wheels are not steerable – turning is done like in a tank. Our kit was also equipped with two motor encoders – devices that measure how many times wheel has rotated – we will try to use that knowledge later.

According to the manufacturer’s data our base can bear 800 grams of load. We have put there:

  • Raspberry Pi 3 B+, the most powerful model available
  • Arduino Uno
  • 4-channel motor shield for Arduino
  • YDLIDAR
  • LiPo battery pack
  • DC voltage regulators

We have decided that our robot should be fully autonomous so all the data processing will happen on-board using Raspberry Pi. It was connected via USB with Arduino which was used to control motors using standard Arduino-compatible controller. We knew that RPi has GPIO pins that can be used to control peripherals like Arduino would but we wanted to separate the concerns and use all the power of RPi for other responsibilities.

Ross robot
Ross robot

Software

We have assembled a mobile base with YDLIDAR mounted on top but YDLIDAR itself cannot build a complete map of our office and navigate around it. We needed algorithms that could interpret incoming data stream of distance measurements and convert it into usable map. We have found the ROS.org project. It is called Robot Operating System but instead of being full OS it is Linux-based framework – collection of tools and algorithms that makes programing robots easier. As hackathon was designed to deliver working products each team was given time to prepare before the main event. We have spent that time on learning ROS and gathering main components for our robot.

ROS is capable of handling LIDAR data, building a map and performing navigation of robot. If some feature is not available in ROS it can be added by coding of a “node” – separate program that communicates with another nodes using “topics” – ordered streams of events. Fortunately, all parts of our use case were already available as standard ROS nodes, topics and event types. YDLIDAR’s manufacturer provided custom ROS-compatible node which handles low-level interaction with device. There is also an Arduino relay library that makes it possible to write Arduino code that directly subscribes and publishes events to ROS topics.

Having written less than 100 lines of ROS nodes’ launch configuration in XML and less that 100 lines of Arduino code, we were able to remote control our robot and see the map on screen. We have used separate notebook which handled joystick controller and displayed a map. The notebook was configured as ROS slave connected over WiFi to ROS master running on RPi. Below we show how simple it was to setup USB joystick controller:

<launch>
  <node pkg="joy"
        type="joy_node"
        name="ross_joy"
        respawn="true" >

    <param name="autorepeat_rate" value="10" />
  </node>

  <node pkg="teleop_twist_joy"
        type="teleop_node"
        name="ross_teleop"
        respawn="true" >

    <param name="scale_linear" value="0.3" />
    <param name="scale_angular" value="0.3" />
  </node>
</launch>

Unexpected problems and spontaneous solutions

During the hackathon days we have experienced some difficulties. As we were not able to test full robot assembly before the main event, some problems have surfaced very late in the process and dirty solutions must have been quickly hacked.

First problem: power source. During initial tests we used 24V DC power source connected to wall power. It had to be calibrated because internal protection cut off the power when current drawn by motors become too high. We also had 12V LiPo battery for final tests and show. Different input voltages were converted by on-board step-down regulators. One has provided 5V needed by RPi, Arduino and YDLIDAR. Second regulator fed 10V to the motors. During the tests it appeared that YDLIDAR cannot be powered from RPi’s USB port because its voltage was not stable enough. In the end we have connected YDLIDAR power input directly to 5V output from appropriate regulator.

Second problem: jerky movement. We thought (because ROS wiki suggested so) that it would be a good design to include PID controller driving the wheels. It is an algorithm that tries to maintain one value (in our case: measured actual speed of wheels) by varying another value that directly influences the first (in our case: power applied to motors). After some tests we have disabled PID controller because it requires fine tuning to behave correctly. As our rotational wheel encoders report only 10 ticks per revolution, the PID was confused by such low measurement resolution and tried to vary motor power too sharply rendering smooth movement impossible. We believe it can be tuned properly but during the hackathon we have setup joystick to directly control motors’ power, and not robot’s target speed, making human operator responsible for adjustments.

Third problem: faulty encoders. Our will to have wheel encoders originated not from possibility to enable PID controller, but from opportunity to increase mapping precision. Knowing how much robot has moved can help to better correlate data from multiple laser scans, producing more accurate map. Unfortunately, one of encoders appeared to work incorrectly, reporting too few ticks per revolution. Not having much time to investigate that we decided to disconnect encoders completely.

Making maps

At the beginning of second day we have already known main limitations of hardware and software and decided that we will use those parts that work predictably. We confirmed that PID controller was not neccessary for our purposes and mapping can be done using laser data only. We decided to enable simplest mapping algorith in ROS – a method called Hector SLAM. We could start first tests.

At first we mapped small room with two desks in it and a glass door. We have put additional objects in the middle to see how their presence would be handled. Everything worked smoothly using default parameters of Hector method. We also confirmed that it is easy to overlay map with additional data coming from sensors – in our case it was simple photoresistor measuring light intensity in the room.

Room
Room

Then we moved onto mapping bigger area – the hall between rooms. There is additional wall dividing it in the middle and a pillar. We added few other objects. During the tests robot was wired to the power source. We tested how to move our bodies around so to not interfere with the measurements. It appeared that after mapping initial fragment it is safe to walk around and Hector algorithm will ignore moving objects. Only after staying for too long in the same place our legs started to be included as part of the map.

Hall
Hall

Final test shows straight corridor. Its map is bended and we are not sure of the cause. It may be related to slow scan rate of YDLIDAR which accumulates error during robot’s movement.

Corridor
Corridor

Future work

Having learnt ROS before the hackathon and solved mostly hardware-related problems during the event, we have shown that map building is possible even with simple setup. We would like to expand the algorithmic part of the solution, enabling our robot to autonomously move in the office environment. Proper navigation components are already available in ROS.

Conclusions

ROS is a powerful tool that can be used both by amateurs and proffesionals. Its sophisticated architecture allows for complex definitions and management of industrial-grade robots, but can also fit in quick and dirty home projects. For us the biggest challenges lied in the hardware layer, but having electronic engineer on the team helped to connect all the parts together. All Ross team members are happy with results and wish to continue the project.

You May Also Like

Spring Security by example: securing methods

This is a part of a simple Spring Security tutorial:

1. Set up and form authentication
2. User in the backend (getting logged user, authentication, testing)
3. Securing web resources
4. Securing methods
5. OpenID (login via gmail)
6. OAuth2 (login via Facebook)
7. Writing on Facebook wall with Spring Social

Securing web resources is all nice and cool, but in a well designed application it's more natural to secure methods (for example on backend facade or even domain objects). While we may get away with role-based authorization in many intranet business applications, nobody will ever handle assigning roles to users in a public, free to use Internet service. We need authorization based on rules described in our domain.

For example: there is a service AlterStory, that allows cooperative writing of stories, where one user is a director (like a movie director), deciding which chapter proposed by other authors should make it to the final story.

The method for accepting chapters, looks like this:

Read more »

Sample for lift-ng: Micro-burn 1.0.0 released

During a last few evenings in my free time I've worked on mini-application called micro-burn. The idea of it appear from work with Agile Jira in our commercial project. This is a great tool for agile projects management. It has inline tasks edition, drag & drop board, reports and many more, but it also have a few drawbacks that turn down our team motivation.

Motivation

From time to time our sprints scope is changing. It is not a big deal because we are trying to be agile :-) but Jira's burndowchart in this situation draw a peek. Because in fact that chart shows scope changes not a real burndown. It means, that chart cannot break down an x-axis if we really do more than we were planned – it always stop on at most zero.

Also for better progress monitoring we've started to split our user stories to technical tasks and estimating them. Original burndowchart doesn't show points from technical tasks. I can find motivation of this – user story almost finished isn't finished at all until user can use it. But in the other hand, if we know which tasks is problematic we can do some teamwork to move it on.

So I realize that it is a good opportunity to try some new approaches and tools.

Tools

I've started with lift framework. In the World of Single Page Applications, this framework has more than simple interface for serving REST services. It comes with awesome Comet support. Comet is a replacement for WebSockets that run on all browsers. It supports long polling and transparent fallback to short polling if limit of client connections exceed. In backend you can handle pushes in CometActor. For further reading take a look at Roundtrip promises

But lift framework is also a kind of framework of frameworks. You can handle own abstraction of CometActors and push to client javascript that shorten up your way from server to client. So it was the trigger for author of lift-ng to make a lift with Angular integration that is build on top of lift. It provides AngularActors from which you can emit/broadcast events to scope of controller. NgModelBinders that synchronize your backend model with client scope in a few lines! I've used them to send project state (all sprints and thier details) to client and notify him about scrum board changes. My actor doing all of this hard work looks pretty small:

Lift-ng also provides factories for creating of Angular services. Services could respond with futures that are transformed to Angular promises in-fly. This is all what was need to serve sprint history:

And on the client side - use of service:


In my opinion this two frameworks gives a huge boost in developing of web applications. You have the power of strongly typing with Scala, you can design your domain on Actors and all of this with simplicity of node.js – lack of json trasforming boilerplate and dynamic application reload.

DDD + Event Sourcing

I've also tried a few fresh approaches to DDD. I've organize domain objects in actors. There are SprintActors with encapsulate sprint aggregate root. Task changes are stored as events which are computed as a difference between two boards states. When it should be provided a history of sprint, next board states are computed from initial state and sequence of events. So I realize that the best way to keep this kind of event sourcing approach tested is to make random tests. This is a test doing random changes at board, calculating events and checking if initial state + events is equals to previously created state:



First look

Screenshot of first version:


If you want to look at this closer, check the source code or download ready to run fatjar on github.During a last few evenings in my free time I've worked on mini-application called micro-burn. The idea of it appear from work with Agile Jira in our commercial project. This is a great tool for agile projects management. It has inline tasks edition, drag & drop board, reports and many more, but it also have a few drawbacks that turn down our team motivation.

Wicket form submit not safe for redirecting to intercept page

The problem When you have a form, that anybody can see, but only logged on users can POST, you may want to redirect the user to the login page, and back to the form after login Using wicket 1.3/1.4, if you do that using redirectToInterceptPage(loginP...The problem When you have a form, that anybody can see, but only logged on users can POST, you may want to redirect the user to the login page, and back to the form after login Using wicket 1.3/1.4, if you do that using redirectToInterceptPage(loginP...