A couple weeks ago I decided I wanted to practice my Java coding. I looked around for possible Java projects, and I came across Minecraft modding. Writing a mod seemed like a great project because it would be fun and easy to get started (thanks to the modding community being very friendly and active).
There are two kinds of mods: single player and multiplayer. Single player mods can do neat things like add items and monsters to the game. Multiplayer mods are a slightly more restricted because only the server code is modified and the mods can't do anything the original client can't handle. I chose to create a multiplayer mod because I also wanted to run a server for my friends.
For multiplayer mods there is an unofficial extension framework called Bukkit. Bukkit is split into two pieces of software. Bukkit proper is an API programmers use to write their plugins. Craftbukkit is a modified server with plugin management. If you want to write a plugin, you want Bukkit. If you want to run a server with plugins, you want CraftBukkit. The Bukkit API is changing all the time, so the best documentation is the source, but I've also found these java docs to be useful.
My plugin is called HealingTotem. It allows players to regenerate health if they are in the proximity of a Totem. The concept is simple, but the design had some interesting twists. As far as I know, this is the only plugin which searches for configurable block patterns. Users can define block patterns, or structures, as a list of blocks with a relative offsets and material types. My plugin efficiently searches for structures as blocks are created and destroyed. Typically, other plugins require the use to enter a command to perform a check, or "activate" the structure by using an item on a block. As a bonus, my plugin searches for structures at different orientations.
I might write some more Minecraft modding related posts later, but for now I just wanted to share my work, so here it is:
HealingTotem - Health Regeneration from Totem Poles (source)
Thursday, August 25, 2011
Sunday, July 24, 2011
Google Labs is shutting down?
Today I learned that Google Labs is shutting down. Google has said it will be "ending Labs experiments," which seems like a nice way of saying, "pulling the plug." It seems like a real shame. That means no more cool things like this, or this.
Sunday, July 10, 2011
[pymex] Or you could just use Jython...
I recently discovered an alternative to pymex: using Jython inside the Matlab interpreter. Jython is an implementation of the Python interpreter in Java. The Matlab interpreter allows the importing of Java objects, so all a programmer needs to do is import the Jython interpreter. Here is an example:
Jython is really cool, but it does have a drawback. Modules written in C for CPython are not compatible with Jython. That excludes alot of modules, but that may not bother some people. If you do need to use a CPython module, you can use pymex.
>> javaaddpath('C:\Jython25\jython.jar')
>> import org.python.util.PythonInterpreter
>> import org.python.core.*
>> interp = PythonInterpreter()
interp =
org.python.util.PythonInterpreter@22ff0470
>> interp.exec('import sys')
>> interp.exec('print sys')
>> interp.set('a', 42)
>> interp.exec('print a')
42.0
>> a2 = interp.get('a')
a2 =
42.0
Jython is really cool, but it does have a drawback. Modules written in C for CPython are not compatible with Jython. That excludes alot of modules, but that may not bother some people. If you do need to use a CPython module, you can use pymex.
Wednesday, June 8, 2011
[pymex] Threading
Threading didn't really work in the first version of pymex. You could create a Python thread, but it wouldn't actually get any execution time. I recently found out why, and fixed it!
Python has limited support for multi-threading. The Python interpreter is not fully thread-safe, and something called a global interpreter lock (GIL) is used as a sort of mutex on the interpreter. Only the thread which has acquired the GIL can interact with Python objects or use the Python C API. The negative side-effect of the GIL is that Python threads run more-or-less contiguously, instead of concurrently. Thus, Python threads can't take advantage of parallel hardware.
By default, Python runs in one main thread and the GIL is not initialized. Threads and the GIL are automatically initialized when a Python thread is created. Python automatically shares the GIL between threads so each thread can execute. This is accomplished by threads yielding on certain functions like I/O, sleep, etc. This doesn't happen for C extensions, they must explicitly release the GIL using the C API.
The old version of pymex would never release the GIL. The GIL would still get released, but only while the Python interpreter was running (during a call to PyRun_SimpleString). This meant that threads would only get CPU time during calls to pymex, and not during normal Matlab execution. Python scripts which joined their threads before ending didn't have a problem, but daemonized threads didn't work at all.
The fix was actually very simple. All I had to do was release the GIL using the C API before returning from the mex function, and reacquire it on reentry. This was done using PyEval_SaveThread and PyEval_RestoreThread. I also decided to release the GIL inside the matlab module during various (slow) mex calls, like mexPrintf. I did this to hopefully increase Python's threading performance.
But there was one drawback: added complexity. Programmers now need to consider thread-safety. Unfortunately, Matlab's mex interface isn't thread-safe. By extension, the matlab module isn't thread-safe. Don't use the matlab module inside a thread, it is liable to segfault! There is an exception to this rule. It is safe to use the matlab module in a thread as long as it ends before the script ends (i.e. the thread is joined). That way the underlying mex calls only occur during the call to pymex, so memory access violations are avoided.
Check out the pymex website for more details!
Python has limited support for multi-threading. The Python interpreter is not fully thread-safe, and something called a global interpreter lock (GIL) is used as a sort of mutex on the interpreter. Only the thread which has acquired the GIL can interact with Python objects or use the Python C API. The negative side-effect of the GIL is that Python threads run more-or-less contiguously, instead of concurrently. Thus, Python threads can't take advantage of parallel hardware.
By default, Python runs in one main thread and the GIL is not initialized. Threads and the GIL are automatically initialized when a Python thread is created. Python automatically shares the GIL between threads so each thread can execute. This is accomplished by threads yielding on certain functions like I/O, sleep, etc. This doesn't happen for C extensions, they must explicitly release the GIL using the C API.
The old version of pymex would never release the GIL. The GIL would still get released, but only while the Python interpreter was running (during a call to PyRun_SimpleString). This meant that threads would only get CPU time during calls to pymex, and not during normal Matlab execution. Python scripts which joined their threads before ending didn't have a problem, but daemonized threads didn't work at all.
The fix was actually very simple. All I had to do was release the GIL using the C API before returning from the mex function, and reacquire it on reentry. This was done using PyEval_SaveThread and PyEval_RestoreThread. I also decided to release the GIL inside the matlab module during various (slow) mex calls, like mexPrintf. I did this to hopefully increase Python's threading performance.
But there was one drawback: added complexity. Programmers now need to consider thread-safety. Unfortunately, Matlab's mex interface isn't thread-safe. By extension, the matlab module isn't thread-safe. Don't use the matlab module inside a thread, it is liable to segfault! There is an exception to this rule. It is safe to use the matlab module in a thread as long as it ends before the script ends (i.e. the thread is joined). That way the underlying mex calls only occur during the call to pymex, so memory access violations are avoided.
Check out the pymex website for more details!
Friday, June 3, 2011
I graduated!
I graduated! After four years of undergrad in EE and two years doing my MS in CompE, I'm finally done with school and ready for the real world!
School has been great, and I was very fortunate to work and study with great people. My advisor John Spletzer is a great guy, a genius, and has taught me more than I can remember. My coworkers, Jason Derenick, James Evans, Amy Forando, Chao Gao, Sean Kelly, Ben Mak, Tom Miller, Mike Sands, Constantin Savtchenko, Justin Sonntag, Dave Stolfo, and Nick Welton, made VADER Lab a great place to work. They are all intelligent, stimulating, and fun people. I could not thank John and everyone else enough for their support, insight, and hard work.
It's always sad to leave, but I'm also happy to be moving forward. All I need now is a job... on to the job search!
School has been great, and I was very fortunate to work and study with great people. My advisor John Spletzer is a great guy, a genius, and has taught me more than I can remember. My coworkers, Jason Derenick, James Evans, Amy Forando, Chao Gao, Sean Kelly, Ben Mak, Tom Miller, Mike Sands, Constantin Savtchenko, Justin Sonntag, Dave Stolfo, and Nick Welton, made VADER Lab a great place to work. They are all intelligent, stimulating, and fun people. I could not thank John and everyone else enough for their support, insight, and hard work.
It's always sad to leave, but I'm also happy to be moving forward. All I need now is a job... on to the job search!
Tuesday, November 30, 2010
[imu] Microstrain 3DM-GX1
Recently I've been playing around with a MicroStrain 3DM-GX1, which is a pretty decent IMU. I found myself in need of an IMU for a project I'm working on, and the lab just happened to have a GX1 lying around.
While the GX1 itself is a solid piece of hardware, the software is a little bit lacking. This is especially true for linux; MicroStrain provides only a small example to get euler angles. It would have been nice if they had provided a library and API, but it was easy enough to write one from scratch using the 3DM-GX1 Data Communications Protocol document.
I feel obligated to say here that MicroStrains documentation is excellent, and really simplified the whole process. I also had to email customer support once or twice, and they were very helpful.
So I wrote a C++ library to talk to the GX1. It was relatively painless because the GX1 uses a serial interface and I could simply use the unix termios API. While the GX1 supports polling and continuous modes, I focused on polling because it's more flexible. To get data from the IMU the following must occur:
While the GX1 itself is a solid piece of hardware, the software is a little bit lacking. This is especially true for linux; MicroStrain provides only a small example to get euler angles. It would have been nice if they had provided a library and API, but it was easy enough to write one from scratch using the 3DM-GX1 Data Communications Protocol document.
I feel obligated to say here that MicroStrains documentation is excellent, and really simplified the whole process. I also had to email customer support once or twice, and they were very helpful.
So I wrote a C++ library to talk to the GX1. It was relatively painless because the GX1 uses a serial interface and I could simply use the unix termios API. While the GX1 supports polling and continuous modes, I focused on polling because it's more flexible. To get data from the IMU the following must occur:
- Set a command to the GX1
- Wait for result buffer
- Read the result buffer
- Parse the result to get meaningful data
Tuesday, August 31, 2010
[o3d2xx] 3D LIDARs Are Cool
This summer I wrote a C API and Matlab driver for an IFM O3D200. This is a really cool LIDAR. It basically captures distance images, meaning the pixels of the image represent distance rather then color, like with a normal camera. It can also send out the Cartesian coordinates of each pixel, so you don't have to do it in preprocessing.
The O3D2XXs use XML-RPC for configuration, and a simple TCP socket for data flow. The XML-RPCs are useful and provide a good deal of customization. They allow the user to change the exposure time, frame rate, frequency mode, etc. The network settings are also configurable, and the LIDAR can use DHCP or a static IP address. Using the socket is easy, the user simply requests and image and then reads in the buffer(s).
Right now my code has to stay top secret, you know, to give Vader Lab a competitive edge. Hopefully someday later I can publish it. Even though most people don't have O3D2XXs right now, I expect this sensor to gain in popularity. After all it's very cool.
The O3D2XXs use XML-RPC for configuration, and a simple TCP socket for data flow. The XML-RPCs are useful and provide a good deal of customization. They allow the user to change the exposure time, frame rate, frequency mode, etc. The network settings are also configurable, and the LIDAR can use DHCP or a static IP address. Using the socket is easy, the user simply requests and image and then reads in the buffer(s).
Right now my code has to stay top secret, you know, to give Vader Lab a competitive edge. Hopefully someday later I can publish it. Even though most people don't have O3D2XXs right now, I expect this sensor to gain in popularity. After all it's very cool.
Subscribe to:
Posts (Atom)