Sunday, March 25, 2012

Naive Control Test

Now familiar with BricxCC and the HTWay, it's time check the new platform's operation. I'm trying to get as close to a balancing code as possible with an accelerometer, but not worrying about it too much until I acquire the latest Matlab. In the meantime, this should bring to light a lot of other considerations that will need to be evaluated and handled in the final control. To get this naive control to work adequately, I'll try using Ziegler-Nichols tuning on a basic control that maps angle to motor speeds. First, a word on the tuning method.

Ziegler-Nichols Tuning Method


J.G. Ziegler and N.B. Nichols in 1942 published "Optimum Settings for Automatic Controllers" as part of "Transactions of the ASME". In it, Ziegler and Nichols developed time domain and frequency domain methods of determining appropriate tuning values. These values are based off of step response and frequency response characterizations of the system's dynamics. Consisting of relatively simple rules, its easy to apply the method to many different problems. For a complete discussion of Ziegler-Nichols tuning, I suggest looking into the wikipedia article, and the original ASME article republished with permission at http://www.driedger.ca/.

For my process, I decided to follow the frequency response method. I attempted to identify the critical oscillation gain, the gain at which the robot oscillated around the upright balanced position, and the period at which it oscillated. To determine this value, I ran a simplified version of the code below with only the proportional factor controlling the output. I varied the values of the proportional gain until the platform began to oscillate nearly around the point of balancing. I found this value to be 1.25. The period at which it oscillated was estimated to be 200 milliseconds.

Naive Control


After some trial and error I was able to put together the code at the end of this post, a simple implementation of a PID controller in NXC. Let's go through stanza by stanza and I'll explain what's going on, the intent behind the code, and considerations for future implementations.

Lines 1 through 5 defines the bound function. This function returns the value of x bounded by an upper and lower value. Since the motors should only be set with values between -100 and 100, we'll use this to limit its actuation.

Line 7 begins the main task. This is the first task that is run on the NXT. Tasks are similar to threads or parallel processes. We could have multiple tasks for sensing and actuation for potentially better performance. For more complex code, I'll revisit this idea.

Lines 8 through 23 declare the variables needed:
  • Integers
    • angle - The angle is represented by acceleration expressed in the forward and backward horizontal plane of the robot in gs divided by 200.
    • deltaTime - The approximate time between each iteration of the main loop in milliseconds. This is set to be 50. A known delta value is used to control the loop speed so further analysis can take place down the road.
    • error - The difference between the idealAngle and the sensed angle in gs divided by 200.
    • garbage - Not used for anything constructive. This is necessary when acquiring data from the accelerometer.
    • idealAngle - The sensed balanced acceleration value in gs divided by 200. Due to the weight distribution of the hardware, the robot needs to lean a little forward to be balanced. Thus, this is set to 9.
    • lastError - The last error value from the last loop iteration in gs divided 200.
    • overheadTime - The time in milliseconds the sensor acquisition, calculations, and motor settings need to complete. Using the commented lines, I was able to determine this to be about 16 milliseconds.
  • Floats
    • derivative and integral - The derivative and integral values from the PID calculations.
    • Kc and Pc - The critical oscillation gain and period. Specifically, Kc is the minimum proportional gain necessary to oscillate the system as described in the last second. These are set to 1.25 and 200 respectively.
    • Kp, Ki, and Kd - The proportional, integral, and derivative gain values. Note that the derivative gain is set to zero. Derivative terms can add a lot of noise to a system, so this is left out for now.
    • output - The output from the PID control.
Lines 25 through 27 initialize the proportional and integral gains using the Ziegler-Nichols tuning method. The critical oscillation gain is multiplied by 0.45 to determine the proportional gain. The proportional gain is multiplied by 1.2 and divided by the period to get the integral gain.

Lines 29 and 30 initialize the accelerometer for reading. This could take some time, so a brief wait is called after the initialization.

Lines 33 through 36 find an initial last error value by reading the accelerometer and finding its difference from the ideal value.

Lines 38 and on are the main loop of the program. All lines that have NumOut(...) are debugging output that gets printed to the NXT's LCD screen.

Line 40 forces the loop to wait an adjusted value to match an actual delay nearly the set delta time.

Lines 49 through 60 find the sensor value and calculate the PID controller's output.

Line 63 sets the motor speed. Note that the output is multiplied by -1.0 because the motors are mounted backwards.

Running the Code


Running the code on the platform has made it apparent the accelerometer alone is not sufficient for balancing. The accelerometer is sensing the acceleration the robot is under. Our axis of interest is the forward-back horizontal direction. In the presence of gravity and no other forces, the acceleration could be directly mapped to an angle accurately. But because the robot is actually under many forces, most importantly the motor driven wheels keeping it balanced, the acceleration in our axis of interest will be the result of all these forces. Another sensor is necessary.

A piezoelectric gyroscope is a sound alternative. Mounted in the appropriate axis, it can be used to detect the speed at which the angle of the robot is changing. This could be used to accurately determine the robot's angle. With more effort, this could be used in conjunction with the accelerometer for even more accurate sensing. I've placed an order for the HiTechnic gyro sensor I discussed in my last post. It should be arriving next week. I'll adjust the controller and try again with the gyroscope.

Next week will be a short week for work on the project. I'll be mentoring the FIRST Robotics Competition Hartford Regional, but I'll try to get as much done as possible.

Source Code


1   int bound(int lower, int x, int upper) {
2     if (x < lower) {return lower;}
3     if (x > upper) {return upper;}
4     return x;
5   }
6
7   task main() {
8     unsigned long tick;
9     int angle,
10        deltaTime = 50, // must be >16
11        error,
12        garbage,
13        idealAngle = 9,
14        lastError,
15        overheadTime = 16;
16    float derivative, 
17          integral = 0,
18          Kc = 1.25,
19          Kp = 0,
20          Ki = 0,
21          Kd = 0,
22          output,
23          Pc = 200.0;
24     
25    Kp = 0.45 * Kc;
26    NumOut(10, LCD_LINE1, Kp);
27    Ki = 1.2 * Kp * deltaTime / Pc;
28     
29    SetSensorLowspeed(S4);
30    Wait(50);
31
32    // read sensor (15 ticks)
33    ReadSensorHTAccel(S4, angle, garbage, garbage);
34  
35    // set an initial last error
36    lastError = idealAngle + angle;
37
38    while (true) {
39      // wait
40      Wait(deltaTime - overheadTime);
41     
42      NumOut(10, LCD_LINE1, Kp, DRAW_OPT_CLEAR_WHOLE_SCREEN);
43      NumOut(10, LCD_LINE2, Ki);
44      NumOut(10, LCD_LINE3, Kd);
45     
46      //tick = CurrentTick();
47 
48      // read sensor (15 ticks)
49      ReadSensorHTAccel(S4, angle, garbage, garbage);
50 
51      // pid calculations (0 ticks)
52      error = idealAngle - angle;
53      NumOut(10, LCD_LINE4, error); 
54      integral = integral + (error * deltaTime);
55      NumOut(10, LCD_LINE5, integral);
56      derivative = (error - lastError) / deltaTime;
57      NumOut(10, LCD_LINE6, derivative); 
58      output = (Kp * error) + (Ki * integral) + (Kd * derivative);
59      NumOut(10, LCD_LINE7, output);
60      lastError = error;
61   
62      // set motor speed (0-1 tick)
63      OnFwdSync(OUT_AC, bound(-100, output * -1.0, 100), 0);
64   
65      //NumOut(10, LCD_LINE1, CurrentTick()-tick);
66    }
67  }

Sunday, March 18, 2012

BricxCC and HTWay Analysis

Now that I've identified BricxCC is a workable environment, it's worth looking into a bit deeper. Bricx Command Center, or BricxCC for short, is an integrated development environment for programming LEGO microcontrollers, such as the NXT. It provides a lot of great tools for operating the NXT. I've found a lot of utility with the direct control tool, the file explorer, and the register watcher while experimenting deploying code to the NXT. I also came across a very interesting similar project online that's worth comparing parallels with.

HiTechnic's "HTWay"


HiTechnic, a 3rd party sensor manufacturer for the Mindstorms platform, has also created a self balancing robot. Here's a video overview of their design in action.



Their robot is similar in design to what I'm working with. At it's heart, it build from LEGO Mindstorms components including the NXT. Their version is more complex including remote control via a infrared remote, and they have added considerations for when the robot has fallen over, and allows you to adjust the wheel sizes when starting the program for the first time. They are also using a gyroscope to detect their robot's tilt angle and velocity. For more information on the HTWay, take a look at their blog page, which also has links to build instructions and code in different languages.

HTWay Control Law


From the NXC code, here is the control law that keeps this balanced.

power = (KGYROSPEED * gyroSpeed + // Deg/Sec from Gyro sensor
    KGYROANGLE * gyroAngle) / ratioWheel + // Deg from integral of gyro
    KPOS * motorPos + // From MotorRotaionCount of both motors
    KDRIVE * motorControlDrive + // To improve start/stop performance
    KSPEED * motorSpeed; // Motor speed in Deg/Sec

The control law takes the gyro's velocity and angle as well as the motor rotation and velocity. The variable motorControlDrive is used as part of the remote control system of the robot. For this analysis it can be considered equal to zero since my project doesn't include any remote control. The gains, set as macros, are given and not calculated. There's no background information as to how those were chosen that I came across.

The state space model that my hardware is based off of, originally discussed in 2009, is very similar to this. My state is defined as the derivative to angle and the angle itself, as they have in their control respectively. This is promising that this is a sound state to be using. And in fact, if I were concerned with where the robot was, or how fast it was traveling, I could also add the position and velocity of the base. Since I'm not doing any remote control, this can be neglected, and left perhaps as an opportunity for expansion later on.

Sensor Considerations


Another interesting piece of information that has come out of this evaluation has to do with the gyroscope. When the gyroscope is run over time, it tends to drift. One way of combating this is using a filter before determining the angle. The NXC code for this on the HTWay is this.

gyroRaw = SensorHTGyro(GYRO);
gOffset = EMAOFFSET * gyroRaw + (1-EMAOFFSET) * gOffset;
gyroSpeed = gyroRaw - gOffset;

gAngleGlobal += gyroSpeed*tInterval;
gyroAngle = gAngleGlobal;

In this code, the raw value from the gyroscope is read, then passed through a filter in the form of a weighted sum to determine the "true" offset. The offset is used in calculating the speed of rotation. The macro EMAOFFSET is given as 0.0005 and not calculated. Conceptually, the majority of the "influence" over the "true" offset value is driven by the previous value of the offset. This further enlightened me to the fact that sensors are faulty and need to be accommodated.

Unfortunately, I only have an accelerometer on hand. I will attempt to work with it before ordering a gyroscope. If it comes to using a gyroscope for tilt angle calculations, I will attempt to leverage the accelerometer I have to aid in the gyro's drift accommodations.

Sunday, March 11, 2012

Short Week on the Environment

Thursday, Friday, and Saturday of this week I was in Worcester for the FIRST Robotics Competition, WPI Regional. A big congratulations to FIRST Team 3182, Athena's Warriors, for placing 5th and making it to the first round of the finals. Excellent job team! Let's keep it up for Hartford at the end of the month! :)

Environment Work


Even though my focus shifted to FIRST at the end of the week, I was still able to begin preparations of my environment for programming the NXT. It was painfully obvious during my first LEGO project that the environment provided by LEGO was not robust enough to handle my needs. Despite being based off of LabView, the simplified interface did not provide enough utility to perform advanced functions.

Matlab and Simulink are going to be a big part of this project, so without a doubt this is the desired interface. Fortunately, Matlab 2012a includes libraries for the NXT and it's most popular accessories. Unfortunately, my computer has 2010a. It is possible to use RWTH, another NXT toolbox, with this older MATLAB version, but all my efforts haven't been able to configure this correctly. For now, when I try to run Comm_OpenNXT from the command window to begin communicating with the NXT, the function returns the following error. The NXT is attached appropriately and has been reset. Tracking this down online hasn't turned up anything useful either.

No NXT found on USB bus! Make sure the NXT is turned on and access rights in /dev/ are
properly set. Rebooting your NXT might help!

Rather than lose more time on RWTH, I decided to begin experimenting with BricxCC while I get a copy of the latest Matlab. BricxCC is an integrated development environment for working with NXTs as well as many other hobbyist controllers. In this environment, an NXT is programmed in a language called "Not Exactly C" (NXC), which borrows a lot from C, but has a much more narrow, restricted focus on NXT programming and includes a very substantial API. For example, NXC introduces a new keyword task which when managed correctly allows the programmer to easily create parallel threads.

So far I have been able to install the software and compile a basic program. Next week I will look into writing meaningful code and deploying it to the NXT.

Project Registration


I stopped into the Registrars Office this week to see Dottie. She helped me finish my project registration and gave me some other graduation materials as well. I am now registered for the project and will prepare my graduation materials soon.

Sunday, March 4, 2012

Particle Swarm Optimization

Since a portion of my project will be dealing with evolutionary algorithms for optimization, I decided to revisit the Particle Swarm Optimizer (PSO) as a potential tool. I first became acquainted with this algorithm in my undergraduate research. In that project, we used the optimizer as a way to choreograph the movements of the robots themselves. I also engaged the optimizer in my graduate optimal control theory class as the basis of a project, creating a visual simulator for a 2 dimensional search space.

Research Double Duty


As a mini-project to incite further research into the PSO, I decided to overlap my efforts and use this extended research as material for a technical presentation as part of an interview for employment at the United Technologies Research Center. Here is the teaser for the talk.

The Particle Swarm Optimization (PSO) algorithm is a simple process for optimizing functions. Discovered by a social psychologist and an electrical engineer in the mid 1990s, it is inspired by naturally occurring social behaviors. Although much more research is necessary, it performs well with benchmarks such as the Rastrigin and Rosenbrock functions. It has seen exponential growth in adoption since its creation due to its relative ease of use and potential impact on many science and engineering fields, such as medical, electrical, financial, and control systems.

In this talk, we will explore the PSO algorithm, briefly touch its background, primarily focusing on its structure and operation. We will also visually explore its performance with benchmarks and interact with its tuning values. We will investigate the algorithm’s application to swarm robotics problems, taking time to identify implementation strategies based on the swarm's purpose and constraints.

For more information on the PSO and to explore my resulting presentation materials, check out the links below!

Individual Files (Google Docs)
Teaser and Bio
Outline
Slides
Slides (Printable)

Everything, including simulator binaries and presentation sources (Dropbox)
UTRC Tech Talk

Project Application


After reacquainting myself with the PSO for this project, I have identified how best to use the optimizer. I intend to tune the feedback gains to some reasonable values based on it's performance over a model of the robot that I derive. The optimizer will use a cost function that maps gains to settling times, the amount of time required for the robot to stay within 2% of it's stable orientation. It is important that the derived model include such non-linearities as motor maximum speeds to ensure that the gains identified by the PSO could reasonably be implemented on the hardware.

Registration


Also, Dr. Eberbach informed me he passed along my project registration to the registrar on Monday. I plan to head in there this coming week to finalize it with my signature.