RapCAD printer interface

I have been starting to think about how to integrate the controls for my Reprap Mendel into RapCAD. I was inspired by Kliments pronterface console which as well as being colorful also looks very intuitive and clutter free. So far all I have done is added a simple prototype GUI interface which can be accessed via the print button from the RapCAD main toolbar. This will allow basic integration and testing with the libreprap library.

Ideally of course I also need to finish off the remaining electronics on my Reprap Mendel so that the integration can be tested properly. So in many ways I want the features that I am developing now to motivate me to finish of my Mendel, which after an initial bout of progress has been sitting on the shelf and collecting dust for a year. The reason it has been so long is that I got distracted writing RapCAD. For some reason I thought that I would have enough time to spend on both projects, but as always I am going to have to manage my spare time more carefully.


Version 0.5.0 is available this month. See the Download Page for details.

Advertisement

RapCAD dynamic arrays.

Just a short post this month. I just wanted to give an example of dynamic arrays which are available in RapCAD version 0.4.0. The screenshot shows what I came up with. Not very exciting, but hoping that this will help William Adams to realise some ideas that he has had regarding this. The thing that makes dynamic arrays work is the concatenation operator ~ and the append operator ~=. The operators were influenced by thier counterparts in the d programming language. On another note I have been talking again with Marius who has been looking at the RapCAD back-end code, he seems quite interested in collaborating on a shared back-end library. At this stage he is working to get his visitor branch into OpenSCAD master. When this is done and stable we would like to put some of RapCAD’s features such as this one into OpenSCAD.


Version 0.4.0 is available this month and supports Dynamic Arrays. See the Download Page for details.

RapCAD imports

The syntax for importing modules into rapcad is quite different from the legacy way of doing it. I decided to break compatibility because of a number of problems with the old syntax, that arise when you want to quickly scan for dependencies. Lets first consider a valid example using the old syntax.

module foo(){
  module bar(){
    import_stl(str("file","name",".stl"));
  }
  bar();
}
foo();

The first problem with this is that the filename argument is actually an expression. If you were parsing this script to find its dependencies, the parser would have to be able to partially evaluate the script, turning str("file","name",".stl") into the string literal filename.stl. The second problem is that the import statements are nested in several sub constructs, meaning that the parser has to understand these constructs in order to extract the import module statements. Last of all the legacy way of importing seems to be inconsistent with the way ‘use‘ and ‘include‘ statements work.

My solution was to add an import statement which works as follows

import <triceratops.off> as dino;

dino();

The import statement appears at the top of the file and it doesn’t take an expression, only a string literal. It cannot be nested, and it fits with the use and include statements. The statement is followed by an ‘as‘ clause and the identifier following the ‘as‘ clause provides a name which can be used to instantiate the imported module. The module can be instantiated any number of times, just as you would any other built-in or user defined module. The module instances can of course be nested in any other construct as required, but the import declaration remains at the top of the file, and so one can easily glean which files the script depends on.


Version 0.3.0 is available this month and is capable of importing OFF files. See the Download Page for details.

How RapCAD will do CAM.

The intention of RapCAD is to provide a programmers IDE that will allow the user to not only model their ideas, but also prototype and manufacture those ideas. Initially the focus is to support additive machines like Reprap and Makerbot. However maybe people will want to use it one day for controlling subtractive machines such as CNC routers, or Laser cutters. To support this I wanted to add as much flexibility as I could to the process of converting the description of the model into GCODE instructions that will create the model.

The idea is to use a special type of RapCAD script called an .rcam script that will perform the slicing dicing and generate paths that will be used by the GCODE generation code.

/* Manufacture module called by RapCAD.
* RapCAD will measure the bounds of the
* final model and pass the model to the
* manufacture module. The size of the
* model is made available via the $bounds
* vector. The manufacture module will be
* called for each layer, the output should
* be a 2D path.
*/
module manufacture(){
   echo("Printing object of size: ",$bounds);
   echo("Printing layer: ",$layer," of ",layers());
   infill(0.4) {
     inset(0.4) {
      slice(h=0.4,cut=$layer*0.4) {
       child(0);
      }
     }
   }
}

/* Layers function called by RapCAD.
* RapCAD will call this function to determine
* the number of layers in the model
*/
function layers() = $bounds.z/0.4;

Apart from the file name extention this script is only different from a standard RapCAD script by the definition of a module which must be called manufacture(), and a function which must be called layers(). The idea is that RapCAD will have all the modules needed for turning a primitive into a set of paths. The paths will then be sent to the GCODE generation routines. The most important module needed for turning a primitive into a path is the offset() module. In Fused Filament Fabrication, we have to shrink the shape by half the thickness of the filament, so that when the model is constructed it fills out to the correct size. A more obvious module is the slice() module, which is responsible for turning the three dimensional form into the two dimensional slices that are build up on top of each other during the printing process. In addition to others there will be an infill() module that given a two dimensional offset polygon will turn it into path roads ready for conversion to GCODE.

When RapCAD is asked to generate GCODE for the given design it first compiles and renders the description into a primitive and adds the result to a cache. The bounding box of the primitive is calculated and then the layers() function within the .rcam script is called to determine how many manufacturing cycles will need to be made. Then the manufacture module is called for each cycle, each time passing the full cached primitive and an incremented value accessible via the $layer variable.

RapCAD will come installed with a standard .rcam script designed for a reprap machine, but I hope that by giving people the flexibility to tweak the scripts, new and better ones will be written.

That’s the plan, now I just have to implement it!


As promised there is a new release of RapCAD available. This months release of RapCAD can be installed by following the instructions on the new download page

For those who want to know what has been added please see the release notes

RapCAD preview release

I decided to build a binary release of RapCAD so that people can have a look at how things are coming along without having to compile it. Its very much in a pre-alpha state so don’t expect to be able to just try out your latest greatest design and just expect it to work. Furthermore it can’t currently create any output in the form of an STL file or GCode, so it really is just a release that will let you preview a design. That said there are some nice features that I would like people to try out and see what they think. Language features such as true variables and functions with bodies seem redundant now when other projects such as openscadpy are boasting full python language integration. Having said that RapCAD scripts and OpenSCAD scripts are a DSL which is nice to use and since it has no general purpose language features such as reading or writing files, network access, etc. The scene descriptions are inherently more secure. While the authors of the software RapCAD, OpenSCAD and openscadpy are known and trusted, the authors of scene description scripts uploaded to to Thingiverse may or may not be trusted. By limiting the language features to the domain of scene description this mitigates any risk.

The features that I am developing now could go into openscad eventually, although some of the things that I am doing would require a substantial re-write of the openscad backend, such as dropping openscads 2D subsystem. (It turns out that the entire 2D subsystem can actually be done using 3D shells that have no internal volume, including boolean set operations) For those who want to try out this release instructions for installation on three popular operating systems; Windows, Ubuntu and MacOSX, can be found in the Download Page

I intend to create binary releases about once a month from now on. Next month I hope to have a release with OFF file export (Its supported natively by CGAL so should be easy to implement) and maybe native support for Bezier surfaces since I have been very interested in the work done by WilliamAAdams here is a sneak peak:

The linear_extrude is not quite working the way I would like yet, as currently it evaluates it by creating a volume for each facet and doing a union of all of these volumes. With it taking 2 seconds for each volume union, the total rendering time is a completely unacceptable 39 minutes! I would like it to work by just creating one volume, but I haven’t worked out how to find the perimeter of the Bezier surface yet.

On the other hand creating a convex hull of two Bezier surfaces works at a comparatively much more acceptable speed, about 18 seconds.

RapCAD is Rendering!

Last month I was saying I was going to hook the OpenSCAD back-end into RapCAD. It turned out to be simpler to just implement a backend myself. I started off implementing the GLView widget. I would have had to have done this anyway, since I didn’t want to hook any of OpenSCADs GUI code. I learned a lot doing this, and I think my version has better performance than OpenSCADs version so I will be proposing some performance enhancements to be backported into OpenSCAD at some point, as well as completing a feature request in the TODO list which is to have ruler ticks on the axis. I implemented something similar for RapCAD which is the outline of the 200x200mm printable area, so it should be quite easy. The next thing I put together was a CGALRenderer class, which converts CGAL primitives into openGL. The design is based on the Strategy Pattern rather than OpenSCAD’s messy rendering function pointer callback, I think this is something that could potentially benefit OpenSCAD as well, so I have already started to backport these changes in a cgal-renderer-refactor branch.

Once these two things were implemented everything seemed to come together quite quickly. So recently I have been adding all the bells and whistles and fun features like “ThingDoc” style code comments. Convex Hull for 2D & 3D primitives, and Minkowski that works with mixed 2D and 3D primitives.

Talk with Marius

I have been trying to understand and document the windows build process for OpenSCAD so that Marius and Clifford might soon be able to publish a new release.

While doing this Marius and I got talking. Specifically he wanted to know whether the work I had done for RapCAD on variables would work in the OpenSCAD back end. I told him a bit about the parser I had implemented, and how I thought that a strong concept of Statements within the language syntax would be needed to support this. We agreed that (like many projects) the OpenSCAD language has evolved over time, and its evolution had led the design to a more Declarative syntax rather than a Procedural one.

Marius also asked me whether it makes sense to write my own language or rather use an existing one. I explained that my main motivation for re-writing alot of what already exists in OpenSCAD was

  1. I was finding it fun
  2. I can understand things much easier if its my own work.
  3. Its easier to do research in a new project, than try and modify some existing codebase.

l like to think of RapCAD as my own research experiment, into an ‘Openscad 2.0’ language spec, and other potential re-factorings that might someday be applied. Marius added that in many ways that was what Clifford had done, when he took MetaCAD, and re-wrote it in C over a summer holiday.

Another thing we talked about is the possibility that some day OpenSCAD might drop CGAL as its back end rendering subsystem, and perhaps adopt something like OpenCASCADE. It makes sense to try and integrate RapCAD’s scripting engine with the OpenSCAD rendering engine in much the same way as efforts like pySCAD have done.

One idea that Marius presented to me was that of a low level API that projects like pySCAD and RapCAD could use. The API might be text based vastly simplified to a description/modeling language that only supports the basic primitives such as polyhedrons, which all other shapes can be defined in terms of, as well as csg operation nodes, and transformations which can all be defined in terms of multmatrix.

In summary I am focusing my efforts on connecting up my existing code to just the rendering functions of OpenSCAD, and modifying OpenSCAD so that it has a generic API for projects like pySCAD, SolidPython and CloudSCAD can use as well.

Not Just a GUI Thing

I haven’t done a lot with RapCAD recently, and its time for my monthly post. What I thought I would write about is my reaction to posts on the OpenSCAD mailing list regarding turning it into a Python language library. First and foremost I think the idea is a great way to provide extensibility.

As Tony Buser says:

Access to such features would be potentially very powerful to do unforeseen things… then there’s string processing – that could be very handy with parametric scripts (look at what I had to do to handle strings in my bitmap text module) Filesystem access would be really nice for loading external data. Interesting things could be done in terms of dynamic objects if the script could call webservices…

For the power user these sorts of things are great. However I wonder if the desire to have Python support is driven by the lack of some features in OpenSCAD, such as:

  • True variables.
  • Functions with bodies.
  • Working scope blocks.
  • Statements allowed inside For and If
  • Determine how many elements are in an array or characters in a string.
  • Get the nth character of a string, and get it’s ASCII code.
  • Vector operations.

(Credit to Leemon Baird who suggested some of these)

My reaction is that we can have both a domain specific language, which is nice for the end user, and a set of language bindings to allow the power user to do advanced things, with their general purpose language of choice. I am currently trying to work out how this could be done in RapCAD, and making the RapCAD scripting language itself just one of the bindings.

With respect to the RapCAD scripting language itself, I also want to add support for the features as described above. RapCAD is not just a GUI thing. I have actually been writing an improved grammar, which I turned into a bison parser. I have also applied some Design Patterns such as Builder and Visitor to my code which may allow easier integration with external languages. Finally as mentioned before I have implemented True Variables, Functions with bodies, and some support for Vector operations.

On the face of it RapCAD just looks like a GUI front end to OpenSCAD, but that’s not actually what it is please feel free to look at the code and post any comments.

Syntax Highlighting

I have implemented syntax highlighting in RapCAD using the same lexical analysis engine as the script parser and evaluator uses.

I wanted to do this for two reasons, firstly flex is comparatively faster than the example QT SyntaxHighlighter implementation which uses QRegExp’s. This is partly because the lexer is built at compile time, where as QRegExp’s are compiled at runtime. The second reason for using flex as the backend to the highlighter was to ensure that there are no ambiguities between the syntax highlighter and the language definition.

I have also started to look at how to make the scripts output 3D shapes using CGAL. Its certainly not a trivial task, but I am starting to understand things.

Basic Evaluation

RapCAD has now got to the point where scripts can be evaluated at a text level. What I mean by this is that modules functions statements and expressions can be evaluated and the results of those evaluations can be output to stdout using the echo module. There is no 3D output yet, so most of this is pretty trivial, but it has been fun for me to learn how to write code in C++. I still need to improve usage of ‘const correctness’ and consider using references instead of pointers, but on the whole I am happy with what I have managed so far. It might be of interest to mention at this stage that I have implemented “Variables that will” and Functions with function bodies are coming along. is implemented.

In the meantime as I have discovered how to do things by implementing them in RapCAD, I have been able to supply similar fixes to OpenSCAD, the most notable being support for nested includes.