This week was almost entirely taken up by testing the code for the Hackathon competition coming up on July 15th. My coworkers and I were tasked with debugging the current code for the competition and gauging just how difficult the competition would be, and if there were enough resources to complete it in the given timeframe. Monday was the day we were meant to start, but there were still some adjustments to be made before the code was ready to test. I spent most of the day working on a style guide for new features in C++11- we recently upgraded our project's configuration files to allow for it and planned to use it for our future code, but we needed a style guide in order to have more readable code. The rest of the week, however, was filled with testing various aspects of the Hackathon competition as it currently is set up, a month before the real competition. Tuesday was hardware setup, getting the tracking cameras functional and checking to make sure all the connections were working and the rovers were functional. Wednesday was a bit more active, testing the basic software setup, adjusting it as needed, and communicating the fixes to the person developing the competition. By the end of the day, it was functional enough to begin the real test of the competition itself. Thursday and Friday were the two days we were allotted to actually test the competition and see how much we could get done in the time frame. We initially worked out the problem space and discovered limitations in the physical setup, drawing out a border to the area we could safely drive the rovers. The rest of the day was dedicated to working out different methods of getting the rover to precisely follow a path when the position and orientation information updates from the cameras were so slow. By the end of the day we had two methods, one that I had designed which utilized the default constant-frequency logic loop and added a timer to the position update handler function. The rover would use the amount of time since a position update as a way to have a motor cutoff point- if it hadn't received an update in under the certain amount of time, the rover froze in place until it got a new one. The other method was designed by another coworker who was familiar with the codebase. It instead removed the constant-frequency timer aspect of the mobility logic function and directly called it from the position update handler. This way, the rover would react instantly to a position update, but only when it received an update. It also had a motor cutoff time, but this was a constant amount of time after receiving an update. This was a technically more robust approach for making sure the rover only moved when its position information was valid, but I took issue with the inability to use this method of approaching rover mobility because it did not allow for the constant-time updates required for precise movements, used when picking up and dropping off blocks. We left the office while still disagreeing on which method to use. The next day, we came together and it was agreed, after some discussion with other members, that we would use the constant-frequency update method combined with a tuned speed such that the rover would move a shorter distance the further away in time it was from a position update. After some testing, this method allowed us to follow a path precisely enough for our needs, and it could also pick up cubes we had scattered about the area, so we deemed it satisfactory and continued on with the little time that remained. The next task we chose was to follow a particular tag that indicated the position of a block. This turned out to be a bit more difficult than we initially suspected, since the tag location was given a unique channel for the rovers to listen to rather than being given as a part of a collection of tag positions. We eventually did get this working, though by the time we did, there was only an hour left in the day to implement obstacle avoidance, path planning, and cube return. We didn't finish, but that wasn't the goal; we got plenty of valuable information for the competition's developer, and we got some experience working in the competition so that we can help others with technical issues and questions during the real Hackathon.
0 Comments
The First Two Weeks... This post is a little bit behind, but it has been a busy and productive first two weeks here at University of New Mexico!
The first day after arriving, we were already getting to business with our tasks. There was some discussion and we unanimously decided that the codebase was in serious need of a refactor and an update to a more modern version of C++, C++11- so we jumped right in, not wanting to waste time. The other DREU participant who was assigned to the same task had never touched the codebase before, so we spent some time bringing him up to speed and doing a cursory check over the main module ourselves. I had participated in the Swarmathon competition for the previous two years and was fairly familiar with the codebase at this point, so I had started brainstorming ideas for the refactor. We decided that the main module took on far too much responsibility and did not handle the smallest amount of functionality that it should have at that point. What we decided on initially was to split that functionality into several main Controller classes- SearchController, PickUpController, DropOffController, and the new ObstacleController. Each of these controllers would then be fed input from various signals received from the ROS ecosystem (camera and ultrasound information, mostly) and would determine if they needed to send an interrupt signal to the main loop running in the primary module. If they did, then they would be given some amount of control over the rover's driving, until they no longer needed to interrupt the main driving behavior. By the end of the first week, we had implemented this system and gotten it mostly working- I took the DropOffController refactor and helped design the ObstacleController code. Partway through this initial stage of refactoring, I had noticed a similarity with this system and how an operating system's kernel will register interrupt handlers for various hardware and software interrupts. The main difference was that the modules controlling the sent interrupts also controlled the handling of them. Noticing this similarity and pointing out that hard-coding the order in which interrupts were handled was not particularly beneficial, I proposed a generic system in which all Controllers implement a shared API, represented with the Controller abstract base class. You could then register controllers into a priority queue, where the priorities could be modified in data instead of in code. This way, instead of switching the code path taken using conditional statements, a simple re-assignment of priorities would allow for different behaviors at different stages of the robot's control. This became the task of the second week. We verified that our changes from the first week still created the same behavior as in the base code, and then created a new Controller type, the LogicController. LogicController itself implemented the Controller interface (potentially allowing for recursive strategies of control), and is responsible for the management of other controllers, passing them information and determining what is to be done with their output. This was the most complex portion of the refactor and is still not complete after the second week- it involves taking almost the entirety of the 1000+ line mobility.cpp file's functionality and passing it on to the various Controllers, and making sure that all the states and transitions still behave as they did before. At our Thursday tech meeting, one last change was proposed in which we eliminated all ROS dependencies within the Controller framework and moved them to another module, and also moved the remainder of mobility.cpp's functionality (at this point, only the functionality relating to actually driving the rover from waypoint to waypoint or sending out precision driving commands) into a new Controller, DriveController. These changes make the entire module independent of the environment it is implemented in, and remove the need to understand specifics about it. This way we can focus entirely on the algorithms we are meant to implement instead of quirks in the simulation or operating system. While we did not make much progress in the implementation of the DDSA directly, these changes will make that implementation much easier and much quicker, and will lead to more maintainable code for the future. |
AuthorKelsey Geiger: a maker, learner, teacher, and doer. Proud to be out and proud of her work. Archives
August 2017
Categories |