Coercing More Effectively

Coercion’s blade needs a lot of work – I think the video of Ripto bending it 30 or so degrees proved that. The question is how to change it. I know Coercion is a good bot, but I have noticed some continual flaws. First of all, the blade is too heavy. It spins up too slowly and it takes way too much work to get up to speed (thanks to losses all over the place), so the weapon motor runs hot and pulls something in the 30A neighborhood. I thought I had more or less fixed the problem before Bot Blast, but running my robot on 7.4V made it far more sluggish than I anticipated and I still wasn’t getting ideal blade performance. The blade is also so heavy that it tends to flip over its nose, which provided a loss at Boy Blast. I have decided to apply some physics to make Coercion more hard-hitting and hopefully more efficient than ever.

Erotational = Iw^2/2

Where omega (henceforth referred to as w) is angular velocity, E is kinetic energy, and I is moment of inertia.

Awesome, so based on that, we can do one of two things to increase the kinetic energy of the weapon:

  1. Increase the angular velocity (how fast the weapon is spinning). This will be the more effective of the two methods because it is a squared term, so if we double the angular velocity, we quadruple the kinetic energy.
  2. Increase the moment of inertia. MOI is the sum of the masses of the particles that make up an object multiplied by the radii from the center of rotation squared. In other words, the heavier something is, the greater its MOI, and the greater something’s diameter is, the greater its MOI.

So there we have it. To make Coercion’s blade work better, we make it heavier and spin it faster. Great physics lesson, Einstein. The problem here is that to make weight for better wheel guards, a better weapon motor, new batteries and the other improvements I have planned for Coercion, I need to make the blade lighter. Remember that MOI is also based on the distance the particles of an object are from its center of rotation. Thus, if I can concentrate the mass as far away from the center as possible, I can “cheat” (not really) a little bit: the blade will hit harder while not weighing in any more.

My target weight of the blade was 11ish ounces, which is about a big reduction over the old blade. I had to make the inside as skinny as possible while making the outside part as wide as possible. I kept the same blade dimensions – 11.75″x1.50″x0.19″ – and I plan to have this blade waterjetted out of S7 and then hardened (I learned my lesson at Bot Blast!).

New Coercion Blade

10.35oz, far lighter than the old, nearly-one-pound blade.

The plan is to spin this blade at 10,000rpm with a 3S LiPoly and a new weapon motor in the 1500-1900kv range (and a new, 2:1 weapon gear ratio). If I recall correctly, Coercion’s blade was spinning at about 7000rpm at Bot Blast, and according to the MOI differences I saw in Solidworks (the new one has about a 22% lower MOI than the old one), the new blade will actually store about 50% more energy. Not bad for saving three or four ounces, huh?

Quotebook, a Grotesquely Over-complicated Version of a Program I Wrote for a Quiz

Last week in my video game development class (which is an introductory-level course on Python 3 with some focus on games), we had a quiz. We had to talk about some things we’d learned, describe the intricate differences between Python’s if, elif and else statements, then write a program. The program intrigued me: the goal was to “simulate a fortune cookie” and display one of five different, pre-determined strings at random.

My first reaction was relief that I was going to be able to write the program with little issue. My second reaction was how incredibly far I could take that idea. An entire social network materialized in my head; a place where people could go to share and discuss quotes or fortunes. Then I realized that I was crazy, but I did decide to make some changes to the program we’d written in my spare time:

  1. Create an online component that would allow anyone to submit quotes to the “fortune cookie”. The “cookie” has become a system that I call Quotebook, for lack of a better name.
  2. Create a Python client for some kind of bare-bones Quotebook API that would accomplish the same task as the quiz program, except after retrieving the quote from Quotebook.

I knew the Python part would be the easy part, so I fired up Visual Studio and got cracking. I used most of the default template but changed the top text and removed the menu. I kept the HeadLoginView and all the other assorted login-related items so I could use the Membership class to attribute submitted quotes to a user. I also added a database to the project and created a table called quotes. Quotes has four columns:

  1. id (int)
  2. byUser (nvarchar)
  3. timestamp (timestamp)
  4. quoteText (nvarchar)

On the homepage, I added a big TextBox and a submit button. Then, I wired it up to write to the database:

protected void btnSubmitQuote_Click(object sender, EventArgs e)
{
    if (HttpContext.Current.User.Identity.IsAuthenticated) // Make sure user is authed before writing bad things to DB
    {
        // Connect to the DB
        SqlConnection sconn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["messageDB"].ConnectionString);
        sconn.Open();
 
        // Create the command to insert the values into the database
        // PARAMETERS are used to STERILIZE all inputs.
        SqlCommand scomm = new SqlCommand("INSERT INTO quotes (byUser, quoteText) VALUES (@byuser, @quotetext)", sconn);
        scomm.Parameters.Add(new SqlParameter("@byuser", System.Data.SqlDbType.NVarChar));
        scomm.Parameters.Add(new SqlParameter("@quotetext", System.Data.SqlDbType.NVarChar));
        scomm.Parameters["@byuser"].Value = Membership.GetUser().UserName;
        scomm.Parameters["@quotetext"].Value = tbQuote.Text;
 
        // Commit to DB
        scomm.ExecuteNonQuery();
 
        // Close and refresh page.
        sconn.Close();
        Response.Redirect("Default.aspx");
    }
    else
    {
        lblError.Text = "
 
You must login or register before adding a quote!"; // Alert user
    }
}

There are a lot of points to cover here. First, the user state gets checked so quotes don’t get attributed to some kind of phantom (and so no exceptions get thrown!). I added a red, textless label to the area next to the submit button so that if the user isn’t logged in, he will get an error message. If he is logged in, the quote gets written to the database. I had to provide my own connection string in the web.config file. The connection string gets used to connect to the database, and a command gets created on that connection.

The command has two parameters: the text of the quote and the user’s name. Those are set through SQL parameters. Although I have no plans to SQL injection attack my own database, it is good practice to use parameters whenever user input is to be committed to a database. After the parameters get set, the data gets written and the connection gets closed.

With the input side of the Quotebook I/O taken care of, I set out to write the output. I wanted two different kinds of output: a mess of all the quotes in reverse chronological order on the homepage and the “bare-bones API” I mentioned earlier. Before I wrote either, I created an easy way to get data out of the database that I call the QuoteEnumerator class. I created a struct called Quote, which contains the quote text and the name of the quote submitter. QuoteEnumerator has a static method that returns a list of all the Quotes stored in the database. I implemented the two like this:

/// <summary>
/// Reads the DB and creates lists of quotes.
/// </summary>
public class QuoteEnumerator
{
    /// <summary>
    /// Obtains a list of quotes from the ASP.NET database.
    /// </summary>
    /// <returns></returns>
    public static List<Quote> GetQuotes()
    {
        List<Quote> retval = new List<Quote>();
 
        // Connect to DB and set up the query
        SqlConnection sconn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["messageDB"].ConnectionString);
        sconn.Open();
        SqlCommand scomm = new SqlCommand("SELECT * FROM quotes", sconn);
 
        // Read the database
        SqlDataReader sdr = scomm.ExecuteReader();
        if (sdr.HasRows)
        {
            while (sdr.Read())
            {
                // Iterate through the results
                Quote q = new Quote();
                q.QuoteSubmitter = sdr["byUser"].ToString();
                q.QuoteText = sdr["quoteText"].ToString();
 
                retval.Add(q);
            }
        }
 
        return retval;
    }
}
 
/// <summary>
/// Contains a quote once it is extracted from the DB.
/// </summary>
public struct Quote
{
    public string QuoteText { get; set; }
    public string QuoteSubmitter { get; set; }
}

The QuoteEnumerator.GetQuotes() method is a relatively simplistic database reading method. It utilizes a SqlDataReader to iterate through all the rows. For each row, it retrieves the quote text and quote submitter, then adds them to a list containing all the other quotes. It returns that list. Using GetQuotes made implementing the homepage side of the output easy.

// Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
    foreach (Quote q in QuoteEnumerator.GetQuotes())
    {
        // Append the quote to the page in a pretty-looking (?) way
        lblError.Text += string.Format("<div style='display:block; padding:2px; margin:0 auto; border:1px solid black; width:80%; text-align:center;'>{0}<br/><br/><span style='font-size:smaller'>Submitted by {1}</span></div><br>", q.QuoteText.Replace("\n", "<br/>"), q.QuoteSubmitter);
    }
}

The result is, uh, kinda stunning…

Quotebook Image

That comment was sure telling the truth!


I only had two obstacles left: implementing the API and implementing the Python script that would utilize it. The API came first. I created a page called getmessage.aspx and deleted all of the code from the ASPX page except the top line indicating that it was, indeed, ASPX. In the code behind, I came up with this little gem to write a random quote as a string to the page (and to give credit to the submitter):

protected void Page_Load(object sender, EventArgs e)
{
    // Grab a random quote
    List<Quote> allQuotes = QuoteEnumerator.GetQuotes();
    Quote chosen = allQuotes[new Random().Next(0, allQuotes.Count)];
 
    // Write the quote as the response text
    Response.Write(chosen.QuoteText + "\n\nSubmitted by " + chosen.QuoteSubmitter);
}

Lastly, I created a Python script to read from the API. It uses urllib, and given my limited Python knowledge, it is more than good enough! (Keep in mind that this is Python 3; my last Python post was written in Python 2)

# randomMessage.py
# Random message downloader python script
print("Fortune Cookie")
DLURL = "http://localhost:6642/getmessage.aspx" # Replace with yours
 
import urllib.request
while input("Enter Q to quit or press ENTER to continue: ").lower() != "q":
    # Open the API page
    response = urllib.request.urlopen(DLURL)
    data = response.read().decode("utf-8") # Download and decode to a string
 
    print("\n" + data, end="\n\n")

With that, I entered some quotes and fired my creation up!

Quotebook Python Script Running

The awesome thing about Python is how incredibly easy it is to build relatively useful programs like this one.


Sure, it’s seven or eight times more code than the school version, but it’s extensible.

Do you have any improvements for this? Additional features? Let me know!