In order to draw a spline 4 points are needed: a start and enpoint of the spline and two control points. The control points define the vector or direction in which the spline starts and ends. Based on this the formula for calculating (X, Y) at interval Index is listed below:

X := Round ((StartPoint.X*Index) + (EndPoint.X*(1-Index)) + (Weight*(EndPoint.X-ControlPointTwo.X)*(1-Index)*(1-Index)*Index) + (Weight*(StartPoint.X-ControlPointOne.X)*(1-Index)*Index*Index));

Y := Round ((StartPoint.Y*Index) + (EndPoint.Y*(1-Index)) + (Weight*(EndPoint.Y-ControlPointTwo.Y)*(1-Index)*(1-Index)*Index) + (Weight*(StartPoint.Y-ControlPointOne.Y)*(1-Index)*Index*Index));

The interval ranges from 0 to 1 in real numbers, to find the middle point on the curve the value of Index should be 0.5. By sampling the equation more frequently the spline will be smoother. The value of Weight controls the tension of the spline or tangency towards the vectors. If set to 0 a straight line is drawn between the start and end point, it can be set larger than 1 although I’m not sure what the effect will be.

I wrote a small program in Delphi 7 to see how to use these functions; it can be downloaded here. When executed you see a white image, click with the left mouse button on the image to set a servo location, a red cross appears on that spot. Do this in total 11 times after which 9 splines are drawn to indicate the shape of the snake based on the provided servo positions. Why 9 splines? The first spline uses 4 points (point 1, 2, 3 and 4) where 1 is a control point, 2 and 3 the start/end points and 4 is the second control point. For the next spline points 2, 3, 4 and 5 are used resulting in a spline between points 2 and 3.

Below image shows a screen shot of several snakes that I drew. Try to keep the distance between the points the same to mimic the actual situation of the servo’s linked together. The Weight value can be changed in the code after which you need to recompile the project.

In order to study the effect of the Weight value I modified the program a bit so the same snake is drawn using various weight factors, below image shows the result.

When a snake moves forward with a constant speed it moves it’s head from left-to-right and right-to-left in a constant speed. As a result it follows a perfect sine is drawn, I added a function that fills the ServoPoints, draws the snake and also draws a perfect sine through those points. This function is placed under the Weight button that is hidden during design time. Make it visible if you want to play with is and re-compile the program.

After a couple of test runs it seems that the most optimal value for Weight is 0.65; it’s also clear that this value should be defined as a constant value in the final embedded software so that the playing can be repeated to see how the actual movement of the snake can be optimized.