This document describes the process of writing the BasicPlayer and BasicCoach on a day-to-day basis. It is meant for me to remember the different choices that I made in the design and for other people to get an idea of how the project came to be a reality.
I programmed the assignments for my project and removed many bugs. Some we're quite serious (invalid object positions and angles). I also wrote a simple coach, but it is almost trivial. I released the new sourcecode. I won't spend more time on this software, so if you want to add a feature, request to become a member of the basicsoccer project group at www.sourceforge.net, program the extension or fix and release the code.
I spent the last few days implementing my own agent to intercept the ball, and I found a number of problems with my BasicPlayer. Because debugging took so long, I decided to write a small visualisation routine to be able to check some of my code.
I decided that I won't need a coach to implement my own players, so I dropped it. Furthermore I got the program pasdoc from the internet to make documentatie. It isn't very good, because to get good documentation you'll get bad (not very readable) code. So I commented the code the best I could, and just generated the simple documentation.
While making the documentation, I saw some inconsistencies in the code that needed to be fixed. Furthermore, because the BasicPlayer is now officially released, I need a better website. I converted all my code to follow the Object Pascal Style Guide (I simply use the free formatter by Egbert van Nes). It made some of the code less readable because now line contains more then 80 characters, but I think it is for the best to adhere to this standard even when it doesn't look great.
I wrote extra code for the positioning of objects. Not only does the code now calculate you one position, it also uses its own position to get an (X,Y) for all movable objects (players and the ball). For seen objects, the angle and distance is used to calculate the (X,Y) and for unseen objects the (X,Y) is used to calculate the angle and distance. While I programmed the code, it became clear to me that I had to reevalute my coordinate system: there was no logic. I should have given it some extra thought two days ago. I rewrote the code for getAbsFaceDir, the localization of the player and made some helper functions for the transfer between absolute and relative angles. Released the source code version 0.9.1.x.
Because the positioning now works, I programmed a function to calculate all the angles and distances for the static objects that are not seen (flags and goalposts). The reactive player now works and I think it is time to release the first version of the source code (version 0.9.0.x).
I began programming on the code to determine the absolute position of the player. However, I first wanted to completely understand the algorithm with the lines and flags. It was not that hard, but for calculating the absolute angle for the player, I have a difference of Pi for the upper and lower line with the AT Humboldt 98 code. If I place the player somewhere on the field and only make a 'turn' and next readout the absolute angle information, my version just normally walks from 0 to 360 degrees. However, I needed to change the calculation of the absolute position, so I think the AT Humboldt 98 used a optimalization. The bottom line is that the absolute positioning now works. The main difference is that the direction of the player is expressed in degrees from 0 tot 360 and not from -180 to 180.
After some more serious thought, I decided it would be best to remove the reference count on the visual objects. If I really need it, it's easily added, and the code doesn't need to be in there right now. I programmed the flag and goal definitions, so these can be used to determine the absolute position of the player.
After a talk with one of my colleagues, I came to the conclusion that the referencecounter for the visual object wasn't really necessary, because normally the list returned from getOVList is Free'd before the next see-messages are processed. However, I'm gonna keep the code it. Maybe somebody will use it for something useful.
I also implemented a confidence for every visual object. When an object is seen the last time iteration, the confidence level is 1. Every movable object has a decay rate from 0.0 to 1.0 to update the confidence every iteration. This makes sure you can program a player that doesn't chase 'ghost objects'.
Furthermore, I implemented the minimal send interval (send only one message for every X milliseconds). This uses the windows.pas GetTickCount. Therefore, maybe this has to be changed to support Kylix.
Made code to parse all the information in the sense_body message and processed angle and distance info from normal see messages.
At last I completed enough code to make a simple reactive player. The player runs to the ball, and kicks it towards the goal. And it works!
The only problem are the immovable objects: I need the absolute positions, so I can calculate the position of the player, and with that information calculate which way to dash and kick. But this is for tomorrow.
Because the Visual Object Memory should work, I was ready to program some tests. However, the soccerserver gave ‘command error’ for every command. After some searching an debugging, I concluded my UDP implementation was too simple. The code from Klaus uses a special class to be able to handle changing ports for UDP/IP. Fortunately, TIdUDPClient from Indy also supports this technique, and I was able to change my code to handle changing ports. I wrote a simple test program to let the player dash,turn,dash,turn,etc. The Visual Object Memory can now be tested.
Worked some time to get the website up and running and adding a counter. Programmed the see flag messages.
Made a Visual Object Memory list that can be updated. I added an isEqual function to all TvisualObject descendents, so the list can be easily updated. Programmed hear and sense_body messages and the see ball, player, line and goal messages.
I registered my project with SourceForge. Furthermore, I defined the different TvisualObject classes and started on parsing the received messages. I decided to use sets (TKindSet) and not C masks (with all the or’s and stuff), so I rewrote the TvisualObject implementation.
I created a TbasicPlayer object and started defining the different procedures that should be implemented: turn, dash, etc. I used the C++ API from Emiel Corten to guide me. I also typed a lot of constants for ball, objects, sides, etc. Furthermore, I decided to design the Visual Object Memory with objects, that all descent from TVisualObject. Also made a send routine, to be able to send commands. Wrote the implementation of the basic actuator commands.
After another day at the University of Amsterdam, sitting behind an old Sun Workstation, fighting with emacs and the standard GNU C++ installation, I just was completely discouraged. I would need to be behind this computer for many more days, just trying to get my little RoboCup soccerplayer to work. I used a standard BasicPlayer and BasicCoach library that was written by Emiel Corten. The API was very well documented, but I wanted to do this project at home, with my own fast computer and the familiar Windows interface. I decided I should make my own RoboCup soccer simulator environment in Windows. That evening, I searched the Internet for some programs (Internet at home is FASTER than internet at the University: that’s sick!) that I could use. I found a soccerserver for Windows, and Klaus Dorer had written a soccer monitor and a basic player and a basic coach. Everything was written in C++, but I wanted to use Borlands Delphi. With the introduction of the free Kylix for Linux, I knew many people will switch, because Borlands products are very friendly to the user, with a great IDE and standard library.
I started analysing the project with the different modules that have to be programmed. There are the BasicPlayer and the BasicCoach and some helper modules (for instance the Visual Object Memory). I got the soccerserver, monitor and basic player (from Klaus) up and running and checked if the program worked ok. The next step was using the Indy components to try to connect to the soccerserver using UDP. I wrote a program that sent an ‘init’ and saw it worked.