MURVV - Android Robot Controller
In the end, what we created was a simple and functional remote control for the MURVV robot. The program runs on an Android phone or tablet and is capable of preventing multiple simultaneous accesses by placing users on a waiting list, or queue as I usually referred to it as. Administrators can bypass this queue system, remove the current user and use the robot immediately via a simple login system. In addition, robot functionality is locked within certain hours of the day to prevent users from accessing the robot outside of regular working hours.
The program was optimized to some reasonable extent and runs at very nearly the same speed as it did before the queue system was implemented. It was also simplified to some extent, making it easier to add additional functions later on.
At the beginning of this project we had simply wanted to write an Android application that we could use to move the robot around. I was given the task of writing this application and started by making a list of all the different functions I wanted the Android application to be capable of performing. As well as these functions, I also drew up a rough layout of what I wanted the application's user interface to look like. And after a series of problems, mostly caused by both my lack of experience in both using phidgets and programming Android applications, I managed to get the application working without having to make any major changes to my original plans.
When this was all done, we decided to expand the scope of the project by making the robot easily accessible over the internet. I knew this was going to be a fairly complicated addition to the project, but I started working on it in exactly the same was as I had done before. I made of list of all the new functions I wanted the application to perform, potential problems I would encounter along the way, and a quick drawing of any new user interfaces I would have to include. And, much like before, after encountering more than few problems -mostly caused by my extreme dislike of computer networking- I managed to add all the new functions to the application.
Things are really moving along smoothly now. In fact, I don't even think I have anything to complain about today!
At the beginning of the project, I created a list of the kind of functionality I wanted to have by the end of the project and most of that, as well as few other things, have been completed now. And although most of the things I completed today are relatively minor in the grand scale of things, I completed a whole bunch of these little minor things that have been on my "to-do" list for a long time.
Tomorrow I will try and find any remaining flaws in the program and fix them. And after that, I think this project will be considered finished... again.
Spent the day wrapping things up and preparing for major testing tomorrow.
Everything is sure coming along nicely now! I've been trying to "child-proof" the program as best as I can. I know the kind of audience that I'm going to be targeting, and I sincerely doubt that every one of them is going to be as knowledgeable and forgiving as I am. Therefore, if I want to stop people from crying out in frustration, hurling themselves off bridges and doing other terrible things to vent their anger with my software, it is my duty to make this program as unbreakable as possible. Of course, with the infamous "networking problems" this isn't exactly the easiest thing to do. There are going to be a lot of problems that pop up that are going to take a lot of work to deal with.
In terms of short-term goals, I've finally got the program to properly display the user's "place in line" and I've also got the program to function on a timer. (So that no one user can hog the robot for twenty years at a time... Don't think that can't happen. If you allow it, someone will find a way...)
The program requires child-proofing!
Today was a day I used to fix all the problems I created before the long weekend. As always, it was some stupid little bug that was causing all the problems. The issue was that I closed the phidget dictionary in some random function and then tried to use it afterwards. Needless to say, that doesn't work very well...
I also spent some time getting git set up on my computer so that I can have a detailed record of all the changes I make in the future. I learned how to use the program during my last internship job, and though I really hated using it for the first couple of weeks, it has now become this thing that I just can't live without. It's extremely useful to have! If you've never used it before, it's worth checking out. And if you've never heard of it before, you can check it out on their website. (Because I really doubt I could do a better job of explaining the software myself...) One thing I will note, however, is that you will probably want to use git with one of the free "git repository websites" so you can store your code online. Either Github or Bitbucket are great options and you can read more about them on their websites.
Most of the problems I created have been fixed now. I also got a git repository set up for my code.
So I spent the last two days rewriting the program into something that's slightly more understandable, but as always, now it doesn't work properly any more. In fact, that parts that do work are really slow now. So now I'm trying to fix all the problems and that's just creating more problems and more work. So now, I think, would be a good time to advertise the revision control system "git", which I think I shall start using with these projects from now on. It's very frustrating when you realize that all of the work you did only made things worse and it's very nice to be able to click a button and revert everything back to the way it was. But, because of my lack of foresight, I can't do that. I don't have any older copies of the program and so my only way of fixing everything is either trying to make the new stuff work or trying to remember what I wrote down almost a week ago and revert back to the old stuff.
Always keep a record of the changes you make to your programs. You'll be thankful you did.
I have a lot of the standard administrator features implemented now, but the complexity of the program is only getting worse. At some point in the near future I will have to try and improve things, either by cutting out unnecessary functions or finding some way to rewrite parts of the program. It's not even a problem of making the thing more "object-oriented" as some of you may be screaming at your monitors right now. It's the problem of passing around so many complicated variables between the robot and the android users and somehow making sure that the robot is not going to crash.
Did I ever mention how much I disliked networking problems?
The program is turning into a very ugly rat's nest and I blame it on networking problems, because networking problems are evil.
Many of the little bugs have been worked out now and the queue works pretty well. Right now, the queue has room for up to 10 different users (including the one at the head of the queue), but after that, it's a free-for-all. That isn't to say that the eleventh, twelfth, and thirteenth users won't be able to get into the queue, at the moment, I have a work-around for that and they can still enter the queue at some point. However, who exactly gets to enter the queue is dependent upon who happens to get in line first and isn't dependent upon anything other than shear luck. Now, of course we have to ask the question: "Is this really a problem?" Quite frankly, I don't think it is a problem. As much as I'd love for people to be lining up in the hundreds and thousands to use this android app, it seems very unlikely that we're going to deal with more than about three or four people at once. And that, I think, is being pretty generous...
Tomorrow I will be working on getting some administrator controls up and running. I want to have some way to be able to boot the current user and let an administrator access the robot without navigating the queue. This could be a little tricky, because between the program on the robot and the android app, this thing is getting really complicated. I'm trying my best to make it easy to understand, but at some point that's just not going to be possible to do any more. Even at this point, I don't think a regular, run-of-the-mill programmer could understand what's going on without an in-depth explanation.
The android app is working, but everything is getting exponentially more complicated and more difficult to maintain.
After finally cutting out enough of the inefficiency so that the robot will run properly again, I've encountered another problem. Somehow, I've cut out a vital part of the program and now it keeps letting all the users just "walk to the front of the queue". Not much more to say about that. It's just another problem I need to fix.
Fixing some problems makes more problems.
As the title of this post states quite clearly, I have a serious problem. While I've finally managed to get my program working, I'm now running into an entirely new problem; namely, the robot doesn't move properly any more. The program is actually so slow now that the robot stutters instead of moving smoothly. Obviously, this is going to be a problem I'll have to fix. No one wants to use something that moves like a city bus in rush hour traffic. And, somehow, I doubt the prospect of waiting in a queue to use something that moves like a city bus in rush hour traffic is going to make it any more appealing.
So I guess I'm going to be spending the next little while trimming the fat. And to be totally honest, there's a heck of a lot of fat on this thing.
The program is now so incredibly inefficient that it doesn't run properly.
So I've done some more research into this "networking" problem. By now I've established a clear understanding of what doesn't work. Specifically, Android does not have any clear ways of terminating a program, so I can't run my queue the way I wanted to. Instead of simply sending an "I'm done using the Android Controller." signal, I have to send a very long series of:
Server: "Are you still using the Android Controller?" Client: "Yes." Server: "Are you still using the Android Controller?" Client: "Yes." Server: "Are you still using the Android Controller?" Client: "Yes."
And when the client is finally done, the signals will look more like this:
Server: "Are you still using the Android Controller?" Client: "..." Server: "Are you still using the Android Controller?" Client: "..." Server: "Why aren't you talking to me?" Client: "..." Server: "Is it something I said?" Client: "..." Server: "Because if it's something I said, I'm sorry! I didn't mean it!" Client: "..." Server: "Hello?" Client: "..." Server: "Forget you, Client! I'm going to see someone else! Someone better!!!"
NewClient: "Hey! I want to use the Android Controller." Server: "OK, great! Here you go! You're like, soooo much better than the last guy. By the way, are you still using the Android Controller?"
In simpler terms, my current networking protocol acts like a flaky, overly-dramatic teenage girl. This is why I don't like networking problems. The answer always seems so incredibly inefficient. But this seems like the only feasible way of ensuring two main points: First, that the server recognizes when the client is connected, and second, that the server recognizes when the client has left, regardless of exactly HOW the client left. (Whether it was by voluntary termination or otherwise.)
My original networking protocol didn't work properly and I had to resort to using something much more inefficient and annoying.
Now that the Android Controller works the way we want it to, I'm going to write a queueing program for it. This will allow multiple users to login to the robot without interfering with each other.
I've taken a bunch of notes about the idea, but I think this will end up being almost entirely a "networking" problem. Ah, good old networking problems... I hate them almost as much as that casserole stain in the back of my fridge. You can't ignore it and you can't clean it up properly; the best you can do is try and "deal with it" in the most efficient way possible. In my fridge, I decided to cover up the stain with a jar of mayonnaise. But I can't cover up the networking problems in the Android Controller with a jar of mayonnaise so instead I'm going to use a series of handshakes and periodic acknowledgements to maintain a queue. I plan on working out the finer details tomorrow. And by then, I'll let you know exactly what's going on.
Now that the Android Controller works the way we want it to, I'm going to write a queueing program for it.
One day over a week and it's finally done. Well, not completely, there's always more things I could do to improve it, but like everyone else who's ever written software before, you know there comes a point when you just say it's finished, even if it's not really done.
Bright and early in the morning today I moved the robot around in a circle and drove it up and down the hallway. That was pretty cool. When you spend a long time on something it's nice to see it all come together the way you wanted it to. And it's even better when things start to move along as quickly as they did. It seems like only yesterday I was first getting it to move... Well, maybe that's because it was yesterday. It's all a learning process, I know that, and the more you learn the easy things become, but I have to admit, as a first time user of these phidget things, the learning curve isn't very steep. Admittedly, there's a bit of a jump between when you first start and when you actually connect to the devices and get them to do anything, but it is surprisingly easy to make progress after that. And if we improve the Android section of the wiki and fix all the problems I ran into, it should be a reasonably simple task to get started.
It took me a little over a week of work, but the project is essentially done. If you're sceptical about using phidgets for a project you're working on because you think they'll be too hard to learn, don't be. As the new intern at the company and a first time user, I found it surprisingly easy to learn.
I can't believe I forgot about this, but I haven't implemented the camera controls yet. That's something I definitely need to do to wrap this project up, as it's fairly important to be able to control the camera as well as the actual robot.
So it's been one full week since I started on this project and today was the first day I actually got the robot to do anything. It was quite the experience when I booted up the app this morning and pressed forward to see the robot slowly crash into the table down the hall. It was an equally satisfying and terrifying thing to watch through the webcam. Half of me was thinking “Uh oh... Stop it! It's going to crash you lunatic!” and the other half was thinking “Hahaha! It's alive! It's aliiiiive!” Well anyway, it did manage to stop before it broke anything...
It still needs a little more work, but I've got enough done that I can actually move the robot around now and that's a pretty good feeling. However, I still don't really know anything about the software that's running on that strange metal box. At the current moment, we have to start up some software on the robot itself before we can connect to it. Ideally, it would be nice to be able to start the thing thing up at the same time as the android app. That way we wouldn't have to worry about whether or not the robot is actually on. Both things would boot up concurrently and it would make it a lot easier to deal with. But is that too hard? too impractical? even possible? I don't know.
In the end. I guess what I really want to do with this thing is make it really easy to use. Right now, they've got some kind of joystick strapped to a piece of 2x4 and you have to connect to a bizarre computer interface that doesn't even seem to work on my computer. Is it because I'm using Linux and they're using Windows? Maybe... Or is it because I just have absolutely no clue how that program works? That seems more likely.
Now, with the android app I've almost completed, you'll just be able to start up the app and see everything from the get go. The webcam view will be right there in front of you and the controls will be so easy to use you won't even have to think about. And that's the objective, right? If you have to take time to learn the controls to anything then the controls are probably more complicated than the need to be. (Though it realize this doesn't really apply to everything. Frankly, I'd be horrified if I found out my pilot was controlling the plane form his phone. Intrigued, sure, but horrified nonetheless.)
Anyway, this is the plan: Four buttons in each corner. In the top corners, there's one for clockwise rotation and one for counterclockwise rotation. Then there's a button in the bottom left corner that switches the controls to the camera (so you can pan/rotate/zoom the camera). The last button, in the bottom right corner shows/hides all the controls, so you can make the interface less cluttered and see more of what you're doing. The webcam feed will take up the entire screen so you can see what you're doing and there will be a little red dot in the center of the screen to make it easier for the user to know where to put his finger.
The robot actually moved today and I made more detailed plans for the user interface. Simplicity and intuition should both play a large part in the design.
The last two days were spent translating the existing C# code into Java code. I've never actually written anything in C# before, so it was a bit confusing at first, but the two days I spent on it were enough time to figure out everything I needed to figure out and by the need of the second day I had all of it translated into Java so I could use it in my Android app.
One thing that I discovered today is that this is an excellent way to learn how to use all the different phidgets. When you're translating code like this you get an opportunity to learn a bunch of different things. First, you learn how to use the language that you're translating from, in this case, I learned how to use C#. Second, you learn how to use the language you're translating to. Of course, I already knew a lot about Java, but I can't deny that I learned a little bit more about it from the experience. And lastly, you learn how to interact with the phidgets in both languages. I think this is a lot more useful than learning how to interact with the phidgets in just one language because, although you may gain a greater understanding about that one language, you actually learn how the individual functions work and what exactly they all do.
So I really would encourage some of you to try and do this once or twice. It's definitely a difficult thing to do, but you learn so much that it's well worth the time and the effort. Just make sure you use two different languages that you actually want to learn about. There's no sense in translating from Visual Basic to Java if you hate Visual Basic and you never use Java.
Translating code from one language to another is a time-consuming, but valuable learning experience.
Friday! and the last day of my first week here at Phidgets.
I didn't accomplish as much as I would have liked to on the Android app, but I did read a bit more into the Android Developer site and tried to figure out how to do different things with the interface. I got some buttons to do interesting things like show and hide other buttons and I played around with the layouts a bit... But as it turns out, setting up the layouts for all the different kinds of Android devices you might use is really difficult. You inevitably have to write several different cases and use different layouts for all the different screen sizes, something I didn't ever think I would have to deal with. I guess I'm just so used to the formatting tools available for web pages, like css where everything is so easy to change, that I'm having a hard time believing that the layouts are so difficult to set up in Android. Perhaps it's something they need to work on or maybe I just need to learn to get used to it.
On another note, we had a barbecue at work today, which was a nice change from the boring sandwiches I usually pack in my lunch. Lately, I've felt like packing a lunch is something I do more because 'I don't want to die of starvation' and less because 'I actually want to eat what I pack in my lunch'. I don't imagine I'm the only one that feels that way, but it's all the more reason I appreciated the barbecue today. However, I did have to wonder why they seemed to think "out back, between two dumpsters" was the best location to hold this event...
Android doesn't a very good job when it comes to developing applications for multiple devices and if you want your code to work on everything from tiny phones to big tablets, you have to be willing to write a lot of code. Also, the city of Calgary should really put a park next to my workplace.
Spent most of the day today trying to get Android to work with Phidgets. It's very frustrating when things simply don't work, but I'm sure each and every one of you know exactly what that's like.
The worst of it was that none of the examples in the wiki were working! The code that the guys in the office wrote just wasn't working no matter what I tried to do. Moreover, some of the code the wiki tells you to download code that doesn't exist! Well, that's obviously something we need to work on and I suppose it's all the more reason we need to be doing more stuff like what I'm doing right now. It shouldn't be a challenge to the examples to work.
All ranting aside, I figured out what the problem was by the end of the day. As it turns out, android doesn't seem to recognize your libraries unless they're in the "libs" folder. That's right, even though the examples have the "phidget21.jar" and "PhidgetsUSB.jar" files in the root of the directory, you have to put them in the "libs" folder instead. Otherwise your app will simply crash as soon as it starts up, which is really frustrating. After I did that, all the examples worked and I even got my own application to recognize the phidgets in the robot.
That's one step forward I guess.
The Android section of the Phidgets wiki needs some work.
So the guys in the office came up with a great idea for the robot they've made. They want to make an Android app for it. We could put this app on a smartphone or a tablet and use that as a controller for the robot. Being the new intern here at Phidgets, I was sent to work on it almost as soon as I walked through the door. I wasn't about to complain. At my last internship, my first assignment was to read hundreds of pages of legal agreements and safety manuals. This was a lot more interesting.
I started the day off getting together all the necessary tools for my endeavour. I've never done any programming for Android before, so I really had no idea where to start. Thankfully, Android makes it relatively easy. They've put together a developer training website, as they seem to call it, with a ton of detailed instructions to help you get started. I'm a staunch Linux fan-boy when it comes to any kind of programming work, so I followed the instructions for getting set up on Linux.
The Android website recommends using Eclipse, a program I learned about, and simultaneously learned to hate, in university. It's not that it's a 'bad' program. Eclipse can be very useful sometimes, but I've just found it to be too bulky and awkward to deal with for most of my projects in the past, so I wasn't entirely enthusiastic about their suggestion. But, as I mentioned before, I really had no idea what I was doing at this point, so I just followed along blindly.
One of the great things about Linux is that most of the well-known programs are notoriously easy to install. I use a distribution of Linux called "Linux Mint" and the process of installing Eclipse was as simple as typing "sudo apt-get install eclipse" into a terminal. Ten minutes later Eclipse was installed and I started up the program and frowned unhappily at the familiar, yet still loathed Eclipse environment that popped up in front of me.
But I continued to follow along regardless and advanced on to the next step, installing the "Android Development Kit". And though I still didn't like Eclipse, I couldn't help but smile at how easy it was to install the ADK. A point and a click later and I was done. Great, next step.
The Android website then asks you to install updates; however, I decided that I didn't want to do that and I just went on to the next step, writing my first app. A couple of hours later, I had a very simple Android application working on both my Android emulator and my Android tablet. I was even beginning to like Eclipse. Eclipse does a wonderful job of showing you exactly what you're going to see on screen when you actually run your app. It also helps you find the right libraries and imports them all automatically. Happy with my progress, I thought it was about time to start working on the real thing.
But before I went any further, it was time to update eclipse, the one step I had skipped earlier. And despite all my accomplishments today, this is where all my past eclipse experiences came flooding back to me in a torrent of nightmarish flashbacks. The Android website tells you to update eclipse, so that's what I did... Well, that's what I tried to do anyway. When I clicked on the update button, Eclipse popped up a window that showed me all the packages that needed updating. No problem, right? Just click on all of them and say OK. Well, that's not how it went down. Eclipse said, "No. I don't want to update." and crashed. I frowned and tried it again. And again, it crashed. "OK", I thought, "Let's try updating the packages one at a time instead. I'll just skip over the one that won't update." Well, to my surprise, this actually worked and somehow I got all of the updates installed.
But then everything went wrong again. Somehow the updates destroyed the entire ADK and now I couldn't get any of my android apps to work again. After trying to get everything working again and having no success, I simply reinstalled eclipse and skipped over the update step permanently. I supposed it would just be one of the quirks I would have to deal with.
For the amateur Android programmer, the introduction is an 'almost' painless process. Android's guide is well written and clear, but even they can't accommodate for the failings of programs they have no control over. So if you're new to Android, but fairly familiar with programming, you shouldn't have too much of a problem getting set up.