This demos is obsolete and should undergo deep interventions to be updated to latest Chrono version.
Tutorial that teaches how to use the CASCADE module to load a 6-DOF robot saved in a STEP file as an assembly, exported from a CAD model.
This is an advanced tutorial that shows how to load complex 3D models that have been saved in STEP file format from professional 3D CAD software.
Most high-end 3D CAD software can save assemblies and parts in STEP format. Among the most used CAD software, we cite CATIA, SolidEdge, SolidWorks, PTC Pro/E, etc. The following tutorial is based on SolidEdge, but it can be adapted to other CADs with minor modifications.
Prepare a STEP file
The CASCADE module is able to directly parse sub-assemblies and sub-parts that have been saved into a single STEP file. However, it is better to prepare the assembly with certain guidelines, before saving it: noticeably, we will put some 'auxiliary' objects in the assembly (the markers) that we will use from the C++ programming side in order to retrieve useful coordinates for building the constraints between the parts. This process is explained in the folowing example.
Creating a demo mechanism (a car, a robot, etc.) might take hours. To make things simplier, we load a ready-to-use model that can be downloaded from the website of a manufaturer of industrial robots, see
download page from the
ABB website. We downloaded the 3D model for the IRB 7600 robot: by the way it is already in STEP format, so it could be loaded directly by the CASCADE unit, but we prefer to mofify it in SolidEdge and save it again.
- Start SolidEdge (we use the v18 version in this example)
- Menu File / Open...
- Choose the STEP (.stp or .step) file of the robot, as downloaded from the ABB site.
- In the 'New' window, in the 'General' tab, select 'Normal.asm' to let SolidEdge create an assembly from the STEP file
Press OK. After the conversion, SolidEdge created the assembly. Look into the directory of your STEP file: SolidEdge created its .asm and many .part files. The Assembly PathFinder panel, to the right, shows all the parts in the assembly:

- Note that the assembly is made of many parts. Maybe that there is not a one-to-one correspondence from rigid bodies for our simulation, and CAD parts, so we want to organize N sub-assemblies, that represent our N rigid bodies in the simulation. That is, it would be nice if each part stays in a separate sub-assebly that represents a 'rigid body', and such subassemblies can optionally contain some auxiliary objects (we call them 'markers') that can be used later on the C++ side to find the position of the joints.
- To make the sub assembles:
- Select the 'Parts library' panel,
- press button 'Create in Place' to open the create window,
- set 'Normal.asm' as Template
- set 'Base' (or 'Forearm', or other meaningful name) in 'New file name',
- browse to your directory where you have all other assembly files, in 'New file location',
- menu File / Close and return, to go back to general assembly.
- Repeat the last steps to create the other subassemblies, named for example 'Bicep', 'Forearm', 'Wrist', etc.
- The created subassemblies are still empty. So we must move the imported parts into them. Drag and drop a part from parent assembly to a child asembly does not work in SolidEdge v.18, yet a simple way to do this is to
- select the part in the parent assembly,
- press Ctrl+C to copy,
- then select the sublevel in the Assembly PathFinder,
- use 'Edit' from popup-menu,
- press Ctrl-V to paste it,
- then go back to parent assembly with menu 'File / Close and return'.
Repeat this until you have all the parts in their separate subassemblies. Some subassembly might have multiple parts. Look our example:

Now we add an auxiliary part in all subassemblies, to represent the coordinates where you want the constraints (links, motors, ..) to be created using C++ functions. These are like 'placeholders'. To do so, we create a 'marker.par' part, such as the one in the following figure:
marker.par
We insert this marker part in all subassemblies, properly aligned to all the joints:

At the end, the Assembly PathFinder panel should show something like the following:

- Select the base assembly, use the menu File / Save as.. and choose STEP as file format, then save the entire assembly.
- Quit the SolidEdge software.
Write C++ code to load the model
The key of the remaining process is the functionality of the ChCascadeDoc class. Such class has the functionality of loading sub-assemblies from a STEP file by using the function mydoc.GetNamedShape(...)
that takes, as argument, the ASCII name of the subassembly (or sub part).
A small inconvenience happens here: because of a SolidEdge-specific issue, the names of the subassemblies in the STEP file are not always the same names that you read in the Assembly PAthFinder window. In detail, all the names of the assemblies are automatically translated to Assem1
, Assem2
, etc., whereas you would expect the names of the assemblies that you created, such as Base
, Turret
, etc.
A workaround to this inconvenience is the following: you use the mydoc.Dump(std::cout)
function to print the hierarchy on the console and take note of the STEP names on a piece of paper (or just use the demo_converter.exe to show that hierarchy), you will see something like:
-Name :Assem10 (root)
pos at: 0 0 0 (absolute)
pos at: 0 0 0 (.Location)
-Name :Assem8
pos at: 0 0 0 (absolute)
pos at: 0 0 0 (.Location)
-Name :IRB7600_23_500_m2000_rev1_01-1
pos at: 0 0 0 (absolute)
pos at: 0 0 0 (.Location)
-Name :marker
pos at: 2.29901e-035 -2.99071e-036 0.2185 (absol
pos at: 2.29901e-035 -2.99071e-036 0.2185 (.Loca
-Name :Assem4
pos at: 0 0 0 (absolute)
pos at: 0 0 0 (.Location)
-Name :IRB7600_23_500_m2000_rev1_01-2
pos at: 0 0 0 (absolute)
pos at: 0 0 0 (.Location)
-Name :marker
pos at: 3.88578e-015 -2.66454e-015 0.2135 (absol
pos at: 3.88578e-015 -2.66454e-015 0.2135 (.Loca
-Name :marker
pos at: 0.41 -0.049 0.78 (absolute)
pos at: 0.41 -0.049 0.78 (.Location)
-Name :marker
pos at: -0.38 -0.03 0.6545 (absolute)
pos at: -0.38 -0.03 0.6545 (.Location)
-Name :Assem1
.... etc. etc. .... ........
From the example above, you see that Base
has become Assem8
, Turret
has become Assem4
, and so on. (luckily enough, SolidEdge did not change the name of the parts, only the assembly names were changed). Take note of this on a sheet of paper.
Now, let's develop the C++ program that loads the robot model and simulates it.
First of all, include the needed libraries (note the unit_CASCADE/... headers) and use the proper namespaces:
#include "physics/CHapidll.h"
#include "core/CHrealtimeStep.h"
#include "irrlicht_interface/CHirrAppInterface.h"
#include "irrlicht_interface/CHbodySceneNodeTools.h"
#include "unit_CASCADE/CHcascadeDoc.h"
#include "unit_CASCADE/CHCascadeMeshTools.h"
#include "unit_CASCADE/CHirrCascadeMeshTools.h"
#include "unit_CASCADE/CHirrCascade.h"
#include "irrlicht_interface/CHbodySceneNode.h"
#include <irrlicht.h>
using namespace video;
using namespace io;
using namespace gui;
Namespace with classes for the CASCADE module.
Definition ChApiCASCADE.h:51
Main namespace for the Chrono package.
Definition ChCamera.cpp:17
Irrlicht base classes (Chrono extensions).
Definition ChIrrTools.cpp:23
Irrlicht base classes (Chrono extensions).
Definition ChCascadeIrrMeshTools.h:50
Main Irrlicht namespace (Chrono extensions).
Definition ChCascadeIrrMeshTools.h:47
Here is the program (a simple demo where the robot is created from the STEP file, constraints are added, and the robot simulation is displayed while moving on a simple trajectory).
int main(int argc, char* argv[])
{
ChGlobals* GLOBAL_Vars = DLL_CreateGlobals();
ChIrrAppInterface application(&my_system, L"Load a robot model from STEP file",core::dimension2d<u32>(800,600),false, true, video::EDT_OPENGL);
ChIrrWizard::add_typical_Sky(application.GetDevice());
ChIrrWizard::add_typical_Lights(application.GetDevice(), core::vector3df(30,100,30), core::vector3df(30,-80,-30),200,130);
ChIrrWizard::add_typical_Camera(application.GetDevice(), core::vector3df(0.2,1.6,-3.5));
Chrono Simulation System.
Definition ChSystem.h:64
Create the ChCascadeDoc, a container that loads the STEP model and manages its subassembles. Also, prepare some pointers for bodies that will be created.
Also, prepare some pointers for bodies that will be created.
ChBodySceneNodeAuxRef* mrigidBody_base = 0;
ChBodySceneNodeAuxRef* mrigidBody_turret = 0;
ChBodySceneNodeAuxRef* mrigidBody_bicep = 0;
ChBodySceneNodeAuxRef* mrigidBody_elbow = 0;
ChBodySceneNodeAuxRef* mrigidBody_forearm = 0;
ChBodySceneNodeAuxRef* mrigidBody_wrist = 0;
ChBodySceneNodeAuxRef* mrigidBody_hand = 0;
ChBodySceneNodeAuxRef* mrigidBody_cylinder = 0;
ChBodySceneNodeAuxRef* mrigidBody_rod = 0;
Load the STEP model using this command: (be sure to have the STEP file on the hard disk)
bool load_ok = mydoc.Load_STEP("..\\data\\cascade\\IRB7600_23_500_m2000_rev1_01_decorated.stp");
Print the contained shapes, showing the assembly hierarchy:
mydoc.Dump(std::cout);
rotation1.QuatFromAngleAxis(-CH_PI/2, VECT_X);
rotation2.QuatFromAngleAxis(CH_PI, VECT_Y);
static void SetDefaultSuggestedEnvelope(double envelope)
Set the default envelope value.
Definition ChCollisionModel.cpp:81
static void SetDefaultSuggestedMargin(double margin)
Set the default margin (inward penetration).
Definition ChCollisionModel.cpp:85
Representation of a moving 3D.
Definition ChFrameMoving.h:27
ChVector3< double > ChVector3d
Alias for double-precision vectors.
Definition ChVector3.h:283
ChQuaternion< double > ChQuaterniond
Alias for double-precision quaternions.
Definition ChQuaternion.h:412
Retrieve some sub shapes from the loaded model, using the GetNamedShape() function, that can use path/subpath/subsubpath/part syntax and * or ? wldcards, etc. Using the / slash is like addressing a Unix directory (in fact the STEP file is organized like a directory with subdirectory, each representing a subassembly).
if (load_ok)
{
TopoDS_Shape shape_base;
if (mydoc.GetNamedShape(shape_base, "Assem10/Assem8" ))
{
mrigidBody_base = (ChBodySceneNodeAuxRef*)addChBodySceneNode_Cascade_C(
&my_system, application.GetSceneManager(),
shape_base);
mrigidBody_base->GetBody()->SetFixed(true);
mrigidBody_base->GetBody()->ConcatenatePreTransformation(root_frame);
}
else std::cout << "Warning. Desired object not found in document \n";
TopoDS_Shape shape_turret;
if (mydoc.GetNamedShape(shape_turret, "Assem10/Assem4" ))
{
mrigidBody_turret = (ChBodySceneNodeAuxRef*)addChBodySceneNode_Cascade_C(
&my_system, application.GetSceneManager(),
shape_turret);
mrigidBody_turret->GetBody()->ConcatenatePreTransformation(root_frame);
}
else std::cout << "Warning. Desired object not found in document \n";
TopoDS_Shape shape_bicep;
if (mydoc.GetNamedShape(shape_bicep, "Assem10/Assem1" ))
{
mrigidBody_bicep = (ChBodySceneNodeAuxRef*)addChBodySceneNode_Cascade_C(
&my_system, application.GetSceneManager(),
shape_bicep);
mrigidBody_bicep->GetBody()->ConcatenatePreTransformation(root_frame);
}
else std::cout << "Warning. Desired object not found in document \n";
TopoDS_Shape shape_elbow;
if (mydoc.GetNamedShape(shape_elbow, "Assem10/Assem5" ))
{
mrigidBody_elbow = (ChBodySceneNodeAuxRef*)addChBodySceneNode_Cascade_C(
&my_system, application.GetSceneManager(),
shape_elbow);
mrigidBody_elbow->GetBody()->ConcatenatePreTransformation(root_frame);
}
else std::cout << "Warning. Desired object not found in document \n";
TopoDS_Shape shape_forearm;
if (mydoc.GetNamedShape(shape_forearm, "Assem10/Assem7" ))
{
mrigidBody_forearm = (ChBodySceneNodeAuxRef*)addChBodySceneNode_Cascade_C(
&my_system, application.GetSceneManager(),
shape_forearm);
mrigidBody_forearm->GetBody()->ConcatenatePreTransformation(root_frame);
}
else std::cout << "Warning. Desired object not found in document \n";
TopoDS_Shape shape_wrist;
if (mydoc.GetNamedShape(shape_wrist, "Assem10/Assem6" ))
{
mrigidBody_wrist = (ChBodySceneNodeAuxRef*)addChBodySceneNode_Cascade_C(
&my_system, application.GetSceneManager(),
shape_wrist);
mrigidBody_wrist->GetBody()->ConcatenatePreTransformation(root_frame);
}
else std::cout << "Warning. Desired object not found in document \n";
TopoDS_Shape shape_hand;
if (mydoc.GetNamedShape(shape_hand, "Assem10/Assem9" ))
{
mrigidBody_hand = (ChBodySceneNodeAuxRef*)addChBodySceneNode_Cascade_C(
&my_system, application.GetSceneManager(),
shape_hand);
mrigidBody_hand->GetBody()->ConcatenatePreTransformation(root_frame);
}
else std::cout << "Warning. Desired object not found in document \n";
TopoDS_Shape shape_cylinder;
if (mydoc.GetNamedShape(shape_cylinder, "Assem10/Assem3" ))
{
mrigidBody_cylinder = (ChBodySceneNodeAuxRef*)addChBodySceneNode_Cascade_C(
&my_system, application.GetSceneManager(),
shape_cylinder);
mrigidBody_cylinder->GetBody()->ConcatenatePreTransformation(root_frame);
}
else std::cout << "Warning. Desired object not found in document \n";
TopoDS_Shape shape_rod;
if (mydoc.GetNamedShape(shape_rod, "Assem10/Assem2" ))
{
mrigidBody_rod = (ChBodySceneNodeAuxRef*)addChBodySceneNode_Cascade_C(
&my_system, application.GetSceneManager(),
shape_rod);
mrigidBody_rod->GetBody()->ConcatenatePreTransformation(root_frame);
}
else std::cout << "Warning. Desired object not found in document \n";
}
else std::cout << "Warning. Desired STEP file could not be opened/parsed \n";
if (!mrigidBody_base ||
!mrigidBody_turret ||
!mrigidBody_bicep ||
!mrigidBody_elbow ||
!mrigidBody_forearm ||
!mrigidBody_wrist ||
!mrigidBody_hand )
{
DLL_DeleteGlobals();
return 0;
}
Create joints between two parts. To understand where is the axis of the joint, we can exploit the fact that in the STEP file that we prepared for this demo, we inserted some objects called 'marker' and we placed them aligned to the shafts, so now we can fetch them and get their position/rotation.
Important! In the STEP file, some subassemblies have multiple instances of the marker, so there could be two or more shapes with the same name marker... how to select the desired one? The GetNamedShape() function has a feature for addressing this: you can use the # character followed by a number, so for example Assem10/Assem8/marker#2 means: get the 2nd instance of the shape called "marker" from the subassembly "Assem8" of assembly "Assem10".
TopoDS_Shape shape_marker;
if (mydoc.GetNamedShape(shape_marker, "Assem10/Assem8/marker#1" ))
ChCascadeDoc::FromCascadeToChrono(shape_marker.Location(), frame_marker_base_turret);
else std::cout << "Warning. Desired marker not found in document \n";
frame_marker_base_turret %= root_frame;
ChSharedBodyPtr mb1 = mrigidBody_base->GetBody();
ChSharedBodyPtr mb2 = mrigidBody_turret->GetBody();
my_link1->Initialize(mb1, mb2, frame_marker_base_turret);
if (mydoc.GetNamedShape(shape_marker, "Assem10/Assem4/marker#2" ))
ChCascadeDoc::FromCascadeToChrono(shape_marker.Location(), frame_marker_turret_bicep);
else std::cout << "Warning. Desired marker not found in document \n";
frame_marker_turret_bicep %= root_frame;
mb1 = mrigidBody_turret->GetBody();
mb2 = mrigidBody_bicep->GetBody();
my_link2->Initialize(mb1, mb2, frame_marker_turret_bicep);
if (mydoc.GetNamedShape(shape_marker, "Assem10/Assem1/marker#2" ))
ChCascadeDoc::FromCascadeToChrono(shape_marker.Location(), frame_marker_bicep_elbow);
else std::cout << "Warning. Desired marker not found in document \n";
frame_marker_bicep_elbow %= root_frame;
mb1 = mrigidBody_bicep->GetBody();
mb2 = mrigidBody_elbow->GetBody();
my_link3->Initialize(mb1, mb2, frame_marker_bicep_elbow);
if (mydoc.GetNamedShape(shape_marker, "Assem10/Assem5/marker#2" ))
ChCascadeDoc::FromCascadeToChrono(shape_marker.Location(), frame_marker_elbow_forearm);
else std::cout << "Warning. Desired marker not found in document \n";
frame_marker_elbow_forearm %= root_frame;
mb1 = mrigidBody_elbow->GetBody();
mb2 = mrigidBody_forearm->GetBody();
my_link4->Initialize(mb1, mb2, frame_marker_elbow_forearm);
if (mydoc.GetNamedShape(shape_marker, "Assem10/Assem7/marker#2" ))
ChCascadeDoc::FromCascadeToChrono(shape_marker.Location(), frame_marker_forearm_wrist);
else std::cout << "Warning. Desired marker not found in document \n";
frame_marker_forearm_wrist %= root_frame;
mb1 = mrigidBody_forearm->GetBody();
mb2 = mrigidBody_wrist->GetBody();
my_link5->Initialize(mb1, mb2, frame_marker_forearm_wrist);
if (mydoc.GetNamedShape(shape_marker, "Assem10/Assem6/marker#2" ))
ChCascadeDoc::FromCascadeToChrono(shape_marker.Location(), frame_marker_wrist_hand);
else std::cout << "Warning. Desired marker not found in document \n";
frame_marker_wrist_hand %= root_frame;
mb1 = mrigidBody_wrist->GetBody();
mb2 = mrigidBody_hand->GetBody();
my_link6->Initialize(mb1, mb2, frame_marker_wrist_hand);
if (mydoc.GetNamedShape(shape_marker, "Assem10/Assem4/marker#3" ))
ChCascadeDoc::FromCascadeToChrono(shape_marker.Location(), frame_marker_turret_cylinder);
else std::cout << "Warning. Desired marker not found in document \n";
frame_marker_turret_cylinder %= root_frame;
mb1 = mrigidBody_turret->GetBody();
mb2 = mrigidBody_cylinder->GetBody();
my_link7->Initialize(mb1, mb2, frame_marker_turret_cylinder);
if (mydoc.GetNamedShape(shape_marker, "Assem10/Assem3/marker#2" ))
ChCascadeDoc::FromCascadeToChrono(shape_marker.Location(), frame_marker_cylinder_rod);
else std::cout << "Warning. Desired marker not found in document \n";
frame_marker_cylinder_rod %= root_frame;
mb1 = mrigidBody_cylinder->GetBody();
mb2 = mrigidBody_rod->GetBody();
my_link8->Initialize(mb1, mb2, frame_marker_cylinder_rod);
if (mydoc.GetNamedShape(shape_marker, "Assem10/Assem2/marker#2" ))
ChCascadeDoc::FromCascadeToChrono(shape_marker.Location(), frame_marker_rod_bicep);
else std::cout << "Warning. Desired marker not found in document \n";
frame_marker_rod_bicep %= root_frame;
mb1 = mrigidBody_rod->GetBody();
mb2 = mrigidBody_bicep->GetBody();
my_link9->Initialize(mb1, mb2, frame_marker_rod_bicep);
Cylindrical joint, with the 'ChLinkLock' formulation.
Definition ChLinkLock.h:410
virtual void AddLink(std::shared_ptr< ChLinkBase > link)
Attach a link to the underlying assembly.
Definition ChSystem.cpp:144
std::shared_ptr< T > make_shared(Args &&... args)
Replacement for make_shared guaranteed to use operator new rather than placement new in order to avoi...
Definition ChTypes.h:66
ChFrame< double > ChFramed
Alias for double-precision coordinate frames.
Definition ChFrame.h:346
Add a couple of markers for the 'lock' constraint between the hand and the absolute reference: when we will move the marker in absolute reference, the hand will follow it.
This is a very simple way of performing the IK (Inverse Kinematics) of a robot, and it can be used to whatever type of robot, even parallel manipulators or complex kinematic chains, without the need of knowing the analytic expression of the IK.
ChSharedMarkerPtr my_marker_hand(
new ChMarker);
ChSharedMarkerPtr my_marker_move(
new ChMarker);
mrigidBody_hand->GetBody()->AddMarker(my_marker_hand);
mrigidBody_base->GetBody()->AddMarker(my_marker_move);
ChQuaterniond rot_on_x; rot_on_x.QuatFromAngleAxis(CH_PI/2, VECT_X);
ChFramed frame_marker_move =
ChFramed(VNULL, rot_on_x) >> frame_marker_wrist_hand ;
my_marker_hand->ImposeAbsoluteTransform( frame_marker_wrist_hand);
my_marker_move->ImposeAbsoluteTransform( frame_marker_move);
my_link_teacher->Initialize(my_marker_hand, my_marker_move);
my_system.
AddLink(my_link_teacher);
6-dof locked joint, with the link-lock formulation.
Definition ChLinkLock.h:301
Markers are auxiliary reference frames attached to a rigid body and moving with the body.
Definition ChMarker.h:35
Set motions for Z and Y coordinates of the 'my_link_teacher' marker, so that the hand will follow it. To do so, we create four segments of motion for Z coordinate and four for Y coordinate, we join them with ChFunctionSequence and we repeat sequence by ChFunctionRepeat
my_marker_move->SetMotionZ(motlaw_z);
my_marker_move->SetMotionY(motlaw_y);
ChBodySceneNode* mfloor = (ChBodySceneNode*)addChBodySceneNode_easyBox(
&my_system, application.GetSceneManager(),
1000.0,
mfloor->GetBody()->SetFixed(true);
mfloor->GetBody()->EnableCollision(true);
video::ITexture* cubeMap = application.GetVideoDriver()->getTexture("../data/blu.png");
mfloor->setMaterialTexture(0, cubeMap);
Constant acceleration function.
Definition ChFunctionConstAcc.h:36
void SetDisplacement(double displacement)
Set the desired displacement.
Definition ChFunctionConstAcc.h:71
void SetDuration(double duration)
Set duration of the double acceleration.
Definition ChFunctionConstAcc.cpp:101
Function returnin a constant value.
Definition ChFunctionConst.h:26
Repeat function: y = __/__/__/
Definition ChFunctionRepeat.h:36
void SetSliceWidth(double length)
Set the width of the slice that should be repeated.
Definition ChFunctionRepeat.h:56
void SetRepeatedFunction(std::shared_ptr< ChFunction > func)
Set the function to be repeated.
Definition ChFunctionRepeat.h:68
Sequence function: y = sequence_of_functions(f1(y), f2(y), f3(y)) All other function types can be ins...
Definition ChFunctionSequence.h:66
bool InsertFunct(std::shared_ptr< ChFunction > myfx, double duration, double weight=1, bool c0=false, bool c1=false, bool c2=false, int position=-1)
Insert function after the fx with defined "position" index in list.
Definition ChFunctionSequence.cpp:108
Class defining quaternion objects, that is four-dimensional numbers.
Definition ChQuaternion.h:34
Modify the settings of the solver. By default, the solver might not have sufficient precision to keep the robot joints 'mounted'. Expecially, the SOR, SSOR and other fixed point methods cannot simulate well this robot problem because the mass of the last body in the kinematic chain, i.e. the hand, is very low when compared to other bodies, so the convergence of the solver would be bad when 'pulling the hand' as in this 'teaching mode' IK. So switch to a more precise solver; this SOLVER_ITERATIVE_MINRES is fast and precise (although it is not fit for frictional collisions):
my_system.SetLcpSolverType(ChSystem::SOLVER_MINRES);
Now, finally, run the loop of the simulator: here are snapshots from the real-time simulator:

Here is the full source code:
#include "chrono/core/ChRealtimeStep.h"
#include "chrono/core/ChRandom.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/solver/ChSolverADMM.h"
#ifdef CHRONO_IRRLICHT
#include "chrono_irrlicht/ChVisualSystemIrrlicht.h"
#endif
#ifdef CHRONO_VSG
#include "chrono_vsg/ChVisualSystemVSG.h"
#endif
int main(int argc, char* argv[]) {
mysurfmaterial->SetFriction(0.3f);
mysurfmaterial->SetRestitution(0);
std::shared_ptr<ChCascadeBodyEasy> body_base;
std::shared_ptr<ChCascadeBodyEasy> body_turret;
std::shared_ptr<ChCascadeBodyEasy> body_bicep;
std::shared_ptr<ChCascadeBodyEasy> body_elbow;
std::shared_ptr<ChCascadeBodyEasy> body_forearm;
std::shared_ptr<ChCascadeBodyEasy> body_wrist;
std::shared_ptr<ChCascadeBodyEasy> body_hand;
std::shared_ptr<ChCascadeBodyEasy> body_cylinder;
std::shared_ptr<ChCascadeBodyEasy> body_rod;
if (load_ok) {
TopoDS_Shape shape_base;
body_base->SetFixed(true);
body_base->ConcatenatePreTransformation(root_frame);
} else
std::cerr << "WARNING: Desired object not found in document" << std::endl;
TopoDS_Shape shape_turret;
body_turret = mbody;
body_turret->ConcatenatePreTransformation(root_frame);
} else
std::cerr << "WARNING: Desired object not found in document" << std::endl;
TopoDS_Shape shape_bicep;
body_bicep->ConcatenatePreTransformation(root_frame);
} else
std::cerr << "WARNING: Desired object not found in document" << std::endl;
TopoDS_Shape shape_elbow;
body_elbow->ConcatenatePreTransformation(root_frame);
} else
std::cerr << "WARNING: Desired object not found in document" << std::endl;
TopoDS_Shape shape_forearm;
body_forearm->ConcatenatePreTransformation(root_frame);
} else
std::cerr << "WARNING: Desired object not found in document" << std::endl;
TopoDS_Shape shape_wrist;
body_wrist->ConcatenatePreTransformation(root_frame);
} else
std::cerr << "WARNING: Desired object not found in document" << std::endl;
TopoDS_Shape shape_hand;
body_hand->ConcatenatePreTransformation(root_frame);
mcubelink->Initialize(mcube, body_hand, *mcube);
} else
std::cerr << "WARNING: Desired object not found in document" << std::endl;
TopoDS_Shape shape_cylinder;
body_cylinder->ConcatenatePreTransformation(root_frame);
} else
std::cerr << "WARNING: Desired object not found in document" << std::endl;
TopoDS_Shape shape_rod;
body_rod->ConcatenatePreTransformation(root_frame);
} else
std::cerr << "WARNING: Desired object not found in document" << std::endl;
} else
std::cerr << "WARNING: Desired STEP file could not be opened/parsed" << std::endl;
if (!body_base || !body_turret || !body_bicep || !body_elbow || !body_forearm || !body_wrist || !body_hand) {
return 1;
}
TopoDS_Shape shape_marker;
if (mydoc.
GetNamedShape(shape_marker,
"Assem10/Assem8/marker#1"))
else
std::cerr << "WARNING: Desired marker not found in document" << std::endl;
frame_marker_base_turret >>= root_frame;
my_link1->Initialize(body_base, body_turret, frame_marker_base_turret);
if (mydoc.
GetNamedShape(shape_marker,
"Assem10/Assem4/marker#2"))
else
std::cerr << "WARNING: Desired marker not found in document" << std::endl;
frame_marker_turret_bicep >>= root_frame;
my_link2->Initialize(body_turret, body_bicep, frame_marker_turret_bicep);
if (mydoc.
GetNamedShape(shape_marker,
"Assem10/Assem1/marker#2"))
else
std::cerr << "WARNING: Desired marker not found in document" << std::endl;
frame_marker_bicep_elbow >>= root_frame;
my_link3->Initialize(body_bicep, body_elbow, frame_marker_bicep_elbow);
if (mydoc.
GetNamedShape(shape_marker,
"Assem10/Assem5/marker#2"))
else
std::cerr << "WARNING: Desired marker not found in document" << std::endl;
frame_marker_elbow_forearm >>= root_frame;
my_link4->Initialize(body_elbow, body_forearm, frame_marker_elbow_forearm);
if (mydoc.
GetNamedShape(shape_marker,
"Assem10/Assem7/marker#2"))
else
std::cerr << "WARNING: Desired marker not found in document" << std::endl;
frame_marker_forearm_wrist >>= root_frame;
my_link5->Initialize(body_forearm, body_wrist, frame_marker_forearm_wrist);
if (mydoc.
GetNamedShape(shape_marker,
"Assem10/Assem6/marker#2"))
else
std::cerr << "WARNING: Desired marker not found in document" << std::endl;
frame_marker_wrist_hand >>= root_frame;
my_link6->Initialize(body_wrist, body_hand, frame_marker_wrist_hand);
if (mydoc.
GetNamedShape(shape_marker,
"Assem10/Assem4/marker#3"))
else
std::cerr << "WARNING: Desired marker not found in document" << std::endl;
frame_marker_turret_cylinder >>= root_frame;
my_link7->Initialize(body_turret, body_cylinder, frame_marker_turret_cylinder);
if (mydoc.
GetNamedShape(shape_marker,
"Assem10/Assem3/marker#2"))
else
std::cerr << "WARNING: Desired marker not found in document" << std::endl;
frame_marker_cylinder_rod >>= root_frame;
my_link8->Initialize(body_cylinder, body_rod, frame_marker_cylinder_rod);
if (mydoc.
GetNamedShape(shape_marker,
"Assem10/Assem2/marker#2"))
else
std::cerr << "WARNING: Desired marker not found in document" << std::endl;
frame_marker_rod_bicep >>= root_frame;
my_link9->Initialize(body_rod, body_bicep, frame_marker_rod_bicep);
std::shared_ptr<ChMarker> my_marker_hand(
new ChMarker);
std::shared_ptr<ChMarker> my_marker_move(
new ChMarker);
body_hand->AddMarker(my_marker_hand);
body_base->AddMarker(my_marker_move);
my_marker_hand->ImposeAbsoluteTransform(frame_marker_wrist_hand);
my_marker_move->ImposeAbsoluteTransform(frame_marker_move);
my_link_teacher->Initialize(my_marker_hand, my_marker_move);
my_marker_move->SetMotionZ(motlaw_z);
my_marker_move->SetMotionY(motlaw_y);
std::shared_ptr<ChBodyEasyBox> mfloor(
new ChBodyEasyBox(8, 1, 8, 1000,
true,
true, mysurfmaterial));
mfloor->SetFixed(true);
if (true) {
double brick_h = 0.3;
for (int ix = 0; ix < 3; ++ix)
for (int ib = 0; ib < 6; ++ib) {
std::shared_ptr<ChBodyEasyBox>
cube(
new ChBodyEasyBox(0.4, brick_h, 0.4, 1000,
true,
true, mysurfmaterial));
cube->SetPos(
ChVector3d(-1.4, (0.5 * brick_h) + ib * brick_h, -0.4 - 0.5 * ix));
cube->GetVisualShape(0)->SetColor(
ChColor(0.5f +
float(0.5 * ChRandom::Get()),
0.5f + float(0.5 * ChRandom::Get()),
0.5f + float(0.5 * ChRandom::Get())
));
}
}
std::shared_ptr<ChVisualSystem> vis;
switch (vis_type) {
#ifdef CHRONO_IRRLICHT
vis_irr->AttachSystem(&sys);
vis_irr->SetWindowSize(800, 600);
vis_irr->SetWindowTitle("Load a robot model from STEP file");
vis_irr->Initialize();
vis_irr->AddLogo();
vis_irr->AddSkyBox();
vis_irr->AddTypicalLights();
vis = vis_irr;
#endif
break;
}
#ifdef CHRONO_VSG
vis_vsg->AttachSystem(&sys);
vis_vsg->SetWindowSize(1000, 800);
vis_vsg->SetCameraVertical(CameraVerticalDir::Y);
vis_vsg->SetWindowTitle("Load a robot model from STEP file");
vis_vsg->Initialize();
vis = vis_vsg;
#endif
break;
}
}
sys.
GetSolver()->AsIterative()->SetMaxIterations(200);
double time_step = 0.01;
while (vis->Run()) {
vis->BeginScene();
vis->Render();
vis->EndScene();
realtime_timer.
Spin(time_step);
}
return 0;
}
Create rigid bodies with a box shape.
Definition ChBodyEasy.h:153
@ BULLET
Bullet-based collision detection system.
Definition ChCollisionSystem.h:45
Definition of a visual color.
Definition ChColor.h:30
Representation of a transform with translation and rotation.
Definition ChCoordsys.h:28
Representation of a 3D transform.
Definition ChFrame.h:33
Revolute joint, with the 'ChLinkLock' formulation.
Definition ChLinkLock.h:380
void SetFromAngleX(Real angleX)
Set the quaternion from an angle of rotation about X axis.
Definition ChQuaternion.h:317
void SetFromAngleY(Real angleY)
Set the quaternion from an angle of rotation about Y axis.
Definition ChQuaternion.h:320
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
@ BARZILAIBORWEIN
Barzilai-Borwein.
Definition ChSolver.h:44
virtual void SetCollisionSystemType(ChCollisionSystem::Type type)
Set the collision detection system used by this Chrono system to the specified type.
Definition ChSystem.cpp:324
virtual std::shared_ptr< ChSolver > GetSolver()
Access the solver currently associated with this system.
Definition ChSystem.h:124
int DoStepDynamics(double step_size)
Advance the dynamics simulation by a single time step of given length.
Definition ChSystem.cpp:1632
void SetSolverType(ChSolver::Type type)
Choose the solver type, to be used for the simultaneous solution of the constraints in dynamical simu...
Definition ChSystem.cpp:249
void Add(std::shared_ptr< ChPhysicsItem > item)
Attach an arbitrary ChPhysicsItem (e.g.
Definition ChSystem.cpp:196
Class for a physical system in which contact is modeled using a non-smooth (complementarity-based) me...
Definition ChSystemNSC.h:29
Type
Supported run-time visualization systems.
Definition ChVisualSystem.h:36
@ IRRLICHT
Irrlicht.
Definition ChVisualSystem.h:37
@ VSG
Vulkan Scene Graph.
Definition ChVisualSystem.h:38
Class that contains an OCAF document (a tree hierarchy of shapes in the OpenCascade framework).
Definition ChCascadeDoc.h:40
bool GetNamedShape(TopoDS_Shape &mshape, const char *name, bool set_location_to_root=true, bool get_multiple=false)
Get a sub-shape with a given name, returned in 'mshape'.
Definition ChCascadeDoc.cpp:337
static void FromCascadeToChrono(const TopLoc_Location &from_coord, ChFrame<> &to_coord)
Convert OpenCascade coordinates into Chrono coordinates.
Definition ChCascadeDoc.cpp:403
void Dump(std::ostream &mstream)
Show shape hierarchy, writing on mstream to print in default console log)
Definition ChCascadeDoc.cpp:202
bool Load_STEP(const char *filename)
Populate the document with all shapes that are contained in the STEP file, saved from some CAD.
Definition ChCascadeDoc.cpp:163
__host__ __device__ Real cube(Real a)
Cube a float value.
Definition custom_math.h:79
Namespace with classes for the Irrlicht module.
Definition ChApiIrr.h:47
Namespace with classes for the VSG module.
Definition ChApiVSG.h:51
std::string GetChronoDataFile(const std::string &filename)
Get the full path to the specified filename, given relative to the Chrono data directory (thread safe...
Definition ChGlobal.cpp:37
ChQuaterniond QuatFromAngleY(double angle)
Convert from a rotation about Y axis to a quaternion.
Definition ChRotation.cpp:192