Let's Make Robots!

Standard Robotic Library

All,

I remember back in the late 1990s when the Standard Template Library for C++ came out. It made things that took days or weeks into mere hours to solve. It was a revolution in thought, a mind blowing leap forward. 

I was thinking about robotics as I was driving home today, and it occurred to me that there seems to be a lack of standard libraries to solve standard programming problems.  To control a robotic arm, inverse kinematics library.  Put the number of arms, length of each arm, depth of the elbows, voila, you can control the arm.  How about a mapping algorithm for a wheeled robot that needs to cover an area (robotic lawn mower or iRobot Roomba-like bots)?  Put in the turn radius for the robot, length, width, axle length, etc and it will make a map of what it runs into.  Want a balancing robot?  Here's a library to make it balance.  Want to do some control of a heater?  Here is a PID library.  Have an encoder on that wheel?  Put in the distance per pulse, pins for led and pulse from emitter, how often to query the emitter, voila distance.  Learning algorithms?  Artificial intelligence? 

I am new to robotics, so maybe I am missing some resources.  But it seems that these sorts of algorithms written in an object oriented way with a standardized approach would go a long way towards making robotics more attainable and usable by more people.  None of this stuff is really rocket science. We need reentrant, object oriented code with a small footprint. Pick and choose what you need, put the pieces together and it does what you want. The Arduino seems to be the processor of choice so an SRL for Arduino would be great.

And if it doesn't exist, all of us should work together to create this kind of repository of code on LMR.  Look at the open source movement and the impact that has had with Linux.  We really could change the world. 

Regards,

Bill

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

The ideoms which I believe in are

  • It's neat to see $2 million dollars of exotic hardware, but in the end - the surviving software is going to run on off the shelf components
  • A good "standard" library or framework for robotics needs to run on as many platforms as possible - For example all OS's (Mac, Linux, Windows) are currently around because each has valid reasons to exist.
  • A good framework must support being massively multi-threaded
  • A good framework must be a model of "Service Oriented Architecture" - such that in a very complex system - sub parts, and minor systems can be brought up, paused, terminated, or restarted without causing deterement effects to the rest of the system.  If you stub your toe - this won't stop you from seeing with your eyes ;P
  • A good framework needs excellent communication - It should have the ability of being distributed over multiple machine, multiple boards, and multiple systems - It should have a peer-to-peer network topology (This goes with the SOA design - where there is no central system but a distribution of equal nodes)
  • A good framework need excellent version control and extension through pluggables
  • A good framework should be able to communicate with the most popular micro-controllers - When you have PCs talking to micro-controllers - I think this is a design in robotics.  Use the best of both worlds. Computers are great for networking, visual processing, number crunching, voice recognition and other "higher" functions much like your Cerebrum,, while microcontrollers are very good for autonomous nervous like systems.  (Things which are very time critical - e.g. monitoring sensors, motor control, sensor control, etc)

I chose Java, for its current maturity, and the vast amount of well organized, and well written libraries which currently exist.  It being a compiled language might be challenging for some, but Java has many scripting engines, including Python - and interfaces can be created to support scripting.

So that's what I would want if I made a framework.

(now the plug) - MyRobotLab - (http://myrobotlab.org)

 

To be honest, if I wanted a robotics library, I'd probably make my own. For example, let's say I want to write it in Python because I love Python. I would find libraries for mathematics, kinematics, dynamics, AI, motion planning, collision detection and visualization. I would then write my own code for hardware abstraction (can't skip that, you really have to write it if you're making your own robot). I'll then make all the modules work with each other, and that's it. From there I just have to remember all the API and then code new hardware abstraction stuff for every new robot I make.

and very cool.  I think C++ is more used in embedded realm and can create native, tight code close to the silicon.  But, you are talking about exactly what I would want to do, but just different language.  Same lovely church tucked in the countryside, different pew is all

An Arduino based library to control a robot arm the way you mentioned could be written. You would also need to add different arm configurations and servo ranges. For example my 13Kg/cm servos have an input range from 600uS to 2400uS for 180 degrees but different brands and models use other ranges.

which is just good object oriented design, a servo would be abstracted away as an interface.  (Just an example, not real code here.)

class IServo

{

public:

    void GoToDegree( float degree) ;

};

In the InverseKinematics class anyplace it uses a servo, it uses an IServo *.  Write a class which inherits from IServo with the implementation details of interfacing to the hardware for the different types of servos in that class.  Override those servo objects in the InverseKinematics library with your own, and you have a working robotic arm.  Make the arm configurations and the specifics of the arm in different overrideable classes, and the same process is possible. 

robotArm.GrabAt(200,200,0) ;

would then do the same thing no matter what arm configuration, what servo was being used (assuming the hardware integration is correct!).

 

 

Oddbot brings up a very good point and I think you missed the significance of it.  Your IK algorithm can't deal with servos.  It has to deal with an arm.  This is a great example of what I mention below, about generality and different hardware.  If your robot has an arm and your IK code wants to position the arm at some specific location and orientation, it will have to be written in one of two ways:  1.  It has to be written for one particular type of arm with some exact number of joints that can position themselves in some specific orientations.  THEN your IK code can call servo(x) to position each joint where it needs to be.  But this only works with arms in the same configuration.  If it is designed for 4 joints and someone uses one with 5 joints, it's useless.  2.  Support any arm with move_arm_to( x, y, z, theta, phi, rho).  Then the user supplied code takes the coordinates and moves the arm there.  That quickly becomes a huge burden on the poor user.

As Markamas mentioned, there is Willow Garage and their very popular, open source Robotics OS.  There are other similar ones.  There has also been work on much smaller, like Arduino size, libraries and operating systems.  I realize your intent is a lower level, and that causes problems.  The things you mention are really device drivers.  Since every system is different, the drivers have to be modified.  There are a LOT of lbraries that handle those things, but they are specific to certain (types of) devices.  They would have to be heavily modified for general use.  If you made similar ones that were general, you would still need a lot of code to make them work with your device.  At that point you have essentially written a real time os.  Instead, you could just download freertos and add your routines and drivers.  In fact, you may want to have a look at that.  To make a general purpose robotics os or even library of standard routines would take more memory than most microcontrollers (like Arduino) has.

These are the times when I wish I had a whiteboard!  I will look at freertos as you suggest, but I suspect you are right that the footprint is too bigh.

 The collection of classes I am suggesting would not be device drivers.  To me, a device driver is something that interacts with an operating system and a piece of hardware.  In my design, the piece that interacts with hardware would be abstracted away.  The specifics of each operating system would be something the actual code writer would have to do since there is no way for me to write specific code for each operating system or each type of hardware.  The algorithm is why someone would use the library not the hardware integration.

I don't know if you ever programmed early windows but it was "cooperative multitasking" meaning that the apps using the system all would yield when they were done with whatever they had to do which on the Arduino is the loop() .  Everybody has to cooperate, or do their thing as quick as possible to make sure noone is "starved" of processing time.  It was a poor man's multi threading, but if everybody played nicely all was good.  And here, unlike early Windows programming, the Standard Robotics Library library would be the only game in town and all play nicely since the base library and its code is under its control. 

So, if you think of a robot as a bunch of programs that work together this approach could work for all but the most time sensitive applications which are seemed to be few and far between.  The overhead for this approach could be very, very small, a few K of ram to implement maximum, but I wouldn't be surprised if I could get it to well under 1K.  The hardware piece could be abstracted away so that each operating system could call what it needs for particular actions.  MoveServo(10) would make different actual calls to the base OS libraries depending on what the controller was.

What do you think?

Regards,

 

Bill

Please don't bring the win16 model back to life.  It's dead for a reason! :-)  But I get your point.  In fact, a lot of people smarter than me do as well.  FreeRTOS that I mentioned has the capability of being used in nearly the same way.  It is not recommended unless you are using a very resource constrained system.  The idea is VERY old, dating I believe from the 50s.  I suspect that most of your programming has been on PCs or similar "large" systems.  I think your idea has a lot of merit, and apparently others do as well, if the target has the resources.  A Raspberry PI for instance, or an embedded PC. And there are such beasts in the wild, as mentioned by me and others here. But you mentioned Arduino specifically, and I will address that.  But before I get to that, let me say that cooperative multitasking is a poor choice for a robot, and preemptive multitasking is a much better and completely viable method on small microcontrollers such as Arduino.

1.  Microcontrollers are SMALL

A typical Arduino uses an ATMega328 which has 32K of flash and 2(?)K of RAM.  A PC from 1985 was HUGE compared to that.  Try supporting the STL on one of those.  Good luck.  But more to the point, try implementing a general purpose, reusable, inverse kinematics library in C++ for 32/2K.  Don't forget you will need to leave space for code to read sensors and drive servos.You didn't want it to do anything else, did you?  C++ and object oriented programming in general is a poor fit for these processors.  Arduino is "sort of" object oriented C++, but mostly as a "super-c" for notational convenience.  It is based on GCC and AVR-LIBC and here http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus is an explanation of C++ on AVRs

You mention it could be "very small, a few K or RAM".  Sorry.  You don't have a few K.

2.  Time sensitive

Robots, by their very nature, are real time systems.  Most functions may be soft real time, but nevertheless require some type of real time response.  Your libraries will have to be written with that in mind.  Some parts WILL be hard real time, and your inverse kinematics algorythm BETTER be able to get interruped and pick up where it left off with possible modifications.  IK won't be much good if it keeps chugging away while the robot is ignoring the "I'm about to fall down the stairs" sensor.  That will, of course, make the code more complex and larger, too.

3.  No two systems are the same

If everyone wanted the same robot, they would just buy a kit or an assembled unit and never add anything.  With different robots come different hardware.  Your high-level code and HAL (hardware abstraction layer) must be able to deal with ANYTHING the builder throws at it, and present a simple and consistent and easy to use interface.  So let's take a look at one example: measuring distances.  We want to be able to measure the distance from the robot to the nearest object.  Only considering the distance measurement itself, without considering any pan/tilt or positioning or other factors that may be of interest.  The measure_distance module will call a user-supplied function (say get_distance() ) that returns with a distance in some pre-agreed units, format, and resolution.  The user-supplied routine still has to do whatever required to measure the distance, but then also has to massage that data into whatever the  library is expecting.  The library needs to be general case, so let's say the returned data is a uint32_t measured in millimeters.  The robot builder might use a cheap ultrasonic device, a sharp IR distance measuring device, a laser rangefinder, a self built ultrasonic device or whatever.  The robot might be roving a desktop, a living room, a hospital, or a desert.  The user code might be a couple lines for a cheap ultrasonic or a hundred lines for home built device.  It might take a few microseconds or 200 milliseconds to measure.  It might need a couple pins or ten pins and a timer.  The library has to be robust enough to handle all cases.  The sensor might have a range of 0 to 50 inches with a resolution of 1 inch, which would be a byte, but we have to massage that into mm and convert to a 32 bit int.  Little inefficiencies start creeping in and adding up.  This is a very simple example.  Imagine a moderately complex one, like drive motor control.  An incomplete list of considerations contains: motor speed, wheel diameter, body width and length, wheelbase, encoder type and resolution, control method, braking, slippage, direction control ( single or bidirectional), etc.  The library, to be general, needs to incorporate all these.  The poor user might not care about many, but has to provide something for the library's satisfaction.

There is a lot more I could say, but I don't want to write a book.  I think I've made the point.  I will summarize with this.  Embedded systems in general, and robotics in particular, present unique and widely differing requirements.  In my day job, I write code similar to what you are trying to do.  The company I work for produces embeddes systems in a fairly narrow product space, mostly with similar requirements.  My job is to write "components" (similar to libraries) that can be used by any product group.  The products are more alike than different internally and have megabytes of memory, but still each product group has to do a lot of work to integrate our component code into each product.  The systems just have too many differences and too many constraints to just throw some general code at them and be done.  If you continue down this path (which I actually do encourage) I predict one of a few outcomes.  1.  You end up with something like Willow Garage's OS, or Microsoft's robot os, or something similarly large.  2.  You end up with something small and more limited, like Free RTOS.  3.  You end up with something small but limited that works on Arduino.  4.  You decide it isn't really a good idea, after all.

Anyway, my 1.5 cents worth.  

except for some embedded stuff I did in college, a bit of plc programming back in 1995 and the playing I have done recently with an Arduino.  And yes, the Win16 model is dead for a multitude of reasons and will stay dead. 

But it was a stepping stone to when the hardware had the cycles to deal with preemptive multitasking which is by far the better mousetrap.  And you have to believe that hardware at a price point will eventually catch up.  My idea is to have millisecond and microsecond timers that yield if there is nothing to do.  All they will be is that yes a certain amount of time has transpired so you can go if you want to.  It will be forbidden to ever use delay(100) in this code library. So, while the arm is moving, it yields every so often and catches that the robot is about to fall down the stairs.  If everyone plays nicely on the playground, all will go well, or boom it falls down the stairs.  Code reviews and testing will be important.

 I think you are right that it would need standardized hardware formats which particular algorithms would match to.  My thought was to then piecemeal link a code chunk or algorithm to hardware.  Have a robot format maybe with two bumpers on the front, link that hardware to an algorithm that if the bumpers are hit, will back up a bit, turn away and go forward.  If you want edge detection, link the led and photoresistor to the code chunk, register with the robot to run that code and you are have edge detection. 

Let it be noted that I am very good with ideas, but maybe not ideas that are really all that great.  Maybe this isn't a great or even a good idea, but I will play it.  I think I will take the simple robot example as above and use that as a starting point.  This will not be easy but might be worthwhile.  It will be fun at the least.  Stay posted and as always I appreciate your input.