ChronoSolidWorks:Demo engine advanced

From ChronoWiki

(Redirected from Demo engine advanced)
Jump to: navigation, search

Example. Customize the simulation of a 4 cyilinder engine

This tutorial assumes that you already learned the introductory tutorial on the Chrono::SolidWorks add-in, that is the demo_engine tutorial.

You will learn how to modify the program that was automatically generated by the exporter tool of SolidWorks, in order to customize the simulation and add advanced functionalities.

The files for this demo can be found in the directory C:\Program Files\SolidWorks Corp\SolidWorks\chronoengine\examples\engine. The directory contains all the parts needed for this assembly.

Please read the demo_engine tutorial before proceeding with this.

So, assume you already created with the SolidWorks exporter for creating Chrono::Engine python files.

Now, the idea is that you can write a more sophisticated Python program to make more advanced simulations; for example you can add springs, dampers, motors, particles, etc.

  • To spend few time, just copy the and rename it as We will work on this file as atemplate.
  • Now, open in your Python IDE (for example, PyScripter). Read ChronoPyEngine:Introduction this if you are new to Python programming for Chrono::Engine.

You can do various modifications to the Python program; here are some ideas.


Import the scene

The unmodified program can be run as -f

but if you remove the argument parsing section and add the import statements above, you can run it from the IDE without the need of specifying the -f parameter.

Example: suppose you exported your engine mechanism as In order to import that Chrono::Engine mechanism in your Python code, write:

from engine4c import exported_items

Note that you write from engine4c, not from

If you run multiple times the program without reinitialization of the Python engine, you might need to force the reload of the module, writing this more advanced code:

import engine4c
from engine4c import exported_items

Note how all exported items are added to a ChSystem:

my_system = chrono.ChSystem()
for my_item in exported_items:

This tutorial is meant for Python, but all the tricks that are described here can be implemented also in C++. The main difference is that, in C++, you cannot load the exported .py file directly: you need to link the unit_PYPARSER library and use the following C++ code to do the job that is done in the six lines of Python above:

ChSystem my_system;
ChPythonEngine my_python;
my_python.ImportSolidWorksSystem("engine4c", my_system);

Add additional coordinate frames

If you want to add additional bodies/constraints/springs etc. via programming, it can be helpful if you can use xyz coordinate frames as references. You can add these coordinate systems using SolidWorks, then export them as .py files, and later fetch their position and rotation. For example, here we see how to use a coordinate system to define the Z axis of a ChLinkEngine motor that we will add between the crank and the ground, later.

  • First of all, add a SolidWorks feature of CoordinateSystem type, using the menu Insert/reference geometry/Coordinate system.
  • Select the beginning of the sketched axis in the assembly, as origin, and select the direction of that axis as Z direction of the coordinate system feature. You should get something like this:


  • If all is working correctly, the coordinate system will be added into the assembly (do not add it into subassemblies or parts, we do not need so in this example).
  • Change its name into something mnemonic, in our example we changed it to Marker_shaft.


  • Save the assembly, and export it again to Chrono::Engine as
  • Now in your you can fetch that coordinate system as a ChMarker object! Just use the SearchMarker statement:

my_marker = my_system.SearchMarker('Marker_shaft')
if my_marker.IsNull() :
    sys.exit('Error: cannot find marker from its name in the C::E system!')

Once you got the marker as a Python object, for example, you could get its absolute position with my_marker.GetAbsCoord().pos.x , etc. For instance, in the next paragraph we will use it to create a constraint in a specific position.

If you have a doubt about the name of an exported object, just open the exported .py file ( in our case) and look where you read lines like this: ....SetName("blabla");

Add more constraints (an engine)

The, as exported by SolidWorks, does not contain any constraint that enforces the rotation of the crankshaft; the only constraints that are exported are the 'mating' constraints such as the revolute joints between the crank and the rods, etc. etc.

Here is an example of how to create an additional constraint, namely, a rotational engine between the crankshaft and the ground. Once you learned this, you will be able to extend this concept to other types of constraints.

  • Fetch the ground body and the crankshaft as Python objects. You can do this thank to the fact that they have unique mnemonic names: ground (default name for the assembly root), and Crankshaft-1 (the name of the crankshaft part). Hence, do:

my_item = my_system.Search('Crankshaft-1')
my_shaft  = chrono.CastToChBodyAuxRefShared(my_item)
if my_shaft.IsNull() :
    sys.exit('Error: cannot find shaft  from its name in the C::E system!')

my_item = my_system.Search('ground')
my_ground = chrono.CastToChBodyAuxRefShared(my_item)
if my_ground.IsNull() :
    sys.exit('Error: cannot find ground from its name in the C::E system!')

Note: differently from the previous case of SearchMarker, here you need also the statements CastToChBodyAuxRefShared, that are used to do a dynamic (down)casting of the types, because the Search function returns just a base type of generic ChPhysicsItem type, and it is up to you to do the casting. (There are many CastToXXYYZZShared functions for Python dynamic casting to various XXYYZZ classes)

  • Finally, add this bit of code to create a constraint of ChLinkEngine type, that is a link that constraints the rotation of two parts; the two parts are the two rigid bodies that you just fetched, my_shaft and my_ground:

revolute_csys = my_marker.GetAbsCoord()
link_motor = chrono.ChLinkEngineShared()
link_motor.Initialize(my_shaft, my_ground, revolute_csys)
link_motor.Get_spe_funct().Set_yconst(2.5*chrono.CH_C_2PI)  # 0.5 Hz to rad/s

The Initialize() function requires two bodies and a ChCoordsysD object that represents the position and rotation of the constraint; in this case the ChLinkEngine constraint assumes that the Z axis of the coordsys is used for the rotation axis.

Although you could create a ChCoordsysD from scratch, by typing the rotation and xyz position values, here it was smarter to use the coordsys of the my_marker object that was created in SolidWorks and fetched in the previous paragraph.

The Set_shaft_mode() is a custom function of ChLinkEngine objects: it can be used to choose which type of connection is used between the two parts. The Set_eng_mode() can switch between ENG_MODE_SPEED, ENG_MODE_ROTATION, ENG_MODE_TORQUE etc., for different types of imposed variables. In our case, we want to set a constant angular velocity, and then we also need Get_spe_funct() for accessing the default ChFunctionConst and change its value; you could also change the type of motion law by using Set_spe_funct(a_new_function).

Change camera viewpoint

If you want to change the viewpoint of the camera for the POVray postprocessing system, look in for the following statement and modify the x y z coordinates of the viewpoint to your needs. The parameters of SetCamera() are the vector with the position of the observer viewpoint, the vector with the position of the aim point, and finally the degrees of the lens angle (ex. 30° for tele lenses, 50° for a wide lenses, etc.):

pov_exporter.SetCamera(chrono.ChVectorD(0.4,0.6,0.9), chrono.ChVectorD(0.2,0,0), 30)

Change material of shape visualization

Maybe that your 3D rendering looks too dull because all surfaces, by default, look like white chalk. However you can pich one object and change its appearance by tweaking the POVray materials. The idea is that you can add additional objects of ChAsset type into each moving part; one of these ChAsset objects could belong to the ChPovRayAssetCustom class, that allows you to add optional POVray statement to the rendering scripts that are generated for a specific shape. Look how this is achieved by using this bit of code:

shaft_povmat = postprocess.ChPovRayAssetCustomShared()
       pigment { color rgbt <0.5,0.5,0.52,0> }
       finish  {    reflection {0.35}
                    ambient 0
                    diffuse 1
                    phong 0.9
                    phong_size 60
                    metallic } ''')

In this case we created a fragment of POVray statements, namely a definition of a pigment and a glossy metallic finish, and we assigned it to the my_shaft object (that we already fetched, using the method described in the previous paragraphs).

Now run again it will create again the .pov and .ini scripts,so you can load again the .ini file into POVray and render the animation; you should be able to see that the crankshaft looks metallic:


Note that we also generated a horizontal plane and a grid: this can be done by adding additional POVray statements that act on a global scale; here is the piece of code:

    light_source{ <1,3,1.5> color rgb<1.1,1.1,1.1> }
    object{ Grid(0.1,0.04, rgb<0.5,0.5,0.5>, rgbt<1,1,1,1>) translate -0.3*y }
    plane{<0,1,0>, 0 pigment{color rgb<0.8,0.8,0.8>} translate -0.301*y }

Setting all objects as transparent

Suppose you want to set the material of all objects in the scene: this can be done by iterating on all objects as in this piece of code, where we want to set all parts as 80% transparent:

transp_povmat = postprocess.ChPovRayAssetCustomShared()
        pigment { color rgbt <1,1,1,0.8> }

for aitem in chrono.IterOtherPhysicsItems(my_system):

Show constraint coordinates

In the previous paragraph we set all objects as transparent; this can be useful in case you want to render the position of the reference coordsystems of the constraints -this can be seen as a 'visual debugging' of the simulation...

The code that you need to enable rendering coordinate systems of constraints in POVray postprocessing is this:

pov_exporter.SetShowLinks(1, 0.03)


Show Centers of Mass

Suppose you want to visualize the Center Of Gravity (COGs, also known as centers of mass) of each ChBodyAuxRef body: this is the code that you need:

pov_exporter.SetShowCOGs(1, 0.05)


The center of mass is computed automatically by SolidWorks when you export the mechanism to the Chrono::Engine .py file, and depends on the density of the materials that you assigned to the parts in SolidWorks interface.

Show coordinate frames

Suppose you want to visualize the reference coordinate sytems of each ChBodyAuxRef body: this is the code that you need:

pov_exporter.SetShowFrames(1, 0.05)


Note that the bodies that are exported from the SolidWorks Add-in are not of the simple ChBody class, but rather they belong to the advanced ChBodyAuxRef class. In fact, while ChBody objects assume that their center of mass is coincident with the reference coordsystem of the body, whereas in ChBodyAuxRef bodies the body's reference coordsystem usually is distinct from the center of mass.

Important: the reference coordinates of the moving bodies are displayed as origins in the SolidWork interface (where x y z planes intersect). Each part in SolidWorks has an origin. If multiple parts are merged in a SolidWorks subassembly that is solved as rigid (see previous tutorial), then the reference coordinate of the moving body is the origin of the subassembly.

Attach a camera to a moving object

Suppose you want to make an animation where a camera is moving together with a simulated part, for example you might want to show the point ov view of a driver that sits on a vehicle. This can be accomplished with the following piece of code:

  • First, fetch an object by looking ats its name; for example here we choose one of the four rods because we want to render an animation where the point of view is moving together with a rod:

my_item = my_system.Search('piston_rod-2/ConRod-1')
my_rod  = chrono.CastToChBodyAuxRefShared(my_item)
if my_rod.IsNull() :
    sys.exit('Error: cannot find conrod from its name in the C::E system!')
  • Now, create a ChCamera asset, set its position and aimpoint in the coordinate system of the conrod and add it to other assets of the conrod:

my_movingcamera = chrono.ChCameraShared()

When you render the animation you should see something like this:


Personal tools