Dedicated to Open Source Software and Open Hardware
Author: Jeremy Wright
Published: 2023-03-20
Last Updated: Never
License: CC BY-SA 4.0
Previous Post: Ideas on Open Hardware Revenue Sharing
The Open Toolchain Foundation recently held a hackathon in Hamburg, Germany which centered around their goal of promoting open engineering practices and tools, such as FreeCAD. I was fortunate to be able to attend, along with 32 other people with diverse specialties. The goal of the hackathon was to convert the Nimble project by Wakoma to an open toolchain, with as much cross-compatibility between tools as possible. There was also room for other projects and processes that could tie into the Nimble project in some form. A list of all the teams and what they worked on can be found here.
Forms were distributed and participants were asked to come up with topics to work on, along with objectives for their topic. Then the sheets were displayed so that similar topics could be combined, and participants could choose which group(s) they wanted to be a part of.
Our group formed dynamically around our topic, with a couple of members dropping in and out as needed.
Our team decided to try to create a framework that would allow us to generate customizable CAD models for the Nimble project and have the documentation update automatically to match. There was an extra goal that was merged into our team of creating a parametric enclosure made of steel that could be welded, with a stretch goal of allowing other materials such as wood.
There is one definition that will be helpful for you to understand before we proceed. When the term parametric is used in the rest of this post, it means that a CAD model has been created in such a way that it can be customized by a user. For example, the Nimble rack leg can vary in length with a different number of holes in it. That leg can be created in such a way that the user can set any length they need for the leg and still get a valid 3D model.
One other thing to note is that you will see the term "tray" referenced throughout the codebase instead of "shelf". After the hackathon it was learned that the term used by Wakoma is "shelf", so that term is preferred throughout this blog post.
Our team's goal was essentially to create parametric documentation that would always be in sync with our parametric models and assemblies. There were 2 classes of tools that were foundational to our approach.
The overall idea was to write a high level generator script that would orchestrate CadQuery model and assembly generation, as well as insert dynamic content into the documentation source files. This required a string template system to be used so the content of the GitBuilding source could be modified by the generator script to fit the state of the parametric assembly. We wanted users to be able to select the networking and power components that they had access to, rather than giving them abstract parameters, and generate the models and assembly from that. It is easier to say "I have this network switch with these dimensions" than to try to figure out what shelf size or leg spacing that would translate to. This required us to create a simple database of the components the user could select from, as well as a configuration file to tell the framework which components were being used. Below is a diagram showing generally how the framework was structured.
In this section I will walk through what the generate.py script does with the CAD models, and so this section might get a bit more technical.
The script starts out by creating a directory where it can put all of the generated CAD and documentation files. This keeps the user's project directory from becoming cluttered.
The script then reads in all of the components the user can select from a JSON file, which served as our lightweight component database. In a final solution there would be a large database of components that can be used to construct a Nimble rack, along with each component's physical dimensions, power consumption, etc. Once all the available components were loaded, a separate config file was used to select just the components that were required to build a specific rack. In our version of the framework each component required the same shelf height, but other shelf heights could be used simply by changing the JSON database file.
Once the components have been selected, the CAD model code is called with the appropriate parameters. The total height of the rack is determined by the number of components, and the heights of each shelf required. That total height is then used to generate the 4 rack legs which have the shelf mounting holes in them. The top and bottom caps of the rack are also generated. The rack can vary in width, requiring the width of the caps to vary, but to simplify things for demonstration purposes we assumed that each component would require the same shelf width. In a real-world version of this framework the width of the rack (and the shelves) would change to fit the widest component selected.
After the main parts of the rack are ready, the shelves are generated by stepping through each compute, networking or power component and generating a shelf that fits it properly. In our demo setup there was only one type of shelf with an open front. However, in a real-world configuration, many types of shelves would be available, possibly even with filler shelves to take up space for something like cable routing.
Ignoring the fact that screws and other fasteners could also be generated and consumed by this framework, all assembly parts are now available. An assembly object is created, and all the parts (end caps, legs, shelves) are added to that. Assembly constraints would normally be used to position the parts, but in the interest of time our parts were positioned dynamically based on the overall dimensions of the rack and which components were being added. The assembly is built in steps, and an SVG image is captured of each step, including when the assembly is complete. STL and STEP files are also exported for each component of the assembly at this time so they can be made available to the user. The series of images below show the SVG images that were captured of each step so they could be added to the documentation.
In this section I will walk through how the dynamic documentation was generated in reaction to the parametric CAD assembly. This section will be more technical, similar to the last section on CAD. It is possible to follow along in the live documentation that was created during the hackathon, which can be found here.
The generate script first creates a download page for all the 3D printable parts. Each 3D printable part generated by CadQuery has an entry with links, and the script also generates a zip file of all the parts together and adds a link for that. The list of shelves that was generated from the selected components is also looped over and added to this list so the download page always has the correct parts in it for a given Nimble configuration. GitBuilding supports STL preview, and so clicking on a link for the STL file opens an interactive 3D preview window.
GitBuilding utilizes yaml files to define things like parts and tools, which are then consumed while writing the narrative part of the documentation. The generator script works next on generating these files dynamically. A yaml file is created for the 3D printable parts, specifying things like filename and filament type. Next, a yaml file is created which holds the components the will be installed into the Nimble rack when it is completed. Remember that the components (i.e. switch, router, battery pack) are what drive the rest of the design. The parametric part of the design is tied to the real-world objects that the user is working with.
After the yaml files are ready, frame and component assembly pages are generated. These pages include a bill of materials, which holds all the assembly parts that were generated, and assembly steps that adjust to the number of shelves that need to be installed. The SVG files that were exported during the CAD process are referenced in this document, to help illustrate the assembly steps.
Throughout the documentation generation process, Python string templates are used so that text can be inserted dynamically and written to a file. The generator script manipulates the GitBuilding files to make them dynamic, and then calls GitBuilding to generate the final, static documentation that can then be deployed to a web server. In our group, Daniel created a Continuous Integration (CI) pipeline that ran the generator script and GitBuilding, and then deployed the result to a GitHub page. That result can be viewed here.
I have skipped a lot of detail to keep this blog post readable, but anyone who is interested can look at the generate.py script for themselves. All work done at the hackathon was open source, of course.
Some of the next steps are already being taken, but there is a lot more that could be done.
This framework has already generated quite a bit of interest, and it seems likely that it will be refined in the future. If you would like to join the discussion surrounding this framework, the hackathon, or the open hardware toolchain in general, please consider joining the Open Toolchain Foundation forum.
© 2018-2024 7B Industries