Actin®  Version 5.1.0
Software for Robotics Simulation and Control
Actin SDK Quickstart

Actin C++ Quickstart Examples

If you would like to just start quickly and cover the details later, this section is for you. This guide provides two quick-start coding examples using the Actin API. The first starts with a stated system and ends with a simulation and control system. The second starts with a CAD model and ends with an application for controlling hardware.

Stated System to Position Control System

Example code will be presented for creating, writing, and reading a position control system for a Robotics Research Corporation K-1207i manipulator.

Loading a Stated System

An example manipulator system, the K-1207i, is defined in an example file that is distributed with the Actin® software. This file, “rrcK1207i_system.xml,” contains the description of an object of the class EcStatedSystem. To load this file, the C++ code in the Code Block 1 below can be used.

// declare an error return code
EcBoolean success;
// add the file location to the search path
EcFileUtil::addDirectory(EcFileUtil::getDataDirectory() +
EcString("/actinExamples"));
// declare a filename
EcString filename="rrcK1207i_system.xml";
// declare a visualizable stated system object
// load the stated system from an XML file
success = EcXmlObjectReaderWriter::readFromFile(visStatedSystem, filename);
// make sure it loaded properly
if(!success)
{
EcPrint(Warning) << "Could not load stated system.\n";
return;
}
Example code for loading a manipulator description. This is Example Section #1 in the quick-start example code.

Viewing a Stated System

To see what this manipulator looks like, you can load the file and create a render window using the class EcRenderWindow, as shown in Code Block 2 below

// instantiate a renderer
EcRenderWindow renderer;
// set the size of the window
renderer.setWindowSize(256,256);
// set the system
if(!renderer.setVisualizableStatedSystem(visStatedSystem))
{
return;
}
// view the system
renderer.renderScene();
// pause one second
EcSLEEPMS(1000);
Example code for visualizing the manipulator. This continues from the code shown above. It is Example Section #2 in the quick-start example code.

Defining a Velocity-Control System

The next task is to define a velocity control system. This is done using the code shown in Code Block 3. In this set of code, first a convenient reference is set for the manipulator. Then the link at the end of the kinematic chain starting with the manipulator is looked up. This is used to construct a frame end effector that is rigidly attached to this last link.

A velocity-control expression is constructed. An EcControlExpressionCore object is chosen to perform the inverse kinematics calculation. This object requires three child members: a matrix, a vector, and a scalar. The matrix is used to measure the joint rates, and the vector is used to determine desired change in joint values. The scalar parameter makes a tradeoff between the joint-rate measure and the joint value measure. In this case, the mass matrix is used to weight the joint rates and joint-limit avoidance is used to determine desired joint positions.

To this core velocity control algorithm, a joint-rate filter and an end-effector error filter are added. These prevent the joint rates and hand-motion error from exceeding specified bounds. Any number of filters can be chained together as shown to build a general control expression. The control expression and the end-effector definition are then added to the individual velocity control description. Since in this case there is only one manipulator being controlled, the velocity control system only has one description.

// make a convenient reference to the manipulator
const EcIndividualManipulator& manipulator =
visStatedSystem.statedSystem().system().manipulators()[0];
// look up the last link
manipulator.collectLeafLinks(linkPointerVector);
// make a frame end effector
// put the end effector into an end-effector set
EcXmlString(linkPointerVector[0]->label()));
eeSet.addEndEffector(frameEnd);
// create a velocity-control core
// set the matrix, vector, and scalar for the core
// add a joint-rate filter
jointWeights.assign(manipulator.jointDof(),0.1);
rateFilter.setWeightsElement(jointWeights);
rateFilter.setUnfilteredRatesElement(expCore);
// add an end-effector error filter
handWeights.assign(6,1.0);
eFilter.setWeightsElement(handWeights);
eFilter.setUnfilteredRatesElement(rateFilter);
// put the system in a container and add it to the velocity control
// description
container.setTopElement(eFilter);
// add the expression and end effector to a velocity control
// description
indVelContDesc.setControlExpression(container);
indVelContDesc.setEndEffectorSet(eeSet);
// add the velocity control description to a velocity control
// system
velContSys.addControlDescription(indVelContDesc);
Example code for building a velocity control system. This continues from the code shown above and is Example Section #3 in the quick-start example code.

Defining a Position-Control System

The velocity control system can now be added to a position control system. This is done using the code shown in Code Block 4. In this set of code, the velocity control system is set, the time step is set, and the maximum number of iterations per cycle is set (this is only used if the CPU is not able to run in real time). Then the two-pass flag is set. This generally should be used, as it protects the manipulator from inappropriate behavior at singularities.

// a variable holding the position control system
// set the velocity control system
posContSys.setVelocityControlSystem(velContSys);
// set the time step
posContSys.setTimeStep(0.012);
// set the maximum number of iterations
posContSys.setMaxIterations(16);
// set the use-two-passes flag
posContSys.setUseTwoPasses(EcTrue);
// set the stated system
posContSys.setStatedSystem(&visStatedSystem.statedSystem());
Example code for building a position control system. This continues from the code shown above and is Example Section #4 in the quick-start example code.

Placing an End Effector

The position control system can now be used to place an end effector. This is done using the code shown in Code Block 5. First the current pose of the end effector is calculated. This is offset in position while keeping the same orientation. This new hand pose is then set as the desired hand pose, and the position control system is polled for a new manipulator configuration every 20 milliseconds. The configurations are those calculated by the position control system to take the end effector to the desired location. Each of these configurations is rendered, and at the end, convergence to the desired pose is verified.

// get the current offset in system coordinates
// set the desired position to be offset from the current position
// by 0.5 m along the x-axis and 1.2 m along the z-axis
EcCoordinateSystemTransformation finalPose = initialPose;
finalPose.outboardTransformBy(EcVector(-0.5,0.0,-1.2));
posContSys.setDesiredPlacement(0,0,finalPose);
// a state to update and render, and an object to hold the
// final pose
// set the system
if(!renderer.setVisualizableStatedSystem(visStatedSystem))
{
return;
}
// execution parameters
EcU32 steps=100;
EcReal simRunTime = 2.0;
EcReal simTimeStep = simRunTime/steps;
// move to the desired pose, and render every timestep
for(ii = 0; ii < steps; ++ii)
{
// get the current time
EcReal currentTime=simTimeStep*ii;
// calculate the state at current time
posContSys.calculateState(currentTime,dynamicState);
// show the manipulator in this position
renderer.setState(dynamicState);
renderer.renderScene();
EcSLEEPMS(static_cast<EcU32>(1000*simTimeStep));
}
// check for accuracy
calculatedFinalPose = posContSys.actualPlacementVector()[0].offsetTransformations()[0];
if(!calculatedFinalPose.approxEq(finalPose,1e-5))
{
EcPrint(Warning) << "Did not converge.\n";
return;
}
Example code for placing an end effector. This continues from the code shown above and is Example Section #5 in the quick-start example code.

Moving the End Effector along a Path

The code shown in Code Block 6 uses the position control system to trace a path with the end effector. It sets a new, but fixed, orientation and a new, changing, position each time step. The orientation is about 180 degrees away from the starting orientation, and the position is a point along a circle with a 0.2 m radius. The end effector makes three loops around the circle.

// execution parameters
steps=400;
simRunTime = 10.0;
simTimeStep = simRunTime/steps;
EcReal radius=0.2;
EcU32 loops=3;
EcOrientation orient(0,0,0,1);
EcReal startingTime=posContSys.time();
// move to the desired pose, and render the position every
// time step
for(ii = 0; ii < steps; ++ii)
{
// get the current time
EcReal currentTime=simTimeStep * ii;
// set the pose
pose.setOrientation(orient);
EcReal angle = Ec2Pi * loops * currentTime / simRunTime;
EcVector offset = radius * EcVector(cos(angle), sin(angle), 0);
pose.setTranslation(finalPose.translation() + offset);
posContSys.setDesiredPlacement(0, 0, pose);
// calculate the state at current time
posContSys.calculateState(currentTime + startingTime, dynamicState);
// show the manipulator in this position
renderer.setState(dynamicState);
renderer.renderScene();
EcSLEEPMS(static_cast<EcU32>(1000 * simTimeStep));
}
Example code for tracing a path with the end effector. This continues from the code shown above and is Example Section #6 in the quick-start example code.

Creating a Simulation

A simulation can be created using the position control system. This is shown in the code in Code Block 7. A simulation animates and—optionally—dynamically simulates the manipulator. A simulation can be saved as XML in plain or compressed format. Both forms are saved in the example code below. Either form can be loaded by the ActinViewer that is provided with the toolkit and used for interactive manipulation.

// a variable holding the simulation
EcSystemSimulation simulation;
// reset time to zero and add the position control system and
// visualization parameters
posContSys.setTime(0.0);
simulation.setFromPositionControlSystem(posContSys,
visStatedSystem.visualizationParameters());
// save the simulation as a plain XML file
EcXmlObjectReaderWriter::writeToFile(simulation, "quickStartSimulation.xml");
// save the simulation as a compressed XML file
EcXmlObjectReaderWriter::writeToFile(simulation, "quickStartSimulation.xml");
Example code for saving the system as a simulation. A simulation can be loaded and interactively controlled using the ActinViewer. This continues from the code shown above, and is Example Section #7 in the quick-start example code.

Additional Capability

This quick-start example showed how to assign a control system to a manipulator. Only one manipulator was used with one end effector and one type of control system. The manipulator itself, which was a simple linear chain, was not defined, but rather loaded from a file. Dynamic simulation was not used. Network communication was not used, nor was visual feedback. The User’s Guide describes these and the many other capabilities present in the Actin toolkit.

CAD Model Conversion for Actin

This section is divided into three parts: 1) conversion of a SolidWorks model to Actin, 2) use of Actin to tailor a simulation, and 3) use of Actin to drive hardware.

SolidWorks Model Conversion

The Actin SolidWorks Converter is a tool for converting SolidWorks models to the Actin XML format. This format can be loaded into the ActinViewer or utilized by other Actin applications which are created with the Actin libraries and header files. The converter is a SolidWorks add-in that is described in the Actin SolidWorks Converter Guide.

Using Actin to Tailor the Simulation and Control Algorithms

The SolidWorks converter creates an XML file with information about the manipulator such as the physical extents and mass properties of each link and the joint that connect the links. From the manipulator information, the converter also creates a default control algorithm for the manipulator. To customize the simulation and control algorithm, it is helpful to create a post-processor that can leverage the full power of the Actin API. Below is an illustration of steps, some optional, for tailoring a simulation and control algorithm.

Read in simulation file

To initiate post-processing, the converted SolidWorks file should be loaded using the following method. The EcXmlObject object created by the SolidWorks converter is an EcSystemSimulation. Section 1.1.1 shows example code for reading a file.

Get the stated system and individual manipulator

Given a simulation (EcSystemSimulation) from the above filing reading method, the post-processor can access the stated system (EcStatedSystem) and individual manipulator through the following methods.

Configuring the individual manipulator

The manipulator can be defined as a floating or fixed base manipulator through SolidWorks or the post-processor. This can be changed through the following method. The input argument is a Boolean.

Mass properties, set through SolidWorks, can be manipulated through Actin using the following method. The input argument is a mass properties object. Note that the setMassProperties() method is in EcManipulatorLink which is the base class for EcIndividualManipulator.

The bounding volumes set through SolidWorks can be deleted and replaced with capsules using the following methods.

The leaf links can be accessed through the following method. This may be desired for changing the end effector link labels or changing wheel bounding volumes and soil interaction properties. The output argument is a vector of manipulator link pointers.

Note that changing link labels requires a remapping of the manipulator through the following method.

Bounding volumes for any link can be set through the following method. The input arguments are the link label name, shape, and surface properties.

(
const EcString& linkLabel,
const EcShape& bvShape,
const EcDataMap* pSurface
);

Set the joint limits through the following method. The input arguments are the link label name, switch for upper or lower limit, and value.

(
const EcString& linkLabel,
EcBoolean isLowerLimit,
EcReal value
);

Change the joint actuators which may include a friction model through the following method. The input arguments are the link label name, and joint actuator object.

Configuring the manipulator system

The manipulator system (EcManipulatorSystem) contains information such as the link interactions vector and the system collision exclusion map. These methods and classes are useful for configuring link interaction for dynamic simulation.

The system also includes the manipulators which can be set through the following methods.

Or

Configuring the stated system

The stated system (EcStatedSystem) contains information such as the position and velocity states. For example, the manipulator can be copied several times to create a simulation with multiple robots with each manipulator having unique position and velocity states. The following methods can be used for this purpose. If there is only one robot, the manipulator index is zero.

(
EcU32 manipulatorIndex,
const EcIndividualManipulator& manipulator,
const EcPositionState& positionState,
const EcVelocityState& velocityState
);

Or

(
const EcIndividualManipulator& manipulator,
const EcPositionState& positionState,
const EcVelocityState& velocityState
);

The stated system also includes the system which can be set through the following method.

Configuring the control system

The position control system is obtained through the following method.

Through the position control system, the end effectors can be configured through the following method.

(
const EcEndEffectorSet& endEffectorSet,
const EcU32 manipulatorIndex
);

The velocity control system is also set through the position control system using the following method. Section 1.1.3 and Section 1.1.4 provide example code for configuring the end effectors, velocity control system, and position control system.

EcBoolean EcPositionControlSystem::addControlDescription
(
const EcIndividualVelocityControlDescription& individualVelControlDescription,
const EcU32& manipulatorIndex
);

Configuring the simulation

The following methods are used to set the stated system and position control system in the simulation (EcSystemSimulation). Section 1.1.7 provides example code for configuring a simulation.

The simulation is also used to set other parameters such as the joint controller system, gravity, time step, dynamic simulators, cameras, and place objects in the environment.

For setting the joint controller system, use the following method.

The gravity vector is set through the following method.

(
const EcVector& upGravity
);

The time step is set as follows.

The dynamic simulation can be turned on and the dynamic simulators can be set through the following methods.

Cameras are added through the following method.

Adding objects to the environment can be down through a mergeWith call.

After setting the simulation, the following method can help improve efficiency by replaces repeated links with references. This is particularly useful with simulations of multiple reused robots.

Write out the modified simulation file

The following method is used to write out a simulation file. Section 1.1.7 provides example code for writing out a simulation.

(
const EcXmlObject& obj,
const EcString& filename,
const EcToken& token // = EcXml::EcNullToken
);

Actin Plugins

Actin provides a plugin interface for developers. An example hardware plugin is provided (exampleHardwarePlugin.cpp). This example plugin can be used as a template for new hardware. The example plugin uses the Ec::Plugin class as the pure virtual base class. The full plugin API is described in the Actin Plugin API Guide. Below is a table of the primary methods in the Ec::Plugin base class.

Actin base Plugin methods.
Method Prototype in Ec::Plugin
init virtual EcBoolean init() { return EcTrue; }
reset virtual EcBoolean reset() { return EcTrue; }
update virtual void update(const EcReal currentTime) = 0;
initState virtual EcBoolean initState(const EcSystemSimulation&) { return EcTrue; }

Before describing these methods, it is also worth noting the constructor and destructor. The constructor is sometimes used to set the update rate (i.e., m_UpdatePeriodInMs=25), read in a configuration file for the hardware, and initiate log files. If the update rate is not set, or set to zero, it will run at the Actin simulation rate. The configuration file is not only useful for setting hardware specific parameters, it is also useful for converting the sense on the incoming simulation joint commands to that of the actual hardware. That is, it is convenient to change the sign on the joint commands through a vector of data in the configuration file. The destructor is useful for resetting the hardware and shutting down.

init() method

The init() method initializes the plugin and hardware. It is a one-time call when the plugin is loaded. Oftentimes, a reset() call is placed in the init() method, but this init() method is useful for any one-time initializations.

reset() method

The reset() method reinitializes the hardware each time the simulation is initialized. For example, if a new XML file is loaded into the simulation, this reset() method gets called. Both the destructor and reset() method should clean up an memory and state information from previous execution of the plugin.

update() method

The method gets called at the rate defined in m_UpdatePeriodInMs which is defaulted to the simulation rate. The method only receives the simulation time through the argument list. To get parameters such as joint angles and joint velocities from the simulation, the getParam() template function is needed. For example, the following calls get the joint angles and velocities from a specific manipulator in the simulation.

Ec::Plugin::getParam<Ec::JointAngle>(m_Config.manipIndex, m_JointAngles);
Ec::Plugin::getParam<Ec::JointVelocity>(m_Config.manipIndex, m_JointVelocities);

After receiving the joint angles and other simulation data as needed, the API for the robot can be called to drive the hardware.

initState() method

The initState() method is called after loading the simulation file but before the simulation is running. This enables the hardware to initialize the simulation to the hardware state. The initState() method receives a reference to the simulation which can be used for updating the simulation.

The getParam() and setParam() template functions can also be used for setting the simulation parameters which is often the case. ecIOParams.h contains the enumerated list (ParamTypeEnum) for all the simulation parameters available for the getParam() and setParam() template functions.

Created by Energid Technologies www.energid.com
Copyright © 2016 Energid. All trademarks mentioned in this document are property of their respective owners.