- Published: Thursday, 15 December 2016 02:15
- Written by Kyle Granat
We recently updated the RobotGeek Snapper Arm with a new gripper, so I've been off in documentation land, getting everything happy for the new change. This inevitable led me to doing some work on the Arm Link Software. I have a love hate relationship with my little arm link program, but it works, so why not?
So first up didn't actually have a whole lot to do with the software, but the Snapper firmware. Andrew wrote all of the IK code for the Snapper, but never implemented Cylindrical or Backhoe modes. Backhoe mode is obviously pretty easy - just map the arm link packets to the servo joints. Cylindrical wasn't bad either, as Andrew had done all the IK work (the code is very similar to the code for the Cartesian X/Y/Z IK, only you ignore the X axis). The pain was going through the code and making it ready for multiple modes. A tedious hour later, I had everything working smoothly.
On the Arm Link side, it didn't take much to get things working. I had disabled cylindrical and backhoe mode on the snapper, so I quickly re-enabled them and added in all of the limits.
Of course an update like this turns into a black hole of updates. I had to update the ArmLink reference page for the new features, commands, and limits. Then I had to add the cylindrical IK engine into the main joystick IK software. And while I was at it I added the backhoe to joystick (which had previously been its own sketch). And then I updated that documentation. It never ends.
We make binary executables available for ArmLink, so making updates can be a little bit of a pain. It's nothing herculean, but to get java embedded with the app I need to build it on each target platform (once on Mac, once on Linux, once on Windows). So I try to wrap up multiple updates in one release when possible. So I decided to move onto a couple of things I've wanted to fix/change in the software.
There are two ways to send positional updates to the arms - you can hit the
Update button to send the current values, or you can check the
Auto Update box. If you check the box, the positions will automatically be sent to the arm. If you lower the transition time (the delta) then you can get the arm to react in real time with your sliders and knobs. This feature works, but I found out that under certain positions that you could start to have problems. I'll go into more details in a later post, but with our Arm Link packet, if you send the same packet multiple times, and the packet has too many '0xff'/255 bytes, it is possible to read the last half of one packet and the first half of the next as a 'valid' packet. This can lead to some bad situations like arms repeatedly pounding the table. I'm still ruminating on ways to fix this on the packet side, but I decided that an easy fix on the software side would be to only send positional packets if a position was actually going to change. So every loop I check the current values against the last values - if there's a change, I send a packet. If not, I go on with my life. Either way I store the packets away to check against next time. This has fixed most my problems, though I'm still investigating an issue where two many '0xff' can freeze the arm temporarily.
Finally I got to add something fun that I've wanted to add for a while. For the InterbotiX arms that use DYNAMIXEL I've gotten a couple of questions about accessing the servos directly. Basically each DYNAMIXEL serveo is a smart servo with a micro controller on board. There's all sorts of data that you can poll the servo for like position, temperature torque, and more. You can also set parameters like compliance on AX servos and PID settings on MX servos. But to get at any of this you need to work at the firmware/arbotix level. After another request for the feature last week I finally decided to implement the future.
On the firmware side I added two new instructions in the
inputContro.h file. The first will get data from the servo / register that you request from (instruction 0x81). The second instruction(0x82) will set data to a servo/register that you set. To pass the data I'm just using the packets normally reserved for X/Y/Z/Wrist for the parameters Id/RegisterNumber/Length/value.
So before I started integration into ArmLink, I wanted to do some testing. The easiest way would probably have been to fire up Cool Term and write out the packets to send to the arm, but I'm a masochist so I started ANOTHER project- Arm Link Barebones. Arm Link started as a basic demo both Interface wise and code wise. And while the code is readable, it jumps through a ton of hoops, so there's a lot to wade through if you're a developer and you just want the minimum example to get going. So Arm Link Barebones is just that, a really basic example of how to control the arm. There's no GUI, just some functions to talk to the arm over serial. Eventually I'll wrap it up in a nice library, but it's a decent stop gap.
Really starting Arm Link Barebones wasn't a big deal, I just ripped up a copy of Arm Link proper. So another hour later I had Arm Link Barebones sending commands to the arm. A few more functions added and there I was blinking servo LEDs and reading firmware versions from my computer. Huzzah!
When I started working on the get/set registers I didn't even plan to integrate it into Arm Link, but I took it that far, so I went just a little further. Really the biggest pain was integrating everything into the GUI. It's kinda cramped as is, and I really didn't want to re-arrange the whole gui. But after some 'creative' moving I finally got all of my fields in. I'm at home right now, and I did a lot of testing by putting some Arm firmware on a spare Geekduino, but I need to actually test it on a real arm. So keep your fingers crossed, hopefully I'll have a release tommorow.
Now keep in mind that I really want to move the Arm Link software over to a chrome app. I think for a demo that chrome apps have everything I need, are cross platform, and super easy to update/do gui stuff. Maybe next time
`The Setup: our Arm Link Firmware supports 3 different arms. A one line
//#define PINCHER //#define REACTOR //#define WIDOWX
Just uncomment the line for your arm and you're good to go, the firmware takes care of all the work for picking the arm.
The Problem: If you try to compile the code you get a slew of unhelpful errors, starting with ...
In file included from InputControl.h:4, from InterbotixArmLinkSerial.ino:72: Kinematics.h: In function 'uint8_t doArmIK(boolean, int, int, int, int)': Kinematics.h:101: error: 'WristLength' was not declared in this scope Kinematics.h:102: error: 'BaseHeight' was not declared in this scope Kinematics.h:106: error: 'ShoulderLength' was not declared in this scope Kinematics.h:106: error: 'ElbowLength' was not declared in this scope Kinematics.h:143: error: 'BASE_N' was not declared in this scope Kinematics.h:143: error: 'BASE_MIN' was not declared in this scope Kinematics.h:143: error: 'BASE_MAX' was not declared in this scope
and going on for several dozen lines. Now if you've read the Setup guide then you should know that you have to uncomment a line for your arm. But what if you didn't? Or what if you forgot? How can we make this a better user experience?
A while back I did some searching for 'Custom Arduino Errors' and the like, but I never found much. But last month while looking at the Razor AHRS Firmware I found exactly what I needed
// Check if hardware version code is defined #ifndef HW__VERSION_CODE // Generate compile error #error YOU HAVE TO SELECT THE HARDWARE YOU ARE USING! See "HARDWARE OPTIONS" in "USER SETUP AREA" at top of Razor_AHRS.ino! #endif
You see, the Razor AHRS Firmware supports a bunch of different hardware, so at the very top of the file you need to define which hardware you're using (sounds familiar, eh?). So the little block above throws an error and stops the user if the hardware wan't defined. And it's a totally custom message, so you can explicitly tell the user what the problem is. Since this code lets you throw custom errors based on pre-processor defines. So now the Arm Link code looks like
#define PINCHER 1 #define REACTOR 2 #define WIDOWX 3 //uncomment one of the following lines depending on which arm you want to use //#define ARMTYPE PINCHER //#define ARMTYPE REACTOR //#define ARMTYPE WIDOWX #if !defined(ARMTYPE) #error YOU HAVE TO SELECT THE ARM YOU ARE USING! Uncomment the correct line above for your arm #endif
Later in the code we can check the type of the arm (see GlobalArm.h)
#if ARMTYPE == PINCHER #define ARMID 1 #define CNT_SERVOS 5 //(sizeof(pgm_axdIDs)/sizeof(pgm_axdIDs)) //...etc #endif
It is worth noting that the firmware should probably be doing a check against the servos that it sees and not engaging unless it sees all the servos. Though this would cause a whole different issue - code running on the robot but no good way to tell the user that servo discovery has found a problem. But that's a quest for next time I guess.
With one of our crew out, I've been working double duty all week, so I don't have all too much to report on this week. One of the things that came up is the need for something a little more robust then the RobotGeek Gripper for our RobotGeek line. The InterbotiX line has the Parallel Gripper, and we actually made some prototypes that use that gripper with RobotGeek servos a while back, but it never really went anywhere. Upon revisiting the project with our slightly newer, slightly stronger servos, we found that it actually works out pretty well. We made a jig for drilling the extra holes needed, and made some new prototypes. Matt came up with some clever ways to mount everything and the gripper seems to do pretty well.
I toyed around a little with the 3D printer over the week, intent on making some new gripper fingers. I started of by printing the original finger file, which turned out decently. I think opening up the rails would make it move smoother, but I also had a sanded-down bottom plate it could attach to, so I forged ahead. I tried a couple of other designs.
A parallel gripper works by connecting the servo motor horn to two swings arms. The swing arms then connect to two finger pieces. The finger pieces are on a plate with parallel rails. As the servo rotate, the swings arms bring the finger plates in or push them out. This means that the maximum movement of the fingers is defined by the servo rotation and the swing arm length. So by changing the size and shape of the fingers, you can change the size of the object you can grip. But since the overall distance the arms move doesn't change, this means that you can only grip objects in a range. So If I can normally grip objects between 0 and 25mm, and I modify my fingers to be 25mm apart, I can only grip things from 25mm to 50mm. Anything below 25mm wide and I won't be able to grab them. For some tasks, this works out.
Matt is experimenting with cutting/modding the existing fingers and has had some luck. He also had the idea to mount 3D attachments to the cut-down fingers, so I printed out some fingers designed for a soda can. I didn't put much thought into the design, so it's kinda ugly. Because the gripper has such a small travel, I don't think this gripper will really work - you'd have to be super accurate or you'd be more likely to spill the can before you could pick it up
Still, there are a lot of grippers you could design that would be actually useful. We've got a couple secret designs in the work. Hopefully next week I'll be able to share some more as well as some improvements to our other 'bots.
This isn't the First Time I've tried to get a RobotGeek Crawler going. I toyed with the idea of a MK-II style crawler, and later a MK-I style quad (because of the lack of 45 degree brackets for RobotGeek). At one point I passed it off to Wade who tried some head-crab like machinations
None of that really went anywhere though. But last week I was thinking about what I could do to make a simple 2-degrees of freedom(dof) quadruped. So that means each leg would get 2 servos, so a total of 8 servos. On your standard Arduino/ ATMEGA 328 you get 6 hardware PWM channels - so you can control up to 6 servos. There are lots of ways to do PWM in software like KurrtE's ServoEX Library, though it will take up some processing power. Still, being able to control 8 servos with no additional hardware is great for keeping the cost down.
I started off with a really simple design shown in the first picture. The body plates Kevin cut me for other experiments. Basically it's the body plates for the PhantomX Quad with the centimeter grid pattern and servo slots for RobotGeek Servos. The coxa to femur is just a dual hinge bracket. The femur extensions are actually plates from the RobotGeek Snapper Arm. Part of me wants to do some alternative designs (swap the coxa/femur ), but that makes mounting harder, so I'll probably stick with the current design.
It was the weekend, so rather than wait for Kevin to cut me some plates, I fired up the 3d Printer and made some plates for the femur extensions / feet. Just a simple taper, a little reminiscent of the MK-I feet. I'm still considering some other options (flipping the femur servo, making the extensions longer, etc) but it's a start.
So the million dollar questions is - Does it walk?. Well, no, not yet. I've got it moving around and doing some motions, but nothing too fun. I'm doing a lot of reading in Inverse Kinematics, and I've got a super simple solver for a 2dof leg to make it move to a position in xyz space. Now I'm trying to figure out exactly how I turn that into consistent movement on the crawler. I'm going to start with rotating the body and the move onto walking. I've been walking through the NUKE generated code that we use for the 3 dof crawlers, which has been useful - I just have a ways to go.
So if I'm still working on this next week, maybe I'll have it shambling around. I'm also thinking about a couple different walker type robots that might be fun, but I want to see where this one goes.
A couple years ago my Lead Engineer Andrew bought a Felt MP Cruiser off cragislist. I was insanley jealous. I absolutley loved the look of it (much more than the newer version of the Felt MP). He also bought a Skyhawk Bicycle Motor Kit which he installed with the help of our friends over at Mad Lab Industries. The motor worked at one point, but I'm not sure it still had an issue or if my lead engineer just didn't have room for it by the time it was finished. Earlier this year my lead engineer moved to start our second office, and he decided tot to take the bike. Knowing that I loved his bike, he gave it to me!
Over the next couple of months Don helped me to get the bike running again. And by helped, I mean did almost all the work. I'm slowley learnining more about this little 2-storoke engine, but I'm no mechanic. We had to clean out the fuel lines and get it a new spark plug, but finally the bike roared to life!
Until it broke.
The weld where the motor mounted to the bottom frame of the bike failed. I ordered a mounting bracket from King Motor Bikes, hoping it would get me up and running, but I didn't take into account that there was basically no clearance between the exhaust on the bike and the bike frame. I was also having some clearance issues on the bolts coming out from the motor itself. Which just serves as a $20 reminder that I need to measure and actually think about how the peice will fit, not just use the order and pray method.
Don, like a true pro came through with a new weld job. He welded a small flat plate to the bike frame to cover the hole /reinforce the frame. Then he wlesed a standoff to that plate. He used his plasma cutter to make a small plate with three holes, one to bolt into the standoff and two to bolt into the bolts coming off the motor. And just like that I was good to go!
Since then I've had a couple of 'adventures'. When I got it one of the pedals was ruined and I was impatient, so I bought a cheap pair of pedals at target. Never. Again. The pedal cracked right down the middle on an uphill climb. I also managed to lose a master link on my engine chain, but I'll carry a spare from now on just incase.
I kinda had my doubts about the motor when I first heard about it, but it's really a stupid amount of fun. And being able to switch between motor and bike can be really handy when getting around town. For my commute to work I try to use the motor sparingly so that I still get some amount of exercise, but If I'm going across town to pick up some last minute groceries I'll just motor it all the way there.
So what's next? I retro-fitted the headlight with an 1 watt LED but I think I'd prefer something brighter. I don't know if I'll try to keep the original enclosure or not. It would be easy if I wanted to go with a LiPo battery, I just don't know how much mainatnce / circuitry I want to do. Once I figure that out I'd like to try to do break lights and turn signals. Until then I'll just use a light up blinker / reflector.
I'm also looking to add a couple of saddlebags to the bike that I got from the American Science & Surplus store. If everything goes well, I'll have it looking something like this
And just for fun, here's a hasty scan of my bike using the structure sensor.
I want to make an adorable robot. I've wanted to make one ever since I saw this video of the robot Mira. So the quest began.
Ideally, I want to make the robot out of RobotGeek parts, as they're plentifully available to me, are low cost, and this robot could eventually become a kit. I decided that I wanted the robot to be able to sit in place, but be able to spin freely, so I started looking at the RobotGeek Continuous turn servo. I'm hoping that it's up to the task - if not I'll need to look at an Pixy camera so that the robot could track color blobs and color codes.
After a couple of terrible sketches, I enlisted the help of Wade to see what we could do. We played around with a couple of options for the tilt mechanism, eventually settling on a 180° RobotGeek Servo. Since we don't have any 'back' brackets, we had to so some clever assembly to get it working. I came up with the idea of using the 4C's idler to attach to the 180° servo, and Wade figured our we could brace two side frames together with a plate. We still need to cut a proper plate, but we used so spare plates from other projects to make a prototype. We
After our initial built, wade made some improvements to the robot, making a better mounting rig for the camera and adding a buzzer. He started working with the Pixy's code and I helped him getting the servo settings right to get some basic color tracking down.
We're tentatively calling the robot Heelo after Kat recommended we call it something that sounded like Heliotropism . We started at Helios, which turned into Helio, which begat Heelo.
We've still got a long way to go. We're evaluating the RobotGeek servos to figure out if they'll give us good enough control to make the robot lifelike. We've also toyed with the idea of using a raspberry pi as a main controller and doing some more advanced vision processing, though I think we want to keep this at a little lower level, at least for now. And then there's the question of shells. We'll probably start by designing and 3d printing some shells, but we don't quite know how the robot will look. Time will tell I guess!
My quest to create a PhantomX Hexapod Toy continues! After a couple of days thinking I had killed my printer (PLA all over teh extruder, no I don't want to talk about it right now but thaks for asking) I've got a couple new prints. I've been playing with super basic joints using rods and holes. You can find the models of my attempt here. I took the femur and tibia from my previous model and separated them. Then I added in a cylinder at the middle of the 'servo' for each part, and a hole big enough for the cylinder on the "F1 Bracket". I figure I'd try this method after I saw how well some of the joints on Kevin's Golsm 3d prints I made worked out.
The holes don't print perfectly, though I wonder if they'll be any better if I use a higher resolution (I only did 200 microns on this print). Also, I could use a file to round out the holes a bit.
This time the rods turned out pretty well, previously I had made them too long. This means there's a lot of sag and when I try to fir the bracket over it I end up breaking the bracket. I'm thinking about thickening the bracket walls up just a little bit.
As it stands, all that's keeping the joint from moving under gravity is the imperfections of the holes and rods. Kat suggested I do something with cotter pins, and I'm also just thinking about striaght gluing the prts together. But If I can figure out some reliable way to get
Gif made with the awesome Gif Rocket app. As an added bonus for this blog, here's a gif that's just full of derp. We had a Quadruoed user load the wrong code onto their robot which resuted in this derptastic IK.