Load a STEP file (demo_CAS_stepfile.cpp)

Tutorial that teaches how to use the CASCADE module to load CAD models from STEP files.

// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
// =============================================================================
// Show how to use the OpenCASCADE features
// implemented in the unit_CASCADE:
// - load a 3D model saved in STEP format from a CAD
// - select some sub assemblies from the STEP model
// - make Chrono::Engine objects out of those parts
// =============================================================================
#include "chrono/core/ChRealtimeStep.h"
#include "chrono/physics/ChSystemNSC.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono_cascade/ChCascadeBodyEasy.h"
#include "chrono_cascade/ChCascadeDoc.h"
#include "chrono_cascade/ChVisualShapeCascade.h"
#include "chrono_irrlicht/ChVisualSystemIrrlicht.h"
using namespace chrono::irrlicht;
#include "chrono_vsg/ChVisualSystemVSG.h"
using namespace chrono::vsg3d;
using namespace chrono;
using namespace chrono::cascade;
int main(int argc, char* argv[]) {
// Create a ChronoENGINE physical system: all bodies and constraints
// will be handled by this ChSystemNSC object.
// Load a STEP file, containing a mechanism. The demo STEP file has been
// created using a 3D CAD (in this case, SolidEdge v.18).
// Create the ChCascadeDoc, a container that loads the STEP model
// and manages its subassembles
ChCascadeDoc mydoc;
// load the STEP model using this command:
bool load_ok = mydoc.Load_STEP(GetChronoDataFile("cascade/assembly.stp").c_str());
// or specify abs.path: ("C:\\data\\cascade\\assembly.stp");
// print the contained shapes
// In most CADs the Y axis is horizontal, but we want it vertical.
// So define a root transformation for rotating all the imported objects.
ChQuaternion<> rotation1;
rotation1.Q_from_AngAxis(-CH_C_PI / 2, ChVector<>(1, 0, 0)); // 1: rotate 90� on X axis
ChQuaternion<> rotation2;
rotation2.Q_from_AngAxis(CH_C_PI, ChVector<>(0, 1, 0)); // 2: rotate 180� on vertical Y axis
ChQuaternion<> tot_rotation = rotation2 % rotation1; // rotate on 1 then on 2, using quaternion product
ChFrameMoving<> root_frame(ChVector<>(0, 0, 0), tot_rotation);
// Retrieve some sub shapes from the loaded model, using
// the GetNamedShape() function, that can use path/subpath/subsubpath/part
// syntax and * or ? wildcards, etc.
std::shared_ptr<ChCascadeBodyEasy> body1;
std::shared_ptr<ChCascadeBodyEasy> body2;
if (load_ok) {
TopoDS_Shape shape1;
if (mydoc.GetNamedShape(shape1, "Assem1/body1")) {
// Create the ChBody using the ChCascadeBodyEasy helper:
body1 = chrono_types::make_shared<ChCascadeBodyEasy>(shape1,
1000, // density
true, // add a visualization
false // add a collision model
// Move the body as for global displacement/rotation (also mbody1 %= root_frame; )
} else
GetLog() << "Warning. Desired object not found in document \n";
TopoDS_Shape shape2;
if (mydoc.GetNamedShape(shape2, "Assem1/body2")) {
// Create the ChBody using the ChCascadeBodyEasy helper (with more detailed visualization tesselation):
auto vis_params = chrono_types::make_shared<ChCascadeTriangulate>( //
0.02, // chordal deflection for triangulation
false, // chordal deflection is relative
0.5 // angular deflection for triangulation
body2 = chrono_types::make_shared<ChCascadeBodyEasy>(shape2,
1000, // density
vis_params, // add a visualization
false // no collision model
// Move the body as for global displacement/rotation (also mbody2 %= root_frame; )
} else
GetLog() << "Warning. Desired object not found in document \n";
} else
GetLog() << "Warning. Desired STEP file could not be opened/parsed \n";
// Create a revolute joint between the two parts
// as in a pendulum. We assume we already know in advance
// the aboslute position of the joint (ex. we used measuring tools in the 3D CAD)
ChVector<> measured_joint_pos_mm(0, 48, 120);
double scale = 1. / 1000.; // because we use meters instead of mm
ChVector<> joint_pos =
((ChFrame<>)root_frame) * (measured_joint_pos_mm * scale); // transform because we rotated everything
if (body1 && body2) {
std::shared_ptr<ChLinkLockRevolute> my_link(new ChLinkLockRevolute);
my_link->Initialize(body1, body2, ChCoordsys<>(joint_pos));
// Create a large cube as a floor.
std::shared_ptr<ChBodyEasyBox> floor(new ChBodyEasyBox(1, 0.2, 1, 1000));
floor->SetPos(ChVector<>(0, -0.3, 0));
floor->GetVisualShape(0)->SetColor(ChColor(0.3f, 0.3f, 0.8f));
// Create the run-time visualization system
std::shared_ptr<ChVisualSystem> vis;
switch (vis_type) {
auto vis_irr = chrono_types::make_shared<ChVisualSystemIrrlicht>();
vis_irr->SetWindowSize(800, 600);
vis_irr->SetWindowTitle("Load a STEP model from file");
vis_irr->AddCamera(ChVector<>(0.2, 0.2, -0.3));
vis = vis_irr;
auto vis_vsg = chrono_types::make_shared<ChVisualSystemVSG>();
vis_vsg->SetWindowSize(800, 600);
vis_vsg->SetWindowTitle("Load a STEP model from file");
vis_vsg->AddCamera(ChVector<>(0.2, 0.2, -0.3));
vis = vis_vsg;
// Simulation loop
ChRealtimeStepTimer realtime_timer;
double time_step = 0.01;
while (vis->Run()) {
return 0;
std::string GetChronoDataFile(const std::string &filename)
Obtain the complete path to the specified filename, given relative to the Chrono data directory (thre...
Definition: ChGlobal.cpp:95
void Add(std::shared_ptr< ChPhysicsItem > item)
Attach an arbitrary ChPhysicsItem (e.g.
Definition: ChSystem.cpp:210
Create rigid bodies with a box shape.
Definition: ChBodyEasy.h:153
Definition: ChCoordsys.h:38
Supported run-time visualization systems.
Definition: ChVisualSystem.h:36
ChLog & GetLog()
Global function to get the current ChLog object.
Definition: ChLog.cpp:39
virtual void AddLink(std::shared_ptr< ChLinkBase > link)
Attach a link to the underlying assembly.
Definition: ChSystem.cpp:158
Representation of a 3D transform.
Definition: ChFrame.h:34
Namespace with classes for the Irrlicht module.
Definition: ChApiIrr.h:47
Class for a timer which attempts to enforce soft real-time.
Definition: ChRealtimeStep.h:25
void Spin(double step)
Call this function INSIDE the simulation loop, just ONCE per loop (preferably as the last call in the...
Definition: ChRealtimeStep.h:34
Definition of a visual color.
Definition: ChColor.h:30
Definition of general purpose 3d vector variables, such as points in 3D.
Definition: ChVector.h:35
static void SetDefaultSuggestedMargin(double margin)
Set the default margin (inward penetration).
Definition: ChCollisionModel.cpp:85
int DoStepDynamics(double step_size)
Advances the dynamical simulation for a single step, of length step_size.
Definition: ChSystem.cpp:1601
ChFrameMoving: a class for coordinate systems in 3D space.
Definition: ChFrameMoving.h:38
Class defining quaternion objects, that is four-dimensional numbers, also known as Euler parameters.
Definition: ChQuaternion.h:45
Namespace with classes for the CASCADE module.
Definition: ChApiCASCADE.h:52
Main namespace for the Chrono package.
Definition: ChCamera.cpp:17
void Q_from_AngAxis(Real angle, const ChVector< Real > &axis)
Set the quaternion from an angle of rotation and an axis, defined in absolute coords.
Definition: ChQuaternion.h:1146
Class for a physical system in which contact is modeled using a non-smooth (complementarity-based) me...
Definition: ChSystemNSC.h:29
static void SetDefaultSuggestedEnvelope(double envelope)
Set the default envelope value.
Definition: ChCollisionModel.cpp:81
Namespace with classes for the VSG module.
Definition: ChApiVSG.h:51