Virtual prototype of the orb 6 DOF encoder

Energy storage is one of the biggest challenges that must be overcome to enable renewable energy utilization in transportation. The goal of the orb project is to develop open-source technologies for spherical energy storage flywheel systems. The orb project is hosted and GitHub.

orbConceptualDwg

A 6 DOF encoder is needed to make this thing work. The idea so far is to use a series of lasers positioned around the rotor to sense the position. Depending on what a given laser beam hits, either the intensity of the reflected light is measured, or triangulation is used to measure the distance. The encoder has to work with any orientation of the rotor. How many laser are needed? Where do they have to be? How will the algorithms that interpret the signals work? I don’t know yet, but I’m getting geared up to make some virtual prototypes now.

I made a sensor system model which is powered by the pythonOCC library. The model is implemented as a few Python classes. With this model I can draw up an arbitrary rotor geometry in almost any cad system, specify the orientation of any number of laser emitters, specify a rotor orientation, and read the distance from each laser emitter to the first surface that it hits. I can even associate reflectivity properties to individual surfaces so that reflected light can be measured. The model is simple. I represent the laser beams with edges, check for intersection between faces and edges, and check for the intersection nearest the laser emitter.

The model is very simplistic and that’s good for now. I really need a simple model to get a grasp of how the sensor algorithms will work. As development progresses closer to hardware, I will add capability so that lenses and photo detectors can be modeled. I’ve played around with pyoptools a little bit and it looks like it will work very nicely within this ecosystem.

pyoptoolsRaytracing

When I’m doing development of an application involving pythonOCC I usually have FreeCAD running, and my web browser pointed to the doxygen documentation for the Open Cascade Community Edition library. Here’s a handy little trick:

Part.__fromPythonOCC__()

Part.__toPythonOCC__()

You can call this in FreeCAD’s python console can convert things back and forth from pythonOCC to FreeCAD. I made some utility functions to speed common tasks related to selection and display based on that trick. It makes a nice bridge between programmatic CAD and GUI CAD on little projects.  Sometimes it is faster to output BREP or STEP files from stand alone pythonOCC applications or to use the native GUI of PythonOCC. It all depends on what you’re doing.  This sensor model application runs headless with no GUI.  I did add some functions in my System class that output a representation of the system in a BREP file.  Just as easily, I could have chosen STEP.

The default doxygen documentation build of open cascade community edition was a little confusing to me. It’s layout seemed to revolve around modules which map to library files.  At the end of the day, Open Cascade just is a bunch of C++ classes and pythonOCC wraps them, so I built the doxygen documentation myself, with a very basic doxygen configuration file.  I work from the class list page.  I don’t know, maybe if I’d have given the standard doc a chance I would have got it, but this works great.

Function arguments are for the most part, one-to-one from C++ to python, but occasionally you will see something where the wrapper does something in a more Pythonic way. For example, some functions that are return by reference in C++ will end up returning a tuple in their Python wrapped form.

The C++ documentation is great, but you also need to check out pythonocc-utils. If you only use the C++ documentation, you will miss out on some higher level, more Pythonic utilities that pythonocc-utils has to offer.

I had to try a few different methods to make the distance detection work for the sensor model.  I knew I needed something that would find the intersections between a TopoDS_Edge and a TopoDS_Face so I made a couple of test cases and I tried these classes which I found and read about in the OCE doxygen documentation and one function from pythonocc-utils:

BrepExtrema_ExtCF → an Open Cascade class

minimum_distance → function from pythonocc-utils

BrepExtrema_DistanceSS → an Open Cascade class.

GeomAPI_IntCS → an Open Cascade class.  Doesn’t take into account that faces are only parts of surfaces.

BrepIntCurveSurface_Inter → an Open Cascade class.  It’s working like a champion!

Haha!  What do you know?  It’s working!

testCases

Well, that’s all I have for now. Time for me to do some more virtual prototyping!  Sensing algorithms here we come!