Archive for the ‘Technology’ Category.

MySQL Memory Allocation Error

Using the MySQL Odbc 5.1 connector I came across a strange error: memory allocation error. It’s like the “pc load letter” of MySQL. In my case the issue was that certain parameters were being set to null values. Once I defaulted the strings to an empty string rather than null the next error to pop up was that the parameters count wasn’t the expected amount. Meaning I had too few or too many parameters added with value. And once that was corrected it worked just fine.

So apparently in some cases Odbc doesn’t like null parameter values. My guess is that the table column was set to not allow null and so it kicked back an obcure error. Either way it works now.

Running on Flash

Solid state drives are finally becoming large enough that computers can be built without a conventional hard drive. Any modern OS can be installed on a solid state drive now. However, they’re very expensive and can’t hold as much as the conventional drives. The basic idea is that you use a solid state drive for your OS to speed up your system but continue using large conventional drives for all your personal data. It’s generally a good idea to keep your personal data on one drive and your OS on another regardless of what type of hard drives you use.

What I’m finding flash drives to be very useful for is running web sites off of them. I’ve been running my own servers for years and end up having to buy new hard drives every year which gets expensive. I realized that the majority of my web-sites are essentially static and they’re small.

So for $5 I can store all my web-sites on a 1-2GB flash drive. If the drive dies I can replace it for $5 instead of $35-100.

The advantage of using a flash drive is that the sites load much faster. The hard drive is no longer a limiting factor for the site itself. Just the database which of course still uses a regular hard drive since flash drives die quickly with heavy writing.

My server used to have a hard drive for the OS and web apps, the database, the logs and the web-sites themselves. I stopped bothering with logging since it’s too much useless information and there are better ways to log errors and visits without being limited to the server app (Apache or IIS). So now my server is down to two conventional drives and as many flash drives as I need.

Using Apache as a Proxy for Server 2003

Putting the “geek” in Dawn of the Geeks are two servers I have set up.  The first server is running Windows XP with Apache, MySQL, PHP and Subversion.  Recently I began developing .Net web sites using C#.   Namely the bank site which is used for managing and tracking personal finances.  Windows XP only allows a single web-site to run and only has IIS 5.1.  Since I have a copy of Windows Server 2003 I decided to put it to use and installed it on another server.  That server just has Windows 2003 with II6.

Now the issue is that all port 80 requests go through Apache. So the first step was to install mod_proxy and mod_proxy_html. Now I can point various hosts to the second server. However mod_proxy doesn’t pass along the original host header. It was sending it to the internal IP. Well, IIS 6 needs to know what host it’s serving for as well if you want to run multiple sites.

The trick is to modify your hosts file on the Apache server so that the host name maps to the internal server.

The flow is

bank.dawnofthegeeks.com hits the DNS server and points to the public IP of my router. The router sends the port 80 request to the apache server. The apache server sees that it’s dealing with bank.dawnofthegeeks.com and reverse proxy’s it to bank.dawnofthegeeks.com, however when Windows XP tries to resolve that host name it gets the internal IP from the hosts file rather than the public IP of the router from the DNS servers. So the request gets sent to the IIS server which sees the hostname bank.dawnofthegeeks.com and serves up the correct web back through the proxy.

Through the magic of the hosts file Apache reverse proxies a host to the same host.

Using JavaScript to Track Visitors

This is log.js that goes in a central location

log.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (typeof(km_scripts) == 'undefined') 
	var km_scripts = new Object();
 
km_myclass_import('http://js.dawnofthegeeks.com/hitlog.php?REQUEST_URI=' + document.location + '&HTTP_REFERER=' + document.referrer);
 
function km_myclass_import(jsFile) 
{
	if (km_scripts[jsFile] != null) 
		return;
	var scriptElt = document.createElement('script');
	scriptElt.type = 'text/javascript';
	scriptElt.src = jsFile;
	document.getElementsByTagName('head')[0].appendChild(scriptElt);
	km_scripts[jsFile] = jsFile;
}

This line of HTML goes at the bottom of every page that I want to track

1
<SCRIPT LANGUAGE="JavaScript" SRC="http://js.dawnofthegeeks.com/log.js"></SCRIPT>

hitlog.php does the hard work of logging the various information to a MySQL database. I can then go to my stats page and see the unique visitors and page view count for every domain that line of HTML appears on. I could break it down by pages as well but for now I’m not that interested in that level of detail in my reports.

In order to avoid having massive unmanagable tables (GoDaddy limits you to 200MB per database) each month has its own table. If I’m running out of space in the database I can export the older tables and delete them from the GoDaddy servers.

hitlog.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
 
// define: $dbhost, $dbuser, $dbpass, $dbbase;
 
function ConnectToJS()
{
	global $dbhost, $dbuser, $dbpass, $dbbase;
 
	$db = mysql_connect("$dbhost", "$dbuser", "$dbpass");
	if(mysql_select_db("$dbbase",$db))
		return $db;
	return 0;
}
 
$db = ConnectToJS();
 
$table = "logs_" . date("Y_m",time());
 
$sql = "
CREATE TABLE IF NOT EXISTS `$table` (
  `id` bigint(20) NOT NULL auto_increment,
  `hash` varchar(255) NOT NULL,
  `ip` varchar(255) NOT NULL,
  `ip_int` bigint(20) NOT NULL,
  `ip_host` varchar(255) NOT NULL,
  `ip_country_id` int(10) NOT NULL,
  `created_at` datetime NOT NULL,
  `path` varchar(255) NOT NULL,
  `referer` varchar(255) NOT NULL,
  `referer_host` varchar(255) NOT NULL,
  `query_str` varchar(255) NOT NULL,
  `agent` varchar(255) NOT NULL,
  `host` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `hash` (`hash`),
  KEY `host` (`host`),
  KEY `ip_country_id` (`ip_country_id`),
  KEY `referer` (`referer`),
  KEY `agent` (`agent`),
  KEY `created_at` (`created_at`),
  KEY `referer_host` (`referer_host`)
) ENGINE=MyISAM 
";
 
mysql_query($sql,$db);
 
 
$ip = $_SERVER['REMOTE_ADDR'];
$ip_host = gethostbyaddr ( $_SERVER['REMOTE_ADDR'] );
$path = $_REQUEST['REQUEST_URI'];
$parts = parse_url($path);
 
$ip_int = explode(".",$ip);
$ip_int = $ip_int[0]*256*256*256 + $ip_int[1]*256*256 + $ip_int[2]*256 + $ip_int[3];
 
$sql = "
	SELECT
		id
	FROM
		ip_to_country
	WHERE
		$ip_int >= ip_start AND $ip_int <= ip_end
";
$res = mysql_query($sql,$db);
$r = mysql_fetch_assoc($res);
$ip_country_id = isset($r['id']) ? $r['id'] : 0;
 
$created_at = time();
$referer = $_REQUEST['HTTP_REFERER'];
$ref_parts = parse_url($referer);
$referer_host = $ref_parts['host'];
$query_str = $ref_parts['query'];
 
$agent = $_SERVER['HTTP_USER_AGENT'];
$host = $parts['host'];
$hash = md5($ip . $created_at . $path . $referer . $agent . $host);
 
 
 
$sql = "
INSERT INTO 
	$table
SET
	hash = \"" . mysql_real_escape_string($hash) . "\",
	ip = \"" . mysql_real_escape_string($ip) . "\",
	ip_host = \"" . mysql_real_escape_string($ip_host) . "\",
	ip_int = \"" . mysql_real_escape_string($ip_int) . "\",
	ip_country_id = \"" . mysql_real_escape_string($ip_country_id) . "\",
	created_at = NOW(),
	path = \"" . mysql_real_escape_string($path) . "\",
	referer = \"" . mysql_real_escape_string($referer) . "\",
	referer_host = \"" . mysql_real_escape_string($referer_host) . "\",
	query_str = \"" . mysql_real_escape_string($query_str) . "\",
	agent = \"" . mysql_real_escape_string($agent) . "\",
	host = \"" . mysql_real_escape_string($host) . "\"
";
 
mysql_query($sql,$db);

Mod Proxy Silliness

By default the latest version of mod_proxy strips out the doc type declaration. To add it back in add

ProxyHTMLDoctype “<!DOCTYPE html PUBLIC \”-//W3C//DTD XHTML 1.0 Transitional//EN\” \”http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\”>” [Legacy]

to your proxy config file. You can make it global or site specific. I’m not sure why the authors of mod_proxy deemed it necessary to strip it out in the first place. A proxy should for the most part send the HTML through unedited. The only necessary changes should be to ensure that references are mapped properly so they go to external addresses rather than internal addresses.

Elmo’s World: The Video Game

Elmo’s World: The Video Game is not licensed or endorsed by Sesame Street. All graphics and sounds are used without permission. It’s a homemade game that your small kids might enjoy.

Download Elmo’s World: The Video Game

System Requirements:
Windows XP/Vista
Microsoft XNA Framework Redistributable 3.0
Bluetooth Adapter
Nintendo Wii Remote
Wii Sensor Bar

Screenshots:

Installation:
Download and unzip to any folder you create. You will need to have a Wii Sensor Bar on top of your monitor. I recommend purchasing a wireless Wii Sensor Bar so you don’t have to fiddle with your Wii game system if you have one. If you don’t have one already you will also need a Wii Remote. Make sure your sensor bar and Wii Remote (also known as a Wiimote) are turned on.

How to Connect Your Wiimote to your PC

To allow your computer to use the Wiimote you will need a bluetooth adapter. To connect the Wiimote to your computer open up your bluetooth device manager. Hold down the 1 button and the 2 button on your Wiimote and then use the bluetooth device manager look for bluetooth devices. Click next to continue through the device manager. If you are asked to enter a pin or code to connect click “skip.” You may be asked which service to use from the Wiimote. Select the keyboard/mouse/HID service if prompted (you should only see one service available).

It seems complicated but once you get it working it’s easy to do again.

Make sure your Wii Sensor bar is turned on and double click on ElmosWorld.exe. If the game reports an error and fails to load your Wiimote is not connected.

Press the home button to quit a mini game and go back to the main title screen. All games simply require that you move the Wiimote to complete the tasks: Feed Dorothy, Catch Soccer Balls or Collect Letters.

Elmo and the Wii

For Christmas I picked up Sesame Street Elmo’s World My First TV Fun & Games because it was only $5 at a store that was going out of business. My daughter is only 21 months and likes to play with the Nintendo DS because she can use the pen and make it do things. I figured that since this thing has all of three giant buttons she might be able to make use of it.

Here’s a sample screenshot:

She enjoys it because it has Elmo. However the graphics are dreadful and it features no actual music or sound effects related to Elmo. The graphics are primitive NES quality. Worse than Super Mario Bros 1. So I’ve decided to remake the games using the Wiimote and the XNA Game Studio.

It’s coming along nicely. The soccer game is mostly done. I’m just hunting for my Elmo sound effects. For as popular as he is there is a distinct lack of Elmo media on the net. I guess when most of your fans are still in their diapers you can’t expect too many fan sites to pop up.

On top of being something that my daughter can actually do (she likes swinging the Wiimote around and seeing Elmo move) it’s a good demonstration of how to put together a game using the Wiimote and XNA Game Studio.

I like my software rendering stuff because I’m doing a lot more. But the XNA Game Studio is my choice for this project. The focus is less on learning graphics programming and more on making games with the Wiimote. It’s ridiculous how easy the XNA stuff is to learn. There is no shortage of sample code to do anything you want. It even integrates with Visual Studio Express so you can get started making 2D or 3D games with little to no effort. And best of all, no cost.

Sesame Street really should look into releasing games for the Wii and DS. Parents would love it. There are so many educational games out there that just have terrible graphics and/or require sub-par gaming systems and there’s no reason for it. My parents didn’t have video games. These days kids are growing up with parents that played and still play video games. Parents today are going to have an XBox, Playstation or Wii. Why require that they buy yet another console or handheld system when they already have one or five?

I’d rather buy an educational title for a system we already own than have to buy yet another console just to have educational titles. With Nintendo’s expandable Wiimote it would be ideal for companies that not only want to create simple games but also have simple controls. I’d happily pay $15 for a Wiimote extension with 3 giant buttons for a toddler to use if I could get simple games for her to play as well. That makes more sense than $5 for yet another game system that she’ll quickly grow out of.

In the meantime, I’ll have to stick to making use of my talents to create my own educational titles for my kid to play.

Some Misconceptions About the Wiimote

One of the early mistakes people made in understanding how the Wii works was thinking that the Wii Sensor Bar actually did anything. After all it plugged into the Wii with what looks like a USB cable and you must have it on or the Wii Remote doesn’t work. Turns out that it’s essentially just a flashlight with infrared LEDs. You can put two candles on top of your TV and play the Wii.

The second misconception seems to revolve around what the Wii Remote actually does. I e-mailed Brian Peek who wrote the Managed Wiimote Library and he was apparently unaware that there was anything missing in his library. He was under the impression (as are a lot of people) that the points returned by the Wiimote for the infrared sensors indicate where the Wiimote is pointing. He didn’t realize that you can’t use those values by themselves to use the Wiimote as a pointing device.

It appears to work in some cases but once you start rotating the Wiimote (you know, twisting your wrist) things don’t work anymore.

Those values are actually where the infrared points appear in the camera. They do not by themselves indicate where the wiimote is actually pointing.

There’s a very good reason for that: the Wiimote is a collection of sensors that reports back the raw data to the Wii. It is not a computer. The individual sensors are not communicating with each other. The camera finds the x and y coordinates of its light sensor that are activated by the infrared light that hits it. The accelerometers measure their respective g-forces. There is also circuitry that indicates what buttons are being pressed. All of those parts feed their data into a bluetooth transmitter.

The reason that the Wiimote is not doing calculations is because it would add additional cost to the controller for no good reason since there is a perfectly good computer sitting on your entertainment center. All that raw data is feed to the Wii and the Wii crunches the data and spits out usable information that games can make use of. The Wii takes the positions of the infrared points of light that the camera sees and combines it with the data from the accelerometers and generates the X and Y coordinate indicating where on the screen the controller is pointing.

If the remote were to do that it would require some sort of CPU and memory and custom software, etc. As it is the Wiimote is not a programmable device. All it does is take data from the sensors and feed it through a bluetooth transmitter for more sophisticated hardware to deal with. It’s genius in its simplicity.

Anyway, the point is that the Managed Library is a great start but like the Wiimote, it only gets you the raw data. You still have to do calculations to realize the full potential of that data. The biggest missing piece is being able to use the Wiimote as a pointing device. I’ve got a good start on that as I’ve mentioned in previous posts. I’ve started work incorporating my pointer code into an XNA project to create a few sample games using the Wiimote as the pointing device.

Yes, that’s right, I’m using a game programming library intended to be used to create XBox games to create Wiimote based games. My software rendering library I wrote from scratch is nice and all and is fun to work with but it’s not going to cut it for making the types of games I want to create now that I can make better use of the Wiimote.

Hopefully I’ll have a release of some games this weekend. The games I’m currently working on are designed for a 21 month old. Perfect for demoing the capabilities of my Wiimote code without burying it under complex game code.

A Better Wiimote Pointer

This is a higher resolution of the sample Wii Pointer app in action.

You can download the app from
wiimote_pointer.zip

Everything is precompiled and ready to go. All the source code is also included. Just follow the directions at Brian Peek’s blog to get your Wiimote connected to your PC. You must have a sensor bar for this app to work properly.

Hit “+” on the number pad to increase the resolution (not the “+/=” key). You can also drag the corners of the app to change the resolution.

common\input_buffer\wiimote_class.cs contains the logic for figuring out where the Wiimote is pointing.

I updated the code to be able to approximate the location of the pointer when one of the IR sensors goes out of range. It works best when you stand several feet back from your computer monitor.

I’m sure there are some potential improvements that could be made but it is an excellent starting point for using the Wiimote as a pointing device in your own games. The sample app uses software rendering so you don’t need DirectX or OpenGL to try it out.

I’ll have some sample DirectX games created in a week or two that make use of this library.

Doing the Math with the Wiimote

Using the Wiimote as a Pointer

In my previous post I simply checked the orientation of the two IR points to determine if the Wiimote is upside down. After playing around a bit I noticed something strange. If I moved the Wiimote off the screen and then back on the screen sometimes the two points would reverse and the pointer image would flip upside down. Apparently the order of the IR points depends on which one the Wiimote registers first, not how they appear on screen. So you can hold the Wiimote perfectly horizontal, move it down off screen and back up and (what are the blue and red indicators in the above screenshot) will flip position.

So that method doesn’t actually work. What does work is even simpler: the roll angle is the atan of the z acceleration and the x acceleration. The pitch angle is the atan of the z acceleration and the y acceleration.

In C# that’s simply


//WiimoteLib.AccelState acc passed into the method
roll = (float)(Math.Atan2(acc.Values.Z, acc.Values.X) * 180.0 / Math.PI) - 90.0f;
pitch = (float)(Math.Atan2(acc.Values.Z, acc.Values.Y) * 180.0 / Math.PI);

I subtract 90 degrees so that horizontal is 0 degrees. I think the pitch could use a fixed adjustment as well but I haven’t made use of it yet so I haven’t looked into it. I use degrees in my code in various places but you could just leave it in radians.

Now the hard part is figuring out what the Wiimote is pointing at. I finally downloaded and tried out the head tracking demo that became very popular on YouTube. I was very disappointed to find that the IR values were being used as pointer position values directly. What that meant is that the demo only seemed to work because the sensor bar was kept horizontal. If you rotated the bar the motion was no longer correct. In other words, it was clever but the hard part was glossed over.

So let me make this clear: the IR values cannot be used directly as the location that the Wiimote is pointing at.

Hunting around on the internet I found a lot of references to triangulation and doing rotations but nobody had any equations. There’s a mouse demo out there were if you hold the Wiimote still but roll it slightly the cursor shoots across the screen. The reason is because it’s misusing the accelerometer data. Rotating the Wiimote in any direction doesn’t not necessarily imply acceleration: and the Wiimote knows this if you do the math right.

So what is the math?


position = new point_class((1.0-ir.Midpoint.X) * (double)sx, ir.Midpoint.Y * (double)sy);

If you’ve looked at the Wiimote Library test app you’ve seen something that looks like that. It’s basically unchanged except for one “minor” detail: the x-axis is flipped.

And you’re not done. That equation gives you the midpoint of the two IR sensors with the x-axis flipped. That doesn’t give you where the Wiimote is pointing just yet.

To finalize the equation you move the position point to the origin. In my code you subtract the point in the center of the screen from the position. You then rotate that point using the value of Roll. Now, add the center of the screen point back to position.

Done. That’s it. That’s the secret of using the Wiimote as a pointer.

Is it perfect? No. You can’t get all the way to the edges because this method requires that both IR sources be visible. It also may not be getting the exact spot on the screen that the Wiimote is pointing at but it’s close enough that I can’t tell. If I point the Wiimote in the upper left corner and roll the Wiimote the pointer stays in the upper left hand corner and so on with the rest of the quadrants.

So it’s a very good start. The basic thing to keep in mind is that input has to be simple. The equations for processing input have to be simple and fast otherwise you’re wasting CPU cycles that should be used for graphics and game play. So there was no reason for me to believe that you have to be doing complex 3D equations to get the pointer going.

Maybe that’s ultimately what Nintendo is doing, but you don’t have to. I’ll have the full code and download available soon so you can try it out yourself and maybe find ways to improve it.

ss_blog_claim=70b9168863fc97c91e6d88b40542a327 ss_blog_claim=70b9168863fc97c91e6d88b40542a327