Thanks to Diego for kindly testing it :)
You can get the MFC dlls from here.
I'm also working on the definitive menu options and state switching for debug/build/run.
First thing I tried was using auto_ptr, but strict ownership transferral didn't work properly with the way Bison works (in some cases Bison copies the semantic value to the stack of symbols but it uses the temporary variable it just copied from).
So there's a need for refcounting and ownership releasing. After looking a bit at Boost library, I coded my own flavour of SharedPtr, a refcounted smartptr with ownership releasing. Because for design reasons I've limited SharedPtr usage to ACL program parsing, you can request the ownership of the pointer at any time so it's not destroyed when the refcount of the wrappers reach 0.
I haven't made it thread-safe, as I have no need for that.
I found my own set of problems when using this smart pointer:
The net result is that now YYSTYPE stores SharedPtr, which are properly freed on a compiler error (I'm using exceptions for that).
Added GOTO operation support and changed a bit the workspace format (all input ports from conveyors, robots and sensors must now read from the same controller).
All routes are now read and created properly.
Implemented relative coordinates (although untested).
Encapsulated the solver inside CRobotInfo by adding SolveInvKin and SolveDirKin methods to that class.
Fixed some leaks: there's only missing 336 bytes in one allocation (only God knows where those bytes are allocated).
Added robot model proper loading (we can do it better, though, by using libraries for the models, thus avoiding to load the same model for different robots).
I was at the Uni to debug the program and I noticed that ER-V is indeed right-handed, so I changed the framework's coordinate frame again. Strangely enough, changing the pretransform matrix was enough to fix this (no need to change rotation axis sense). I plan to investigate this further in the future, as I was expecting to have to change some rotations in kinematics calculations from clockwise to counterclockwise or viceversa.
![]() | ![]() |
Sensor active | Sensor inactive |
You can plug sensors into controller's input ports and read the sensor value from a program. The same goes for conveyor speed values, you can plug it to a controller and control the conveyor speed either using an interpolated position or a discrete output. You can also plug sensors directly into conveyors and robots.
Right now only ray sensors are implemented, but it should be easy to add other kind of sensors (cone, weight, area, segment). I took the ray AABB intersection code RealtimeRendering 3D object intersection page, which has a link to Pierre Terdiman's page.
Behind the scenes, there has been a major revamping in order to include input/output routing from controllers, sensors, robots and conveyors. This routing is supported via the IPortReadable interface, which allows a range of ports to be read. Ports are external outputs a controller, conveyor or sensor exports. The other entities in the system can consume those outputs in various ways.
There's some rationalisation and abstraction still missing as, although the framework allows it, arbitrary routing is not correctly generated from the .rbw file.

The controller is using the following program, where IN[1] is where the sensor is plugged to and axis 1 of GROUP C position is connected to the conveyor.
program sensr
define i
define spd
set spd = 20
open
moveld oper
for i = 0 to 20000
setpv cnvy 1 spd
move cnvy
wait in[1] = 0
wait in[1] <> 0
setpv cnvy 1 0
move cnvy
moveld grab
close
moveld oper
moveld drop
open
moveld oper
endfor
end
Ever since I saw ODE I've been wanting to do something like this:

The domino model is taken from windows TTF Arial font glyph. To get the glyph outline, I took the code from TrueType Font Secrets by Michael Bertrand and Dave Grundgeiger. You can actually dominoise any string you want :).
The con is that as soon as you have a few domino pieces on top of the other, ODE takes about 3s to calculate each frame (a step of 0.02s, five steps per frame), although I guess my scene database code is also to blame for that. The animation finished beforetime because of a stack overflow (even if the linker was set to use 12MB of stack), ODE is really stack-hungry.
In the first frames you can see a strange whitefan-like artifact centered on the image. This seems to be some TNT2's OpenGL bug :? (I don't draw white polys anywhere) and looks like it happens when I use too many polys.
ACL program debugging was broken because of the latest fixes to allow local directories on workspaces (the debugger was checking a relative path against an absolute path, the comparison never matched and you couldn't step, breakpoint, etc). I took some time to fix this.
When compiling for release, nicely stacked boxes in circbelt.rbw workspace would bounce as soon as you switched dynamics on. This didn't happen in a debug build. After chasing some red herrings about storing types and not pointer to types in some CArrays, I got to the conclusion that it had to be some FPU handling mismatch between release and debug builds (I saw that if I changed the top box position from 360 to 360.0001 the problem didn't arise).
When I mentioned the problem to mac, he reminded me the x87 extended internal precision (80bit) vs. IEEE 754 standard types (32 or 64bit) issues. It happens to be that the FPU internal calculations and FPU stack register sizes are 80bit. This means that operating on values spilled to memory do not give the same result as if the operands remained on the FPU stack (the latter keeps full 80bit precision).
He suggested using /Op (improve floating point consistency) compiler option and it worked!
While debugging the issue, I took some time to rework all the scene structures to use pointer to types as CArray element (as opposed to storing the type itself). This is needed because I use external references to array elements (CObjectInfo need to know about the CRobotInfo grabbing it and so on), and I cannot just use indices or the address of elements, as both can change when CArray elements are deleted or the CArray resized due to reallocations.
I also rationalised all the dynamics integration and the conveyor/object/robot handling by adding IStaticEntity and IDynamicEntity interfaces. No more conveyor hacked code!
Conveyors will only work if you have the dynamics module active (I plan to add a disable dynamics option). Although I've only done conveyor belt tests, I will add support for table conveyors as well (with angular motion instead of linear).
Right now a conveyor node is:
PROTO Conveyor [
field SFString name "" # Name of the conveyor
field SFMatrix frame 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 # Coordinate frame
field SFVec3f bbox 10 10 10 # Bounding box used for placing objects on top
field SFEnum type BELT # Conveyor type BELT / TABLE
field SFFloat speed 1 # Speed in units/sec (or angular speed)
field SFBool on FALSE # ON/OFF
# Merge speed with on/off ?
# Conveyor BELT direction is on XY plane towards +X
# Conveyor TABLE direction is on XY plane and concentric
] { }
I've hacked together some pieces of code to do a quick and dirty conveyor test:

When I leave the simulation running for a while, I have some problems with objects bouncing for no apparent reason before reaching the end of the conveyor. I think I'm leaving some hidden body in the system which causes objects in the conveyor belt to jump.
And here we have the table-style conveyor in action:

You can combine belts and semicircular tables (this is yet another rehacked version of conveyor) in such a way that a semicircular table forms the corner of two conveyor belts at both sides of the belts:

I tried building the circular belt out of two y-direction and two x-direction conveyors but the hard change of friction direction in the borders between x and y directions caused the boxes to jump wildy (half the box was pulled in x and the other half in y).
Semicircular conveyors avoid this problem because the friction direction in the boundary between conveyors is continuous. Nevertheless, I've noticed that the problem still happens once in a blue moon with the semicircular conveyor approach (and sometimes not even in the boundary between conveyors, which makes me hope this is just some bug I have somewhere.
The conveyor implementation is still a nasty hack (for example, I treat square conveyors as tables, half-square as half-tables and all the others as belts).
I've had strange problems with ODE because of using a scale bigger than the one in the examples (it took me a while to understand why my objects were sinking meters and meters into the ground plane and then floating up). All the CMF, gravity and ERP measures were wrong for such a big scale. I've added a scale factor to the models I insert in the simulation, so they match the scale used in ODE examples (around 1.0, as opposed to 300~500 units). Looks like ODE is a quantum dynamics library ;)
Even with the scale factors in, I had to decrease the simulation step from 0.1 to 0.02 so boxes stacked up didn't shake and crumble. This means that I iterate several dynamics steps for each graphics step (currently 5 steps to 1). I hope I will be able to achieve stability modifying ERP or CFM parameters, as the system is quite sluggish with such a small simulation step. I can also try David Whittaker's stepfast version, which should behave better with resting objects.


As you can see on those videos, I don't model the robot in the dynamics system, not even the grip (that explains why bars penetrate the robot):
PS. I had to remove Doxygen's documentation because I'm running out of space in my ISP's tiny account :(.
I've been setting up the project to compile release builds (I've been building debug all this time).
Doh! time: I had some trouble debugging the release build because, although I set the Generate Debug Information combo in "Code Generation" Tab, I forgot Linker tab checkbox.
And now the blues: When compiling for release, I've been getting non-sense access violations when trying to create objects from classes registered in my factories. I've tracked it down to MSVC insisting on calling the constructor of Factory on every file I call Factory::Instance().
My factories are singletons, so the constructor should only be called once. After some debugging I found that the reason why MSVC calls them several times, is because it inlines the Instance() static function wherever it's called. For some reason it forgets that it doesn't need to call the constructor everytime.
I solved the problem disabling inlining optimisations in the files where I call Instance() (yeah, sad).
Another problem I found was that Project Settings dialog box options didn't match to what it was really stored in the .dsp file, so I spent some hours hair pulling thinking that the fix I had found didn't work.
And last but not least, a few days ago I had to disable "intellisense" support because FEACP.DLL kept crashing when parsing one of my files, after modifying something on it.
I've fixed the ER-V kinematics problems I had introduced yesterday, so I can resume now the multirobot tests. Unfortunately fixing those problems became an issue of trial and error in the fivedof kinematics. I really have to rationalise the kinematics at some point.
On the multirobot side, I've created a small sample program:

When developing this shuffle test, I've noticed that a proper local coordinate frame shouldn't change the handedness of the coord system, otherwise you get "mirror" effects which cause rotation inversions at the joints: a given joint angle value will mean rotating right in one case and left in another (expected behaviour from using different handednesses).
What you really want is an even number of symmetry effects, so a given robot will always rotate the same way for a given joint angle value.
In the case of shuffle, both robots use the same program and positions without ever colliding (positions are specified wrt the robot local frame or in robot joint values), which is kind of neat:
dimp posa[3]
setpv posa[1]
2581
11982
-10346
-3249
0
setpv posa[2]
67
11543
-14526
-3248
0
setpv posa[3]
-2618
11922
-10395
-3248
0
program shufl
define i
moveld posa[1]
for i = 0 to 20000
open
close
movecd posa[3] posa[2]
open
movecd posa[1] posa[2]
endfor
end
run shufl
Just by implementing the kinematics for this robot (which is easy), you get a full controlled robot programmable in ACL (instantiating the ACL controller with 4 joints per Group A position).
This has served as pudding-proof of the flexibility of Roburgger's interface architecture, showing that adding new robot types is indeed easy. The idea is that it should be as easy to add a different controller/language (but I don't plan to do that at all!).
While implementing this robot I sort of broke the ER-5 support, because
the ER-5 kinematics do not zero at the same zero position as the
Denavit-Hartenberg model (ER-14 do, though).
Next thing I'll do is to change the kinematics to work using the zero DH
position (this was already in the list of tasks to do).
You can see here a video of the new robot in action:

I've also added per-robot coordinate frame, so now you can have several robots
in the same robot cell, each not only with a different center but a completely
different local coordinate frame (orientation).
I've also adapted the point and click interface to work with this generalised
per robot coordinate frame.
I found an interesting problem when implementing local coordinate frames: the VRML
models and default robot coordinate frame are left-handed, so when the local
coordinate frame is right-handed (due to this per-robot specifiable
frame) you have to invert the clockwiseness of the polygons described in the
VRML model.
I currently workout whether a coordinate frame is left or right handed by
looking at the number of minus signs of the orientation submatrix (I've
empirically verified that this methodd works).
The whole enchilada is this: when you double click on a viewport, you obtain window X
and Y coordinates to unproject, but the Z value is missing. That Z value is obtained
from the intersection of the X,Y ray (starting from the viewpoint) with the plane
parallel to the view plane and located at the current grip position.
That way, with two double clicks (on in XY viewport and another in the XZ one),
you can accurately place the grip.
I think this is the way
Cosimir works.
The biggest problem implementing it is that gluUnProjecting things didn't work
properly because I thought NDC Z values ranged from 0 to 1,
which is utterly wrong (Normalised Device Coordinates range from -1.0 to 1.0 for all three axis).
Errr ... actually I made two other minor mistakes like using milimiters instead of tenths
of milimeters and forgetting to apply the glDepthRange parameters when calculating
the OpenGL transformation by hand (nobody's perfect!).
Due to that, I began to think that I had misunderstood the way glOrtho worked
(the MSDN stating the wrong matrix for glOrtho didn't help much either),
so I spent a day testing several other glOrtho params and scribbling random figures on my notebook.

And now, today's video. It should ring a bell if you've studied Computer Science. It's
not really done algorithmically (I'm too sleepy for that), but it looks cute nonetheless.

I've discovered that the unestability of the CODECs was due to the Angelpotion CODEC (even if I wasn't using it for anything). Removing that CODEC fixed the program crashes when deinitialising the DLL. The program crash caused 100% CPU usage from then on and forced a machine reboot.
I found the offending CODEC by looking at the process name causing the crash and looking at that name at the windows\temp directory (CODEC dlls are written there as .tmp files before usage).
I'm now going back to test the paletted AVI support, looking at WriteAVI SDK sample which uses a 256 color bmp to create the AVI. Looks like you can use MS RLE CODEC only with 256-color bitmaps, but I haven't been able to introduce palette switches in the stream yet (I have a very disco-age-groovy avifile of the arm, you won't find that in shops and it's available only upon request!).
I thought I had found a solution: TSCC Codec for lossless compression but the version available on their website doesn't allow compression, just decompressión, so I'm sticking to MPEG4.

BTW, I've found that the MPEG4 CODEC doesn't work properly if the source bitmap's width & height are not multiple of 8 (it produces a sheared output).

This has actually been the first time I've used the ACL debugger: the first version of the program was wrong, so I used RobIDE to fix it interactively :).

So what's next? Well, proper object support (not just boxes) and physics!. After adding physics (read: ODE), there will be few things left to do, but to add a Conveyor type of robot, polishing the UI and the rest of the code (mainly error checking at kin & compiler level).
I was also thinking on coding an iterative generic DH solver (Cyclic Coordinate Descent), so you can use any DH described robots, we'll see (note that there are joint configurations where the greedy CCD approach cannot solve the inverse kinematics - think of a prismatic joint with an angular joint on the prismatic's axis).
I then empirically found that I had to scale by -1 in x instead of in z,
and also to scale the xa and xf values by -1. (Basically I just put in enough
minus signs after the fact to make it work.) Al Barr refers to this technique
as "making sure you have made an even number of sign errors."
"A trip down the graphics pipeline", Jim Blinn.
(as quoted by Carmack himself).
So true!. I've been spending (wasting actually) these days fixing some hardcoded calculations I had to the Denavit-Hartenberg vs. geometric model integration. You can tell the previous model wasn't quite right because the rotations weren't done wrt the z-axis (the blue one).
It turned out that I was using incorrect rotation matrices (one-too-many minus signs), which were making things work. As soon as I corrected them and removed some other hard coded calculations, coupled with changing to a left-handed coordinate system (the original robot uses that system), nothing worked and I was really puzzled.
At the end the problem was fixed adding an even number of minus signs here and there. The scientific reason is that left-handed coordinate systems don't hold the right-hand rule, which means rotations are clockwise wrt the axis (negating the angle does the job).
Using the the grip coordinate frame calculation, I've done a small object grabbing mockup: you can insert CObjectInfos in the scene and the robot can have one of them attached. Whenever the robot moves, it sets the attached object orientation and position to the grip one and voilá.


Although I understand the necessity of formalising robot kinematics, I see Denavit-Hartenberg notation as some kind of "direct kinematics for dummies". I've also found that you cannot faithfully model ER-V with a DH model, because of the waist to shoulder link.
I've gone through a big deal to match the DH model to the geometric model:
Although those calculations are performed at display time, I plan to change them so they are performed only at model loadtime. I have only one hardcoded value to remove kinematics-wise, which is the relationship between Denavit-Hartenbert zero positions and inverse kinematics solver zero positions. I may need to change the solver to use DH zero positions.
All this coordinate juggling really wanted me to add matrix-transformation classes to my roburgger::vmath namespace, so I have. They match the structure I already had for vectors:
Now I honor the controller node type field and the robot node solver field, creating the right kind of controller and solver by using controller and kinematics factories. No more acl.h and fivedof.h including in RobIDEDoc.h !.
The patterns are heavily based on Modern C++ Design ones:
// Kinematics solver factory singleton initialisation static Factory s_fact(kinematics::Factory::Instance(), "fivedof");
On a different front, I hand-compiled ODE and tested it with the test_boxstack sample program. Looks like it should be easy to plug into roburgger, we'll see.
I found a few glitches while compiling ODE, mainly some functions exported in the DLL's .def file which are not implemented in the code (this is due to the .def file being generated with a PERL script from an outdated file). Another problem is that the default makefile uses GNU's make (later on I found that you can get a win32 port of GNU's make from ODE's website), so I created my own VC6 workspace, which led me to including some legacy ODE files which don't have to be included unless you compile ODE in that legacy mode.
Yes, the environment works again and with the VRML model.

I've finally fixed the memory leaks caused by the watch window (a watch was created on every update and never destroyed). This implied adding DeleteRow notifications to the CTreeListCtrl, so user data can be deleted when a row is deleted asynchronously to the app (when DELETE key is pressed over a row or when an empty name replaces a valid watch - and thus the watch gets removed).
On a side note, watching the full controller in the watch window can make things
go quite slow if updated on every movement. I guess the reasons behind that are
having to parse and create the watch on every update (although this could be slow
due to running it in debug mode).
The solutions (besides compiling a release target) are to find a way of not
reparsing & recreating the watches on every view update (but this could be hairy
in case you are watching a variable with different types in several tasks)
or just not updating the window unless you are doing a step-by-step debug session
(which is what VC++ does).
I haven't been very productive code-wise, as I have been giving some thought to the
interactions between controllers, solvers and robots - how one and the other are
created and what degree of flexibility to allow.
I think I will hide the solver from the user: each robot will have its own
hard-coded solver (although internally solvers will be parameterised via link length,
robot geometry and decoupled-ness).
So finally the user won't be able to add solvers to the
workspace, just robots (I didn't see any sensible benefit in allowing adding solvers
without a robot attached to it - something like having a robot controlled by two different
controllers or several robots attached to the same interpolators of a controller is a nono
under this scheme).

I also had to add prefixing to FLEX and BISON, as now I have two lexers/parsers in the project and some symbols were colliding.
The VRML model looks nice :), although it doesn't move yet and some VRML code needs reworking:
The workspace is now loaded from a VRML file with user-defined nodes. The format is still preliminary but it looks like this:
#VRML 1.0
Workspace {
name "Test workspace"
path "c:\works\pfc\src\RobIDE\"
Controller {
type "ACL"
name "Ctrlr 1"
programs [ "acl\movetest.acl" ]
# Missing associations between interpolators & in/outs
Robot {
solver "fivedof"
name "Robot 1.1"
model "wrl\er-v.wrl"
}
}
Controller {
type "ACL"
name "Ctrlr 2"
programs [ "acl\test.acl" ]
# Robot {
# solver "fivedof"
# name "Robot 1.2"
# model ""
# }
}
}

I spent the weekend at Toledo
(the Spanish one, famous for swordcrafting and being the crossroad of the three cultures - arabic
, latin and jewish) and
Madrid, with some friends having tons
of fun :). If you like uphill cities, don't miss Toledo if you happen to be thereabout!.
When in Madrid, we also saw people's demonstrations against war in Puerta del Sol
and the police charges against them (I didn't see any violence in the demonstrations - I think
that one of the demonstrations was unscheduled, hence the police charges - the only thing
I can say is that the police vans running over and spreading dump bins splashed more dirt
than demonstrators did). People is getting really annoyed at the government here.
On a side note, I got nicely surprised at how many Spanish-speaking US americans tourists were in Madrid.
Back to work, I've implemented console input and output (PRINT, PRINTLN and READ commands) and added proper tabl control support. The tab control in the console/watch view is fully functional, so it actually switches controller when change tabs.
I've created a CControllerDoc that encapsulates each controller, so now the workspace
contains an array of those documents. The CWatchConsoleFrame is now independent from
the controller documents in the sense that you may have that window shown even if you don't
have controllers loaded. Maybe in the future I'll change that window to be a dockable one.
Because the controller documents are actually owned by the workspace document, the
CWatchConsoleFrame is never closed but hidden/shown (closing the frame would delete the
documents embedded in it).
Clock is ticking away and I still have to do lots of things :(, I hope I'll be able to plug in the first version of the 3D renderer views this weekend.


The CDocuments I have created are:
I'm thinking about the views I need beside the ones I already have.
There a few glitches with this approach:
Sometime after this checkin I will probably rename the namespaces from languages to controllers, acl to scorbot and introduce the kinematics namespace.
I've come across some precision problems with floats when using normalised plane vectors and
big coordinates (as a result of using the real robot measures). The offending code
was the movement following a circle (out of interest, the same code I fixed a few days ago).
I was testing against the cross product being zero (yeah, I know exact float testing is evil
but I need it for 180º tests and I get some moral relief from the fact that it's for zero-testing)
and it wasn't zero (but close to it), so the code was taking the wrong path (more exactly,
rotating against the wrong axis).
I could hack a fix using epsilons but I guess that using
epsilons is just sweeping the corpse under the rug, so I just removed some unnecessary
normalisations so the quantities calculated
are similar.
The other big change (besides file structure revamping) is that I've moved the
invkin / dirkin calculations to the PositionData classes: GetCoord,
GetJoint, etc, methods now calculate the direct and inverse kinematics if needed.
When the dir kin is modified, the invkin is marked as stale and viceversa, so before any
modification the proper stale flag is checked and the given kin recalculated if necessary.
I have to remove the method which allows to access directly to the position's
IntegerData (IIRC used only in watches), but other than that it works beautifully.
After some speed tests (sysmon pawah), looks like the thread-driven version will be needed: the processor is 90% idle when executing the program but it goes dog slow (right now virtual machine ticks are hooked on a 10msec WM_TIMER).
I've done a major revamp of file structure:
/roburgger roburgger.h roburgger.cpp /languages languages.h languages.cpp /acl acl.h acl.cpp instructions.h instructions.cpp operands.h operands.cppIn the future I'll probably nest the directory structure. I also moved some of the functions in acl.h to implementation files (acl.cpp, instructions.cpp, etc).
The drawbacks I find in keeping .h/.cpp split are:
The allieged reasons to keep the interface/implementation split are:
There's a weird problem with the Z-buffer at the Uni's machines. I believe it has to do with
ATI cards: The rendering looks like as if the z-buffer was disabled, so polygons further
away are rendered on top of polygons closer to the viewer. That could be because
of requesting a 32bit z-buffer and ATI card returning a 0bit z-buffer (this is just a
suspicion grabbed from thin air). I've just noticed that I don't set the glDepthFunc
, although it shouldn't be necessary (OpenGL warrants a default value of GL_LESS, which is
what I want). I've added initialisation code just in case and I'll retest next time I go to the Uni.
The fact that it works OK on MS's software renderer (XP, Win98) and on TNT2 and GF2GTS makes
me think that it's something dodgy in ATI drivers rather than in my app O:).
Oh, yes, and it doesn't work on WinNT 4.0 either. The MFC document menu doesn't show up (you only get the IDR_MAINFRAME menu), so you cannot do any debugging at all. I'm smelling outdated MFC libraries here...
I also found that ERV has decoupled kinematics even for joint coordinate system, so when you modify the shoulder joint value, the elbow motor encoder changes to keep the elbow-to-wrist link oriented. Note that even the elbow motor encoder changes, the elbow joint value itself doesn't change because joints for elbow (and wrist) are given in deltas from the previous joint (the delta shoulder-to-elbow remains constant when you modify the shoulder).
I've already modified my kinematics to mimic this behaviour and it's working fine :). In the way of doing that I fixed two features:
The fact that the program crashes at deinitialisation time wouldn't be so much of a problem if it wasn't because sometimes it doesn't save the AVI file properly and it always forces me to reboot afterwards (the latter looks like an interaction of using the CODEC in a console app, as it's the Winoldap process the one that locks up and causes cpu chugging and unresponsiveness).
I recoded from scratch the AviWriter I wrote at 3Dlabs (I didn't have the sourcecode), so now I have a tool to convert a bunch of BMPs to an AVI or to compress an AVI. It's slightlier featureless, but it does the job.
I've found a couple of good pointers on AVI creation (besides MSDN):
In the robot side of things, I fixed joint by joint interpolation of cartesian positions,
as it was never converting the cartesian positions to joints, but trying to convert them
to joints (isn't copying & pasting code great?).
I also added movement through an array of positions (MOVES command), although
current implementation will need some rework once I have the MPROFILE command in
place (MPROFILE has to be applied to the first and last positions of the array,
not to each position).

I've moved all the vector functionality to its own file (vmath.h in roburgger::vmath namespace). I've also added a simple Quaternion implementation to be used in the CircularMovement.
I say "the main problem" because I keep messing around with the coordinate frames and stupidly inverting the vector directions when dotting them (I also put one-too-many minus signs from time to time). Anyway, it's finally working, at least for the way I understand the decoupled nature of ERV.
I've also changed the CRobotCtrl to do the roll transformation on the grip, so now you can screw and unscrew things (screws).
I've coded my first mathematical vector classes. The way I've done them is with a VecN
template and with descendants of the template instanciation for 3 and 2 components (Vec3f
and Vec2f). The template, instanciable providing vector element T (double, float, ...) and
vector size (2D, 3D, ...) holds the common operations (VecN+VecN,
VecN*T, etc).
The only striking thing is that in order to be able to use those operations when working with template instances, I had to add a
Vec2f/Vec3f constructor from VecN, so it doesn't complain about
trying to use VecN operators on Vec2f/Vec3f.
Added mathematical vecN classes. Added inverse kin calculations (pitch vals need reviewing when moving away from the XZ plane).
The RobotCtrl control is the OGLCanvas descendant in charge of drawing the robot (currently it just draws a few boxes). I've fixed the robot control drawing for OGLCanvas changes (proper alignment of Y axis) and fixed normal calculation for each face.
I've noticed that the CTreeCtrl has a few glitches with the selection line when going to the first editable cell (it doesn't select the next row if the next editable cell is in the next row). It also happens to assert from time to time when moving through cells using tab. Needs investigating.

The graphic display reuses a hacked version of my OpenGL MFC control and is quite functional,
it's updated properly on each subtick (BTW, I finally fixed the subtick vs. debugging problem I
had yesterday) and you can see how the joint positions are smoothly interpolated. Heck, you
can even modify the POSITION variable in the watch window and the robot joints
get visually updated :).
If you watch POSITION variable (which reflects the current robot joint values),
it only updates when the movement finishes and the control returns to the debugger. I had
a version updating it continuously, but it was leaking too much memory so I removed that
(I have a - hmmm - benign leak in the watch management and when breaking into
the program back to the VC debugger I would get minutes and minutes of VC's memory checking
dumps).

PS. I have to admit that after all this time doing non-OpenGL stuff, I had forgotten even how to draw polygons and it took me some hours to get them with the right colors - argh!
I've added movement support to the virtualmachine. Right now only for joint-by-joint
interpolation, but the framework is there for all the others as well.
The current status is that you can use MOVE and MOVED commands,
and the current position is interpolated to the destination position in several ticks.
If the task is put to sleep (MOVED command), it's awaken when the movement
finishes.
The movement is stored in the movement buffer, so in case this or other tasks append
movements the system should take care of it (note that the buffer is currently unsized,
but should be easy to add blocking when inserting in the movement buffer to simulate
the real behaviour).
I've changed Tick so it takes several ticks to execute one instruction, this
is so with a view to hook the movement feedback via graphics in the Tick
function as well (so a tick is actually a subtick from an instruction standpoint).
This currently causes movement to interact with the step-by-step debugging in a weird way:
when you step over a MOVED, the next subtick finds the task sleeping
and it cannot update the instruction pointer to the right line of the program in the
text window (as no instruction is currently being executed).
The next time you press step over, because the current task is NULL,
it completely forgets that you were debugging a specific task and it does a
free-run instead. I haven't investigated a solution to this yet.
Next I'll add a very simple wireframe OpenGL rendering so I can check that movements work as expected. I'll also add inverse & direct kinematic hooks (I have the invkin calculations from the robot the uni previously had).
I've also fixed a stoopid bug when watching array elements (you would always see the contents of the first element). That bug made me think that the movement interpolation wasn't working, when it was the watch I used what wasn't working.
After sorting out the problem by working out a grammar to resolve ambiguities, finally watches are fully working (setting &
getting).
The last thing I may need to add to watches is to make them fault tolerant (I guess they
assert wildly right now if you provide incorrect expressions) and maybe simple arithmetic
operations (+, -, /, *) and relational (==, >=, <=, >, <) so you can use the
expressions for data breakpoints. But I want to progress with the main framework before getting
on these nit-pickers.
EXPR
: !
| TASKNAME
| TASKNAME!VAREXPR
| VAREXPR
VAREXPR
: INTEXPR
| POSEXPR
| ARRAYEXPR
INTEXPR
: ARRAYNAME[EXPR]
| POSEXPR.INT
| POSEXPR.FIELD
| INT
POSEXPR
: POSARRAYNAME[EXPR]
| POSARRAYNAME[EXPR].
| POSNAME
| POSNAME.
ARRAYEXPR
: POSARRAYNAME
| INTARRAYNAME
| POSARRAYNAME[]
| INTARRAYNAME[]
FIELD
: 'X'
| 'Y'
| 'Z'
| 'P'
| 'R'
INT : any positive number or 0
In summary:
Today's screenie is the new watch expressions in the works. You can see how you can index an array with an arbitrary complex expression:

[HKEY_LOCAL_MACHINE\Software\SourceCodeControlProvider] "ProviderRegKey"="Software\\Microsoft\\SourceSafe" [HKEY_LOCAL_MACHINE\Software\SourceCodeControlProvider\InstalledSCCProviders] "Microsoft Visual SourceSafe"="Software\\Microsoft\\SourceSafe" [HKEY_LOCAL_MACHINE\Software\Microsoft\DevStudio\6.0\Source Control] "Disabled"=dword:00000000

When trying to use "window standard scrollbars" to my CWatchCtrl (as opposed to independent scrollbar controls), I've noticed that STATIC controls do not forward click events to those scrollbars (no matter what static style you set to it). Using a BUTTON instead of a STATIC seems to work.
As usual, MSDN doesn't say anything about this (or it doesn't say it in the correct help topic).
Well the scrollbar interface is now working. I finally derived the CWatchCtrl from my own registered class (deriving it from "BUTTON" worked but caused a very big grey button to be drawn). There are still a few quirks with pageup/pagedn keyboard interface, but it more or less works.


Here's the latest version:


So I've built my own CStatic-derived control. Right now it allows inplace editing of cells, navegating with tab/return/updown, and row selecting with mouse. It's not very flicker free yet, and it lacks headings, a vertical scrollbar , column resizing and tree-like behaviour (hiding/showing files). I hope to code these shortcomings tomorrow.
On the language side, I've coded some functions to get WatchedExpr.
NAME | VALUE | accessor (hidden from debugger output)
arrayname | {...} | arrayname
[0] | 225 | arrayname[0]
[1] | 256 | arrayname[1]
[2] | 1 | arrayname[2]
the expression to watch is "arrayname", but the WatchedExpr returned is one
composed by a base WatchedExpr with the accessor "arrayname" and several embedded WatchedExpr
with names "[0]", "[1]", "[2]" and accessors "arrayname[0]", "arrayname[1]", etc. This decouples
debugger-shown representation (the "name" of the expression) from the language-specific way of
accessing one variable.
While coding the watch control, I've watched (heh) a very moving movie (doh, this sentence is getting worse every moment), Hilary and Jackie, about the life of sisters Hilary and Jacqueline Du Pré (the latter a very well known celist player, who married famous pianist/conductor Daniel Baremboin). I won't spoil the film here, so I'll just say that the story is very interesting and touching, with a superb classical music score, so don't lose the chance of watching it if it happens to be aired at some TV channel nearby.
BTW, I was told that there's a Lua WSH port and indeed there is
My dad spotted that one of the round shaped pieces inside the supply was burnt. The piece is an NTC thermistor, a temperature-dependent resistor in charge of regulating the fan speed (google pawah). Looks like common resistor values for that piece are in the order of 10K ohms (as seen in some schematics on the net), but those pieces don't normally have a quantity label attached (and even less the one I have, as it was really burnt).
So I went out for the NTC hunt, but I only found 5K ohm thermistors and they were too small for my likings, so I bought a new power supply for 20 euros (I found 300Watt power supplies for 20, 30, 40, and 46 euros, so you'd better watch out when buying this kind of things).
Regarding the progress (no piccies today), I have the instruction debugging fully implemented and hooked to the Scintilla test app:
I think this method is "language agnostic" as, for example, a recursive language (which ACL is not) could return the stack pointer if it can reenter subroutines, etc, so you could use the same debugger framework and just plug in the new interpreter.
Currently, the only problem is that I run the instruction interpreter hooked on an OnTimer, this means that each tick takes 10ms. I plan to move it to a different thread and run it full speed so if you are waiting for a breakpoint to hit you don't have to wait 10ms for every instruction it has to execute (unless you are in wall-clock accurate mode). This will introduce the usual multithread fun ;/.
So regarding the debugger, I have only missing symbol debugging (watches!), and maybe data breakpoints (once I have watches, that should be a child's play).
Oh, yes and I've been told that VC7 accepts void *rawMemory = operator new[] (10);, there it goes my call to fame :(.

One of the uses of this reverse lookup is to set breakpoints and check that the text line where the breakpoint is set contains an executable instruction, otherwise the breakpoint is moved to the closest line with a valid instruction. Plugging in proper breakpoint handling is trivial from there.
I've also noticed that Scintilla's markers have priorities, i.e., marker with higher ids are drawn over markers with lower ids. This means that the marker id signalling the current instruction must have the highest id (so it's displayed over breakpoints, bookmarks, etc).

I went into a lot of trouble to get the pixel data from a memory HDC when using DrawIcon to render an HICON extracted from an IMAGELIST. For some reason, the icon would be drawn at x2 size (it worked ok if the icon was a plain HICON resource), so I've finally calculated the masking myself by accessing the mask and color bitmaps and not using DrawIcon.
I've also corrected some debug information mismatch when producing ELSE and
ENDIF code (the file line would point at the wrong line) and rationalised which
instructions are executed by the true branch of the IF and which are
executed by the false one:
This will affect which lines you can put breakpoints on and when they trigger. It more or
less follows the behaviour of VC++.
IF cond -> Executed by both
instr -> Executed when cond is true
ELSE -> Executed when cond is true
instr -> Executed when cond is false
ENDIF -> Executed when cond is false

After spending the last few days blindly hacking my Scintilla MFC wrappers (CScintillaEditCtrl.h and CScintillaEditCtrl), I've finally been able to actually see some code being run line by line.
Today I've added debug information retrieval and request to the virtualmachine (get filename & fileline from the instruction to run). This allows to do a "step by step" execution and that's what the previous picture shows. I changed the Scintilla wrappers to use 1 as first line instead of 0 (I find it a bit strange that there's a "line 0" of a text).
I still have to add:
I really need to begin to use source control <argh!>
I found an interesting article by Paul Di Lascia on using CControlView to create views of controls. The bottom line is that CControlView (deriving the view directly from the control) is quite unless your control doesn't have extra local data (nor virt funcs), so I may create a thin CUserControlView to encapsulate the onsize & onfocus changes needed when going the route of making the control a child of the view.
Oh, yes, I almost forgot, these past days I also added parser support for SETP/MOVE instructions.
I still have to:
The Interface base class is working ok, although I've found a strange problem with VC++ not being able to do *pIntReadWriteable = iMyInt;, although it's able to do *pIntWriteable = iMyInt, looks like some int constness problem in the IntReadable interface :? (out of interest, MEC++ recommends not to virtualize casting operands, shame on me).
I'm still thinking on using exceptions and rewrite some parts to exception-safe code (probably using auto_ptr).
Other implementation alternatives would be:
With regard to the global progress, normal set operations are now implemented, still thinking on how implementing PVAL and PVALC (maybe creating a new IntFromPosOperand)
So the symbol table needs redesigning:
Still not very convinced on naming conventions. Right now I'm using smallcaps namespaces, capital initials for classes and
methods, able for interfaces, m_ for members, initial capitals for compound
variable names (aka camelcaps) and a bit of hungarian notation (initial p for pointer variables, etc).
I still think that the CACLWhatACuteClassIAm looked very nice.
On a side note, VC 6.0 / VC 7.0 don't seem to accept void *rawMemory = operator new[] (10); although gcc does. This is somewhat important because it's written on page 21 of More Effective C++ by Scott Meyers. If this was a true typo, I could send it to Mr. Meyers and I would appear as collaborator in the next reprint of the book (wow!).