Terry Pratchett was born in 1948 and is still not dead.

….Is the very first thing printed in my copy of Reaper Man.  I suppose it’s fitting, that Reaper Man was the first one that came to hand. It’s Reaper man that contains one of the more profound insights into the duration of a single human life:

no-one is finally dead until the ripples they cause in the world die away

So in a sense, the title of this post is still true, and will always be true – it will be a very long time before the ripples of Sir Terry’s work finally die away.

I saw Sir Terry speak twice at the Hay Literature festival, once when I was about 7 years old, and again when I was 15. I’ve also met him in a different setting entirely.  When I was 7 the only books of his I had read were Truckers, Diggers and Wings – books I hope to introduce my own children to, one day. My dad had taken me, and he’d taken his copy of Maskerade to get it signed. He wasn’t able to, but I started to read it on the way home.

When I was 15, I’d gone with a friend to see him talk, and that was just around the release of Thud!. Afterwards, during the signings, he spoke to me at some length about Half-Life 2, because I was wearing a Half-Life 2 tshirt. It was incredible to have someone I looked up to so much just talk to me for a few minutes about a common interest.

The final time I met him, was a far more personal setting. He came into the bookshop I was working in. My boss was out to lunch, so I was manning the counter. I was sure it was him, but didn’t want to completely geek out at him while he was just doing some shopping. He bought several rare second hand books (And I can’t remember for the life of me what they were), and when the transaction was completed, I told him I was a big fan of his books. I’ve always wondered what it was like for celebrities to be pestered in public, but he didn’t mind at all, and we spoke for a few minutes about the Hay festival and Hay itself. I said that his descriptions of L-space had always reminded me of the second hand bookshops in Hay-on-Wye.

My boss came back, and brazenly capitalized on the situation by asking Sir Terry to sign some of our stock! He was quite happy to, but my boss barely waited for him to be out of the door before marking the prices up and sticking them in the window. (My boss apparently went to the same school as Bernard Black).

I’m going to go away and celebrate the life of Terry Pratchett, one of the greatest authors of all time, by reading Reaper Man. I’ll have a glass of whiskey, and I’ll light a candle.

“What I could do with right now is one of Mr Dibbler’s famous meat pies – ‘

And then he died.

The Archchancellor glanced at his fellow wizards, and then tiptoed across to the wheelchair and lifted a blue-veined wrist to check the pulse. He shook his head.

“That’s the way I want to go,” said the Dean.

“What, muttering about meat pies?” said the Bursar.

“No. Late.”

Goodbye, Sir Terry Pratchett. We’ll miss you.

I miss ‘puter games.

I haven’t played anything in weeks, if not months. I’ve been working away from home since mid May, and during that time I’ve barely touched anything.

Instead I’ve been reading about games, keeping up with releases, but over the last couple of weeks I’ve instead been caught up in DRAMA. Games Journalism DRAMA.

I’m sick of it, yet morbidly fascinated by it. But I’ve lost sight a bit of why this is my hobby in the first place. So I’ve gone down my steam list and installed things that:

a) Will run on my work laptop

b) I haven’t played before

Here’s what I’ve got installed at the moment:

Red Faction runs very poorly.

CoH won’t launch.

I’ve played KSP a lot already.

So a trip to 1998 is in order. I’m going to play SiN.

New project: Triumph GT6

For about 3 years now, I’ve been looking to buy a classic British sports car. This desire was spawned by seeing how much fun Matt was having with his MG.

There’s something really special about “classic” cars, there’s an aesthetic you just don’t tend to see in modern cars.

So I’ve bought myself a Triumph GT6. When I bought her she was in pretty good shape, and I’m going to be working on her a lot, trying to restore and improve as much as possible. Here she is:

I'm sitting behind the wheel.

I’m sitting behind the wheel.

Driving this car is an incredible feeling. I’ve previously only driven cheap, modern cars that have been thrashed by a series of learner drivers. This car has no power steering, no servo assist on the brakes, and she’s pretty low to the ground. The engine is bigger than anything I’ve driven before (Except 4x4s), and so driving was at first a little intimidating.

You can feel everything that’s going on with the car, I feel like I’m connected directly to the road. There’s no float, and there’s feedback I can actually feel whenever anything happens, I can feel the road quality. Not that I’m a fantastic driver who can feed all this back into how I drive or anything, but as a sensation it’s fantastic.

There’s a lot of work needs doing, and I’m going to write up a lot of what I get do here, for posterity, and to let my friends know.

I’m still rubbish at Dark Souls

Since working out that I was trying to take on enemies that were FAR beyond my current character, I’ve been having an easier time of things.

I can actually progress through the Undead Burg, and kill a few enemies at a time before getting wasted.

There’s something very satisfying about progressing in this game, it’s the feeling that you are learning and mastering systems that you once found irredeemably hard.
My progress (when not trying to kill skeletons) followed this pattern:

1. Run up the hill, kill an enemy or two.
2. Make a stupid mistake and die.
3. Run up the hill, kill a few more enemies.
4. Progress a little further, find a new area, kill an enemy and die.

Each time I try again, I can get further into the unknown without dying. It’s not that I’m memorizing where enemies will come from (even though I am doing), it’s more that I’m getting better and better at combat, so even new, unknown areas don’t kill me quite as quickly as before.

I still make stupid mistakes often though.

Making it to a bonfire triggers such a sense of relief. The save system might be irritating sometimes, but it really does create a wonderful tension. I’m forced to play slowly, carefully, methodically. I can’t run in and slash enemies to death, even if I know how many there are and I’ve taken them on a while load of times already.

All that said, the Taurus Demon took some doing for me. All that tension the save system can create just turns to frustration for me, when dealing with a boss.

If I have to play for ten minutes to meet the boss, and get squashed flat in 30 seconds, it’s hard for me to learn it’s attack patterns.

The excruciating slowness of the “stand up” animation means that if I’ve been knocked over, I’ll rarely get up in time to dodge the next (completely lethal) attack. And then I have to trek all the way back up to the boss to try again, try a different strategy, or just try my luck again.

The video above shows me going through some of my failures with the Taurus Demon. Each time I got killed through what felt like luck, and when I did eventually succeed, it felt more like I was exploiting an AI weakness than outsmarting a massive Demon. I found a blind spot under his legs where he couldn’t hit me, and whacked him in the groin until he exploded. Even doing this I took damage because I got trodden on.

After this, it was back to the exploration and cautious fights, which are what I like most so far. Finding the ladder back down to the bonfire was a relief, especially since I’d narrowly avoided dying by dragon.

And then I climbed a staircase and got flattened by a big bastard black knight type bloke.

I’m rubbish at Dark Souls

I picked up Dark Souls: Prepare to Die edition in the autumn steam sale. I tried to play it with keyboard and mouse, and found the controls to be decidedly lacking.

I resolved to wait, until I could get a gamepad to play with instead. I’ve been wanting to get a gamepad for a while, preferably a wireless one, so I can play the more arcade type games I own from my sofa.

Having finally got a controller, I started Dark Souls again.

And I’m terrible at it.

In the tutorial level, the first weapon I picked up was a broken sword hilt. This was fine for taking care of the non-violent zombies that are scattered through the first level, and you’re supposed to pick up your real weapon the first time you meet an archer, just after you get your shield (I think).

I managed to miss this.

And forged ahead anyway.

I died.

A lot.

After meeting a dying knight, who gave me his Easter (Estus) flask, I had my first “real” fight with a zombie wielding a sword. I was only doing about 2 damage per hit, 3 if I did a heavy attack. It took a very long time to kill it.

Just after him, was a small courtyard where I had to deal with 2 at the same time. They trounced me over and over again, and then around the corner was an archer, and the entrance to the boss fight.

I played this section repeatedly for about 2 hours. I lost track of how many times I died.

When my sword hilt broke, I realised that no matter how hard this game was supposed to be, the tutorial probably shouldn’t be THIS hard. I backtracked a lot, and found my real sword. Which did 20x the damage of the hilt.

I AM SOMETIMES A MORON.

I managed to kill the Asylum Demon without too much trouble (in fact I think I got it on the first go).

I savored my victory for a short while, walked out of the room and was then startled when I walked into an airport (the giant crow picked me up).

Now that I’m in the next area, I’m trying to deal with these two skeleton chaps. I’ve been trying for about two hours now. I’m starting to wonder If I’ve done the same thing – did I miss something really obvious? Maybe. Anyway, here’s a video of me failing a lot. I recorded this using Nvidia shadowplay, which is a very neat tool. Much nicer than having to pay for fraps, and it doesn’t impact my framerate much.

I fail at parrying, I role the wrong way, I lock the wrong target, I get stuck on things.

I’m not very good at this game.

Very small dogs.

My parent’s bitch, “Ted” just whelped. It was her first litter, and she had 3 live pups. Since the father is called Bill, they watched the film “Bill & Ted’s Excellent Adventure” in preparation. The dogs didn’t pay any attention.

After the first two plopped out (the runt was DOA), Ted apparently lost interest in the whole thing, and stopped. They took her down to the vets, who scanned her and saw that neither of the remaining two were even in the birthing canal. Lazy sods. After being given an injection, Ted managed to have them both in the back of the landrover.

So – the three puppies are called Rufus, Missey and Socrates. I look forward to the day when I can shout “SOCRATES” across a public park.

Going home to Wales on Friday to examine these microscopic dogs in person, and probably make “daaawww” noises.

Here they are:

DSC_0918 DSC_0917 DSC_0916 DSC_0920 DSC_0919 DSC_0913 DSC_0915 DSC_0914

UAV, reading sensor data Part II

In our previous adventure, Matt and I defeated the dragon and rescued a fake princess who turned into a giant spider  managed to get some meaningful data from both the gyrometer and the accelerometer. We also made some pretty graphs.

The next step is for us to compare the outputs from the Gyro and the Accelerometer. This is currently impossible, given that the Accelerometer is transformed into meaningul readings (degrees) already, and the gyro is just a load of “rate of change” readings.

We can get the orientation readings from the Gyro like this:

  //Create variables for outputs
  float xGyroRate, yGyroRate, zGyroRate, xGyroRate2, yGyroRate2, zGyroRate2;
  long Time;
  //Read the x,y and z output rates from the gyroscope & correct for some innacuracy; convert to seconds
  xGyroRate = (gyroReadX())/57.5;
  yGyroRate = (gyroReadY())/57.5;
  zGyroRate = (gyroReadZ())/57.5;
  //Determine how long it's been moving at this 'rate', in seconds
  Time = (millis()-previousMillis);
  //Multiply rates by duration
  xGyroRate2 = -(xGyroRate/Time)/4;
  yGyroRate2 = -(yGyroRate/Time)/4;
  zGyroRate2 = -(zGyroRate/Time)/4;
  //Add to cumulative figure
  if (((xGyroRate2)>(gyroLPF))||((xGyroRate2)<(-gyroLPF)))   CumulatGyroX += (xGyroRate2);   if (yGyroRate2>gyroLPF||yGyroRate2<-gyroLPF)   CumulatGyroY += (yGyroRate2);   if (zGyroRate2>gyroLPF||zGyroRate2<-gyroLPF)
  CumulatGyroZ += (zGyroRate2);

Now that we’ve done this, we can measure an axis from both the Gyro and the Accelerometer at the same time, and overlay them on top of one another in gnu plot.

Like so:

Yeah, that didn't really work.

Yeah, that didn’t really work.

Ok, so there was something wrong with that. We tweaked the code some more, and got something a bit better:

No, that's worse.

Much worse.

Finally, we figure out where we went wrong with the code. We don’t have the old versions, so we can’t show you our idiotic mistakes. After fixing it, we get something much closer to what we were expecting:

Roll measurement from Gyro and Accelerometer

Roll measurement from Gyro and Accelerometer

We can see from this graph that both sensors are outputting more or less the same thing. However the gyro measurements are actually off by a bit at the start, and are slowly producing a more noticeably incorrect orientation. If we used just the gyro, we’d end up with the plane downside up. There are also “spikes” in the accelerometer readings, at 700 and 1300 – these are probably noisy readings from the sensor.

To get an idea of how much the gyro readings drift, we turned on all the gyro sensors and then left the board still for a few seconds:

Gyro drift in three axes.

Gyro drift in three axes.

This is obviously not going to work long term – we can’t be certain of either sensor. We need a way to combine the readings from both sensors, or face the consequences.

UAV, reading sensor data

A long time before we did our session where we controlled some servos, we had a session where we were reading sensor data.

We’ve tried this a number of times, but this instance was where we actually started to get worthwhile data, and we could interpret it correctly.

We are currently reading two sensors to find orientation data: the 3 axis gyroscope and the 3 axis accelerometer.

I’ll cover the accelerometer first.

Reading Accelerometer Data

We’re using a 3 axis accelerometer  which if read correctly can tell us the pitch and roll of the aircraft (actually, just the pitch and roll of the sensor, but the sensor will be built into the aircraft).

Each axis in the accelerometer (we’ll call them accX, accY and accZ) tells us how pull that sensor is experiencing (at rest, this is due to gravity). We only need 1 axis to start with, to measure Pitch.

PitchIn this crappy diagram, the rectangle represents our accelerometer. It’s measuring apparent gravity. As the acceleromter has its pitch increased (rotated clockwise, in this case), the apparent gravity being measured in that axis will decrease.

Theta represents the angle between the apparent gravity and actual gravity.

The trigonometery to calculate pitch is pretty easy:

apparent gravity = cos (theta) * g

or:

acc = cos (theta) * g

The relationship between theta and pitch is very simple: simply add 90 degrees to theta to get pitch.

So, rewrite

apparent gravity = cos (theta) * g 

as

theta = acos (acc / g)

And then to get the actual pitch:

pitch = asin (acc / g)

/*------------------------------------------------------------------------*/
//Accellerometer Read and Output Section
 
  float xAccRate, yAccRate, zAccRate;
  double pitch, roll;
 
  xAccRate = (accReadX());
  yAccRate = (accReadY());
  zAccRate = (accReadZ());
 
  double measured_g = sqrt((xAccRate*xAccRate)+(yAccRate*yAccRate)+(zAccRate*zAccRate));
 
  roll = (atan2(xAccRate/128,zAccRate/128))*(180/3.141);
  pitch = (atan2(yAccRate/128,zAccRate/128))*(180/3.141);

Reading Gyro Data

Gyro data is actually a lot easier to read, in some ways. All a the gyrometer is doing is measuring rate of change since the last reading.

Therefore, all we need to do is integrate over a period of time to get the rotation in a certain axis.

Code:

/*-----------------------------------------------------------------------------*/
//Gyro Read & Output Section
 
  //Create variables for outputs
  float xGyroRate, yGyroRate, zGyroRate, xGyroRate2, yGyroRate2, zGyroRate2;
  long Time;
  //Read the x,y and z output rates from the gyroscope & correct for some innacuracy; convert to seconds
  xGyroRate = (gyroReadX())/57.5;
  yGyroRate = (gyroReadY())/57.5;
  zGyroRate = (gyroReadZ())/57.5;
  //Determine how long it's been moving at this 'rate', in seconds
  Time = (millis()-previousMillis);
  //Multiply rates by duration
  xGyroRate2 = -(xGyroRate/Time)/4;
  yGyroRate2 = -(yGyroRate/Time)/4;
  zGyroRate2 = -(zGyroRate/Time)/4;
  //Add to cumulative figure
  if (((xGyroRate2)>(gyroLPF))||((xGyroRate2)<(-gyroLPF)))   CumulatGyroX += (xGyroRate2);   if (yGyroRate2>gyroLPF||yGyroRate2<-gyroLPF)   CumulatGyroY += (yGyroRate2);   if (zGyroRate2>gyroLPF||zGyroRate2<-gyroLPF)
  CumulatGyroZ += (zGyroRate2);

Pretty simple 🙂

Some pretty graphs

Of course, that code took us a long time to actually write. And we may have borrowed some from elsewhere, I can’t for the life of me remember. Once we’d got it working, we plumbed the serial output into GNUPlot, so that we could get a visual representation of what was going on.

The general idea was to tilt the board by 90 degrees in once axis, then return it to it’s original position. This would produce a sine wave, eg:

output2

After mucking about for a bit with minicom, I used this command to capture the serial output:

sudo minicom --capture mincap

The serial output just looks something like this:

ID: 69
2 0 0
-32 -4 -27
-1 -1 1
0 -1 1
0 0 1
0 -1 0
0 1 0
0 1 0
1 -1 0
1 -1 0
0 -2 0
0 -1 0

Once we’d got that, I spend yet more time mucking around in gnuplot. Actually, I jest. It was pretty easy to plot a graph.

The first graph we got was this:

We'd done something very obvious and simple wrong.

We’d done something very obvious and simple wrong.

Spot the deliberate mistake.

Upon seeing this, we retired to the pub. Over a pint or three, we realised what it was we’d done wrong.

The Arduino board has an integer size of 16 bit, meaning it has a max size of 32,767. If you try to do

int i = 32767 + 1;

then i would have the value -32767.

And that’s exactly what was happening. We’d used an Integer, because occasionally I’m as thick as a brick sandwich.

We weren’t doing anything with the data yet to convert it to degrees, and we weren’t even sure how big the numbers would be, and we were just adding it all up.

Here’s another graph showing the same thing, but with the dots joined up:

temp2

After we started using the (entirely more sensible) long data type instead, we got what we’d originally expected:

temp6

So, as predicted, we got ourselves half a sine wave. If we tilt it by 90 degrees in one direction, then back to flat, then 90 degrees in the other direction, we get the full sine wave:

If the graph is a bit lumpy, it's because Matt had the shakes.

If the graph is a bit lumpy, it’s because Matt had the shakes.

In the next post, I’ll talk about working out the actual orientation, and sensor drift.  We’re also going to compare the output from the accelerometer and gyro.

Arduino: Controlling Servos

Last Sunday, Matt came to visit. He brought his MAN TIN along, which is filled with micro controllers and breadboards and miscellaneous wires and a machine that goes “Ping”.

We’ve not done any UAV work for a very long time, in fact the last time we did any was last Autumn. This has actually been my favourite session to date, because we made things move!

We’re going to be using servos to drive our control surfaces on the UAV, and this was a sort of Proof of Concept in making the things work.

We built the board, and hooked up the servos. The arduino program actually has some sample code for servos built in, so, not knowing how they work, we just hooked up that sample code.

All it does is make the servo rotate 180 degrees in one direction, then 180 degrees in the other direction, over and over again.

Here’s the code from the Arduino website. It’s not identical to ours, because we changed the pins, and then experimented with the speeds a bit. The speed was easy enough to alter: just change the delay between moves.

 
// Sweep
// by BARRAGAN <http://barraganstudio.com>
// This example code is in the public domain.
 
 
#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo
// a maximum of eight servo objects can be created
 
int pos = 0;    // variable to store the servo position
 
void setup()
{
myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}
 
 
void loop()
{
for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
{                                  // in steps of 1 degree
myservo.write(pos);              // tell servo to go to position in variable 'pos'
delay(15);                       // waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
{
myservo.write(pos);              // tell servo to go to position in variable 'pos'
delay(15);                       // waits 15ms for the servo to reach the position
}
}

Here’s a video of it actually working:

Half-Life 2: Point Insertion Part I

Abstract

Recently, Valve released Half-Life 2 and it’s episodes for Linux. For me, this is more or less a dream come true, something I’ve been waiting and wanting and wishing for since I started using Linux in 2006.

I’ve tried Wine, multiple times, and it’s always been a bit too quirky, with too many peculiar bugs and foibles. This is not to say that I don’t find Wine impressive. Wine is probably one of the more audacious projects I’ve ever seen – an attempt to reverse engineer one of the most obtuse black boxes ever, the Windows API.

So now that Half-Life 2 has been natively released for Linux, I decided it was time to do a complete replay of the game. I’ve played the game a lot, but I don’t think I’ve actually sat down and gone end to end for a long time. I always skip bits, replay certain sections and then stop.

This time I’m going to share my experiences, via pretentious blog posts, probably on THE INTERNET (but not necessarily  I’ll accept requests to have pages posted to you, if you first of all send me a written request via the royal mail).

I’m doing this not because I think I’ve got anything interesting to say, or anything new. Everything has been more or less said about the game at this point, and if I ejaculate all over it I don’t think it will make much difference to the world at large.

No, I’m doing this because I want to and because I’m a mouthy git, and because this is the internet I can do what I like.

Technical Specifications

I’m playing this on a Samsung Series 7 Chronos, which is an ultrabook type thing. It’s got:

Xubuntu 13.04 x64

Intel Core i5

8GB RAM

nVidia geforce 630M

Although the nVidia bit is actually Optimus, and I get way better performance out of the Intel bit than I do with the discrete nVidia chip. Still working on that.

And away we go!
Continue reading