Overview

Here we explain loading model to ModelLoader by GryUI in general and the simulation control in DynamicsServer bycreating a scheduler.

Below is the list of steps you go through:

  1. load the model
  2. Initialize CORBA
  3. Retrieve NamingService
  4. Retrieve OnlineViewer and load the model
  5. Retrieve DynamicsServer and configure simulation
  6. Retrieve Controller
  7. Simulation loop

Load the Model

First, load a model file using ModelLoader. Please specify the path to the model file of a floor and a robot as Model [0] and model [1].

BodyInfo_var floor = loadBodyInfo(Model[0].c_str(), argc, argv);
BodyInfo_var body = loadBodyInfo(Model[1].c_str(), argc, argv);

Initialize CORBA

Next, you initialize the CORBA ORB and retrieve the reference to the NamingService.

CORBA::ORB_var orb;
orb = CORBA::ORB_init(argc, argv);

CORBA::Object_var poaObj = orb -> resolve_initial_references("RootPOA");
PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(poaObj);

PortableServer::POAManager_var manager = rootPOA -> the_POAManager();

CosNaming::NamingContext_var cxt;
CORBA::Object_var	nS = orb->resolve_initial_references("NameService");
cxt = CosNaming::NamingContext::_narrow(nS);

OnlineViewer

Retrieve OnlineViewer.

OnlineViewer_var olv = getOnlineViewer(argc, argv);

In addition, the model is loaded by OnlineViewer.

olv->load(floor->name(), Model[0].c_str());
olv->load(body->name(), Model[1].c_str());
olv->clearLog();

DynamicsSimulator

You prepare for the following function to retrieve a group of servers.

template <typename X, typename X_ptr>
X_ptr checkCorbaServer(std::string n, CosNaming::NamingContext_var &cxt)
{
  CosNaming::Name ncName;
  ncName.length(1);
  ncName[0].id = CORBA::string_dup(n.c_str());
  ncName[0].kind = CORBA::string_dup("");
  X_ptr srv = NULL;
  try {
    srv = X::_narrow(cxt->resolve(ncName));
  } catch(const CosNaming::NamingContext::NotFound &exc) {
    std::cerr << n << " not found: ";
    switch(exc.why) {
    case CosNaming::NamingContext::missing_node:
      std::cerr << "Missing Node" << std::endl;
    case CosNaming::NamingContext::not_context:
      std::cerr << "Not Context" << std::endl;
      break;
    case CosNaming::NamingContext::not_object:
      std::cerr << "Not Object" << std::endl;
      break;
    }
    return (X_ptr)NULL;
  } catch(CosNaming::NamingContext::CannotProceed &exc) {
    std::cerr << "Resolve " << n << " CannotProceed" << std::endl;
  } catch(CosNaming::NamingContext::AlreadyBound &exc) {
    std::cerr << "Resolve " << n << " InvalidName" << std::endl;
  }
  return srv;
}

After getting the specified type from the NamingService, this is handled various exceptions. Retrieve DynamicsSimulatorFactory using this function.

DynamicsSimulatorFactory_var dynamicsSimulatorFactory;
dynamicsSimulatorFactory =
  checkCorbaServer <DynamicsSimulatorFactory, DynamicsSimulatorFactory_var> ("DynamicsSimulatorFactory", cxt);

if (CORBA::is_nil(dynamicsSimulatorFactory)) {
  std::cerr << "DynamicsSimulatorFactory not found" << std::endl;
}

DynamicsSimulator_var dynamicsSimulator = dynamicsSimulatorFactory->create();

Here retrieve DynamicsSimulatorFactory, and then invoke DynamicsSimulator using the create method. Next, you initialize the DynamicsSimulator.

dynamicsSimulator->registerCharacter(floor->name(), floor);			    
dynamicsSimulator->registerCharacter(body->name(), body);
dynamicsSimulator->init(timeStep, DynamicsSimulator::RUNGE_KUTTA, DynamicsSimulator::ENABLE_SENSOR);

The model of a floor and a robot is registered into DynamicsSimulator. The time of every step of the simulation, the difference method, the activation/deactivation of the sensor are set in the init method. The DynamicsSimulator::EULER that uses the Euler method and the DynamicsSimulator::RUNGE_KUTTA that uses the Runge-Kutta method in the difference method. There are the DynamicsSimulator::ENABLE_SENSOR for activation and the DynamicsSimulator::DISABLE_SENSOR for deactivation in the sensor.

Next, set the gravity vector.

DblSequence3 g;
g.length(3);
g[0] = 0.0;
g[1] = 0.0;
g[2] = world_gravity;
dynamicsSimulator->setGVector(g);

Next, decide an initial posture of the robot.

Vector3  waist_p;
Matrix33 waist_R;
waist_p = 0, 0, 0.7135;
waist_R = tvmet::identity<Matrix33>();
DblSequence trans;
trans.length(12);
for(int i=0; i<3; i++) trans[i]   = waist_p(i);
for(int i=0; i<3; i++){
	for(int j=0; j<3; j++) trans[3+3*i+j] = waist_R(i,j);
}
dynamicsSimulator->setCharacterLinkData( body->name(), "WAIST", DynamicsSimulator::ABS_TRANSFORM, trans );

decide an initial angle of the joint.

DblSequence angle;
angle.length(29);
angle[0] = 0.0;         angle[1] = -0.0360373;  angle[2] = 0.0;         angle[3] = 0.0785047;
angle[4] = -0.0424675;  angle[5] = 0.0;         angle[6] = 0.174533;    angle[7] = -0.00349066;
angle[8] = 0.0;         angle[9] = -1.5708;     angle[10] = 0.0;        angle[11] = 0.0;
angle[12] = 0.0;        angle[13] = 0.0;        angle[14] = -0.0360373; angle[15] = 0.0;
angle[16] = 0.0785047;  angle[17] = -0.0424675; angle[18] = 0.0;        angle[19] = 0.174533;
angle[20] = -0.00349066;angle[21] = 0.0;        angle[22] = -1.5708;    angle[23] = 0.0;
angle[24] = 0.0;        angle[25] = 0.0;        angle[26] = 0.0;        angle[27] = 0.0;
angle[28] = 0.0;
dynamicsSimulator->setCharacterAllLinkData( body->name(), DynamicsSimulator::JOINT_VALUE, angle );

Calculate the forward kinematics once to reflect the posture after setting.

dynamicsSimulator->calcWorldForwardKinematics();

Next, register the collision detection pairs. The collision detection pairs registered here will be done. This pairs the robot with the floor.

DblSequence6 K, C;    
K.length(0);
C.length(0);
dynamicsSimulator->registerCollisionCheckPair(floor->name(),"", body->name() ,"",
		                                            statFric,slipFric,K,C,culling_thresh);

Finally, invoke the initSimulation method.

dynamicsSimulator->initSimulation();

Controller

Controller is acquired by using each Controller name.

Controller_var controller;
controller = checkCorbaServer <Controller, Controller_var> ("SamplePDController", cxt);

if (CORBA::is_nil(controller)) {
   std::cerr << "Controller not found" << std::endl;
}

In this case, Controller named PDcontroller is acquired. Initialize the Controller.

controller->setModelName(body->name());
controller->setDynamicsSimulator(dynamicsSimulator);
controller->initialize();
controller->setTimeStep(controlTimeStep);

You start it at the end.

controller->start();

Simulation loop

This is a turned loop when an actual simulation is executed. This simulation loop consists of as follow.

  1. Invoke Controller::input(Robot data is inputted into Controller from DynamicsSimulator. )
  2. Invoke Controller::control(Calculation of the output value of Controller )
  3. Invoke DynamicsSimulator::stepSimulation (One step of a simulation)
  4. Invoke DynamicsSimulator::getWorldState (Read-out of a simulation result )
  5. Update OnlineViewer (update OnlineViewer)
  6. Invoke Controller::output (A control value is outputted to DynamicsSimulator from Controller. )

The code is described as follows:

bool control=false;
if(controlTime <= time){
    control=true;
    j++;
}

if(control)
    controller->input();

i++;
time = timeStep * i;
controlTime = controlTimeStep * j;

if(control)
    controller->control();
               
// ================== simulate one step ==============
dynamicsSimulator->stepSimulation();					    
              
// ================== viewer update ====================
try {
    dynamicsSimulator -> getWorldState( state );
    olv->update( state );
} catch (CORBA::SystemException& ex) {
    return 1;
}

// ===================== get robot status ===================
DblSequence_var waist_pR;  // position and attitude
DblSequence_var waist_vw;  // linear and angular velocities
dynamicsSimulator->getCharacterLinkData(body->name(), "WAIST", DynamicsSimulator::ABS_TRANSFORM, waist_pR);
dynamicsSimulator->getCharacterLinkData(body->name(), "WAIST", DynamicsSimulator::ABS_VELOCITY,  waist_vw);

// ================== log data save =====================
log_file << time << " ";
log_file << waist_vw[2] << " ";
log_file << endl;

if(control)
    controller->output();

if( time > EndTime ) break;

Execution

  1. Start GrxUI.
  2. Execut OpenHRP/sample/controller/SamplePD/SamplePD.sh (.bat) from a command line.
  3. Execut OpenHRP/sample/example/scheduler/scheduler.sh (.bat) from a command line.

In the case of Windows, please add (OpenHRP3)/bin to PATH.