Menu [Hide]

Cicada Developers Blog

Print

Cicada

draw with turtlegraphics - animate with turtlegraphics

Copyright (c) 2010, C J Hilder, cj.hilder@clear.net.nz
 
Cicada is work in progress. It is open source and free. Cicada adds object-oriented 3D turtlegraphics to Python using Panda3D.
 
Philosophy

Cicada is a programming environment that allows you to learn a computer language in a way similar to learning a natural language - starting with a subset of a fully fledged language instead of starting with a "toy" language and then having to learn a different language when you are ready to do more complex things.

This is possible with Python. Python has a sufficiently simple syntax that it can be used with young children, and also has reasonably wide professional use. The need for parentheses on every command (function invocation) and case sensitivity are both traps for young players. These can be largely circumvented with a suitable drag-and-drop interface.

Logo is a langauge that was originally designed for children and it certainly functioned in that way, but only as a "toy" langauge that has never had a professional user base. One reason for this status was the unusual syntax, another was the lack of good graphics, GUI, and so on. However, Logo did popularise turtlegraphics which I believe provides a very useful tool for the beginner programmer. While Python might have a suitably simple syntax, the straight text interface does not excite!

Adding object-oriented 3D turtlegraphics to Python has been made possible with Panda3D. This is a professional-grade 3D rendering engine. Cicada gives beginners control of a sophisticated 3D renderer, allowing them to use progressively more of its power as they develop the skills.

To preview Cicada
Documentation is still rather slim. More to come later.
 

The stand-alone Windows Installer:

Download the latestest version from http://teach.hilderbuild.com/cicada/

For non-Windows platforms:

  1. Download and install Panda3D, latest snapshot version 1.7.1. (the version used for development is Panda3D-2010.08.20-108.exe)
  2. Download and install wxPython runtime for Python 2.6. (the version used for development is wxPython2.8-win32-unicode-2.8.11.0-py26.exe)
  3. Download and extract all files from the latest Cicada zip file (scroll down and click 'files attached').
  4. From the command line launch main.py

If you already have a version of Python installed you will need to make sure that when Cicada runs it runs under the Python files included as part of the Panda3D package. Panda3D 1.7.1 installs Python 2.6, which is not the latest version of Python. You might have Python 2.7 or higher installed already. Multiple versions of Python can happily co-exist on your computer, but Panda3D is compiled for a specific version of Python and might not work under other versions.

Done
  • sprite drawing in wireframe mode
  • traditional turtlegraphics command set: forward, back, right, left, penup, pendown, setPos, setHeading, setPenColour, clone, stamp...
  • enhanced turtlegraphics command set: up, down, rollLeft, rollRight
  • kinetic ink command set: turn the sprite drawing into the sprite persona, e.g. adoptDrawing()
  • load 3D models (and their animations) as sprites
  • crude CLI for demo purposes
  • catch exceptions and give error messages from the CLI
  • run code in separate thread for each sprite:whenStarted(...) and start()
  • separate animations for walking sprites
  • default sprite
  • sprite can draw triangles with colours and texture (limited flexibility of texture drawing)
  • sprite text and 3D text
To do (in no particular order)
  • technical issues to do with threading:
    • at the moment wx function calls are all coming from a task - this means that a programmer using Cicada will crash the system if they use wx because that will call into wx fom a different thread. Ultimately it will be necessary to use acquire/release around all wx calls, and/or to run wx from its own thread.
    • workspace management needs to be rewritten to allow for full support of classes and modules, as welll as accurately detecting changes that need to be saved before clearing the workspace. Some global variables need to be preserved at least in name in the saved file e.g. sprites.
    • Cicada uses simple threads, ultimately true threading will be needed to allow programmers full choice about how they write code
  • workspace management
    • add ability to delete functions from the workspace
    • switch toolbar to dock at the bottom when writing pane is maximised
    • keep test code in source memory for each function defined
    • detect changes in writing pane and ask if losing changes when clearing or saving with uncompiled modification to a function definition in the pane
    • edit should position cursor and scroll to left edge
    • possibly edit should be additive so that you can edit more than one function at a time
  • textures need to be able to stamp correctly (at the moment they follow the sprite not the drawing)
  • there appear to be rounding errors causing forward and back to not be symmetrical - maybe necessary to compile Panda with extended precision
  • talk to groups of sprites
  • separate animations for standing, walking, and turning sprites
  • sprite can draw arbitrary surfaces with colours, textures and bumpmaps
  • sprite can draw circles, spheres and tubes
  • sprite can draw with an italic pen that draws surfaces with colours, textures, and bumpmaps
  • sprite can carry the camera, and can shine light
  • camera control something like the Google Maps control - with pan and zoom - allowing you to navigate an arbitrarily large world
  • sprite can carry particle emitter
  • sprite can start blocks of code (threads) in response to messages (consider gist.github.com/50140)
  • 1 sprite step = 1 mm on screen
  • sounds
  • collisions
  • gravity (sprite in free fall)
  • improved GUI with management of classes and modules, as well as improved load/save/edit facilities
  • workspace managed as a filedict
  • friendlier error messages
  • dialog box interaction to set up a new model (egg file) for use as a sprite persona (set scale, heading, xyz offsets, animations)
  • support for naming sub-parts of a sprite(mergePersonaAs) and addressing them directly to alter joint positions
  • drag and drop IDE (similar in concept to the Scratch interface)
  • become world famous for developing such a wonderful application
Related resources

A fully 3D capable version of Logo: Elica.

2D Turtlegraphics in Python: xturtle.

Cicada image on this page from Larivière, M.-C.; Rhode, B.E.; Larochelle, A. 2006 (and updates): New Zealand Cicadas (Hemiptera: Cicadidae): A virtual identification guide. The New Zealand Hemiptera Website, NZHW 05. http://hemiptera.landcareresearch.co.nz/ accessed 12/7/2010.

Blog

The biggest challenge in getting the basic moves (forward, back, left, right, up, down, rollLeft, rollRight) working was understanding the coordinate geometry and matrix transformations involved. It took a while to get the orientation of the three axes into my head, and also the way Panda3D considers a heading of 0 to be pointing along the +Y axis. Calculating the axis of rotation for left, right, up, down was actually quite tricky and required a good grasp of the 3D geometry involved. Once I got all that sorted everything else has been very easy - Panda3D is very robust, logically constructed, object-oriented, and has built in commands for almost everything you want. After version 00.00.02 I think it will just be a matter of adding features one after another; looks like there will not be any tricky parts to work out! -- 30/5/2010

A bit of effort getting wxPython working under the Panda, but all sweet now! Version 00.00.03 has a crude interface, but functioning. -- 1/6/2010

Version 00.00.04 is proving challenging. Animating commands such as forward and back requires careful use of sequences. This version is not working yet!! Ok, I confess - this is major. The whole concept is fraught. Animation software, like Panda3D and also Flash etc, is typically event driven. Normal sequentially executed code is an anathema to such systems. All code must execute between frames, and continuous processes are constructed from functions that are called once per frame. Specifically you cannot do things like

while animation is playing:
       pass

The code runs between frames, so the frame never advances and the loop never exits. However, my ambition is to create an animation environment where you can animate with commands like forward and right. Such animation is not event-driven. Version 00.00.03 does not have any animation and works perfectly well. However the turtle jumps from end to end of every journey. Version 00.00.07 overcomes this and has animation as the turtle moves forwards, using a Panda3D posInterval. Everything waits while each animated move completes. Turtles can never move at the same time, but it works. Version 00.00.06 is an attempt to get threads working - the idea is that every turtle runs in its own thread, so if a turtle needs to wait for the animation to complete, it can do so without holding up other turtles. Unfortunately this technique is not yet working. It appears that you cannot modify the Panda3D world from more than one thread at a time. It might be possible with AsyncTasks, but there is no documentation for them. Version 00.00.08 is the most sophisticated. It ques the turtle move animations as Panda3D Sequences, yet waits for them to complete only when it must. This is a compromise, but at least it is working. - 5/6/2010

With a little help I now have threads working. Basically Panda3D, when compiled with Simple Threads, uses a cooperative threading model that requires

while animation is playing:
       yield

Recompiling Panda3D without Simple Threads will enable 'true' threading which does not require yeilding. I have also found that threads that start new threads (nested threads) do not return properly, however threads can be started by the AsyncTaskManager and these work correctly so this appears to be the way to go. - 11/6/2010

Problems with nested threads are now emerging. I may need to write my own thread manager to start threads always from a regular task in the task loop (instead of allowing them to start threads themselves they would just go into a que, and my thread manager would start them when it runs in the task loop) - 12/6/2010

Version 00.00.15 has a thread manager and so far threads appear to work ok with hundred (even thousands) of threads running successfully at the same time. Some further work will be needed to assure that Cicada code is threadsafe, but the basic structure is in place and working. Try example1() then example2(). - 13/6/2010.

Version 00.00.16 has animations for turtle moves. It took a while for me to work out that the extremely complicated 3D matrix calculations I was doing became trivial once relative nodepath transform setters and getters were used. In the end these were the only practical way to do the animations because when the turtle rotates, its nose needs to follow a great circle path. This is extremely difficult to do using HPR unless you use relative transforms meaning you adjust only H, P or R to achieve a rotation whatever the starting orientation was.

Animating lines while they are drawn was another tricky thing. A separate node was used to which the line is parented while it is being animated. After that it is reparented to the drawing node. Version 00.00.18 is basically useable. It establishes a turtle named "x". Commands like x.forward(100) and x.right(90) can be used to move the turtle. - 17/6/2010

Animating lines completed the animation of turtle moves and appeared to introduce jerky animations. I fixed this by replacing Thread.forceYield() with Thread.sleep(0.04). This works (for whatever reason) to ensure animations are smooth. - 24/6/2010

Preparations for release of version 00.01.00 are now under way. Heres the list of must-dos for that release...

  1. load and save Cicada workspaces - done 27/6/2010 - version 00.00.22
  2. edit function definitions in the command window - done 27/6/2020 - version 00.00.22
  3. integrate the IDE windows into a single application window - done 1/7/2010 - version 00.00.24
  4. include the ability to stop running threads and sequences - done 9/7/2010 - versions 00.00.27-29
  5. implement a system for drawing triangular surfaces and write text - done version 00.01.02 - 13/7/2010
  6. set up default turtle - done 10/7/2010 - version 00.00.29
  7. package everything as a single self-installing download - done 1/7/2010 - version 00.00.24
  8. Name change from Kink to Cicada(nesessary because of the existence of kink.com) - done 9/7/2010 - version 00.00.27

Interesting bug emerged with situation of adoptDrawing() followed by adopt(panda) causing weird crash. Fixed with workaround of using stash() instead of removeNode() for cleaning up drawings after adoptDrawing(). Don't fully understand. Could be I am doing something silly, could be a bug in Panda3D.

Version 00.01 released. Feature set is complete for this version, but it still has known bugs of a subtle nature (see above). It's actually quite useable, and can be reviewed in its present state - version 00.01.02.

Version 00.01.03 uses Panda3D 1.7.0 (an upgrade from 1.6.2). This has made no difference to the bug situation - a solution is still being sought. Version 0.1.5 is quite stable, with a workaround for the bug.

As far as solving the bug goes: it behaves in every way like a dangling pointer or memory overwrite issue. It comes and goes in unpredictable ways when you add/remove code from anywhere in the program. Once it first happens, it keeps getting more frequent. It is only triggered by stashing, detatching, or removing graphics elements that have been animated with an interval that has finished, but it is not consistently triggered. It looks like, once triggered, it is a fragment (ghost) of the interval that continues to try to animate using dangling pointers. Attempts to ensure the intervals have finished (even as far as using .__del__() on them), have failed to alleviate the problem. The IntervalManager thinks they have been finished and removed and appears powerless to do anything further with them. The situation occurs regardless of whether the graphics in question have been created by a function running within a funtion interval, or not, and regardless of whether they have been created in a task or a thread.

Roadmap from here: (16/7/2010)

  • develop the smallest possible code example that exemplifies the bug and send to David for him to work on.
  • A few small changes to turtle commands: setPenColour -> setColour; showActor -> showTurtle; clearActor -> adopt(None); setActorScale -> setSize. Make sure setColour and setSize will take as inputs the outputs of getColour and getSize.

It didn't work!! :( The smallest possible code snippet was about 400 lines of Python code. It consistently caused the bug on my two laptops, but worked perfectly on one of the school computers. It also worked perfectly on both of my laptops under the latest snapshot build of Panda3D, but using this new build my main program crashed. Something to do with wx, but again no definite solution - I have started the 0.2 branch building on 0.1.10 and chipping out bits of the wx interface to see if I can get an answer. However, another possible branch is to abandon the Panda3D threading mechanism and use Python threads doing my own thread locking for every Panda3D call. This has the disadvantage that users must go through specific threadlocking protocols before using any native Panda3D calls, but the distinct advantage that it would avoid any bugs in the Panda3D threading code - which seems to be the problem at the moment. David cautions that ordinary thread locking doesn't guarantee problem free operation with reference counted obects because they can go out of scope at any time, but I think this might not be an issue because you are essentially forcing all Panda3D calls to happen one at a time - any operation that modifies a pointer must essentially complete before it releases the lock. I think it might be worth a shot, and be more reliable that the present system which is highly unstable and totally shonky!!!

Version 0.2.0 (August 21) retains Panda3D cooperative threading and animation with intervals and sequences, but drops most of the wx interface. It seems to be working correctly with all test software passing at this time. The next challenge is to build a decent wx interface without triggering any problems.

Version 0.2.1 (August 25) now has a basic wx aui interface - all systems go! The program will not exit normally when launched from within PyPE, but exits just fine when launched from main.bat.

Version 0.2.2 (August 26) is now stable. Basic functionality is now complete, although the user interface is still pretty dire.

Version 0.2.5 (September 4) now has respectable interface, but still no documentation. Alpha release. Next release will be same code with a wee bit of documentation.

Version 0.2.6 (September 6) changed Turtle to Sprite, turtle actor to sprite persona. Minor bug fixes. Still in alpha.

Version 0.2.8 (September 13) added a set of examples and some minor tweaks to workspace management. This version is now ready for user evaluation. Still in alpha - no known sources of crashes except allocating too many threads, several incomplete features such as textures and workspace management.

Last edited by System Administrator .
Page last modified on Monday 13 of September, 2010 20:44:24 NZDT.


RSS feed Wiki