Пример #1
0
  /** creates vehicle at desired position
      @param pos struct Position with desired position
  */
  void Hexabot::create(const osg::Matrix& pose){
    if (created) {
      destroy();
    }

#ifdef DEBUG_MODE
    cout << "hello, This is the debug mode" << endl;
    cout << "@@@@ First, We create the robot!! @@@@" << endl;
#endif

    /*********************************************************************************:
     *  The ordinal configuration
     *     Environment, color, feature etc/
    ***********************************************************************************/

    // we want legs colliding with other legs, so we set internal collision
    // flag to "false".
    odeHandle.createNewSimpleSpace(parentspace,false);

    // Hexabot color ;-)
    osgHandle.color = Color(0/255., 30./255., 0./255., 1.0f);

    // Joint color ;-)
    OsgHandle dynaHandle(osgHandle);
    dynaHandle.color = Color(204/255., 51/255., 0./255., 1.0f);
    //dynaHandle.color = Color(0/255., 0/255., 0./255., 1.0f);

    // Tibia Color (colored by leg)
    OsgHandle tibiaHandle[6] = {osgHandle, osgHandle, osgHandle, osgHandle, osgHandle, osgHandle};
    tibiaHandle[0].color = Color(0./255., 0./255., 0./255., 1.0f);
    tibiaHandle[1].color = Color(153./255., 102./255., 0./255., 1.0f);
    tibiaHandle[2].color = Color(153./255., 204./255., 0./255., 1.0f);
    tibiaHandle[3].color = Color(153./255., 0./255., 30./255., 1.0f);
    tibiaHandle[4].color = Color(153./255., 102./255., 30./255., 1.0f);
    tibiaHandle[5].color = Color(153./255., 204./255., 30./255., 1.0f);

    // change Material substance
    OdeHandle odeHandleBody(odeHandle);
    odeHandleBody.substance.toMetal(3.0);

    // get a representation of the origin
     // By multipling this parameter to pose, we can get only the position data of pose
    const Pos nullpos(0, 0, 0);


    /*********************************************************************************:
    *  Create Body Structure
    *     Trunk, Leg etc.
    ***********************************************************************************/

    /*********************************************
     *  Main Frame */
    // Make the boxes connect each other to make rectangle
    /**********************************************/
#ifdef DEBUG_MODE
    cout << "@@@@ Creation of Body frame starts!! @@@@" << endl;
#endif
    // make the rectangle boxes to make hexagon (they are connected each other and make hexagon)
    // make 2 rectangle plate objects
    for(int i=0; i< 2;i++){
      trunk.tPlate[i] = new Box(  conf.body.length, conf.body.width, conf.body.height);
      trunk.tPlate[i]->getOSGPrimitive()->setTexture("Images/wood.rgb");
      // This function (setMass) seems not to be implemented
      //trunk.tPlate[i]->setMass(conf.body.mass / 6.);
    }

    // First object should be initialized (I choose the lower rectangle one)
    trunk.tPlate[0]->init(odeHandle, conf.body.mass / 2., osgHandle);
    trunk.tPlate[0]->setPose( pose );
    // add it to Object
    objects.push_back(trunk.tPlate[0]);

    // just for memorlizing transForm
    trunk.tUpTrans = new ImpTransform2(trunk.tPlate[0], trunk.tPlate[1],Matrix::rotate(0., Vec3(0, 0, 1)) *Matrix::translate(0, 0, conf.dyna.height));
    trunk.tTrans = trunk.tUpTrans;
    trunk.tTrans->init(odeHandle, conf.body.mass / 2., osgHandle);
    // add it to Object
    objects.push_back(trunk.tTrans);


    /*********************************************
       LEGs  **sholder, coxa femur tibia
       //
  **********************************************/
#ifdef DEBUG_MODE
    cout << "@@@@ Creation of Leg frame starts!! @@@@" << endl;
#endif

    // Useful Parameter to make robot model

    // Transition Matrix from origin of this robot to center of the robot
    //  notice: the orgin of the robot is on the center of the lower hexagonal plate
    osg::Matrix trans_rO_to_rC = Matrix::translate( 0., 0., conf.dyna.height / 2.);

    // Trans Matrix from center of the robot to Shoulder Dynamixel center
    // The horizontal length between robot center and Shoulder Dynamixel center
    double length_rC_to_sC_x = (conf.jLength.length_x_center_to_TCJ - conf.dyna.length_axis_to_center);
    // Matrix
    osg::Matrix trans_rC_to_sC_x =  Matrix::translate( length_rC_to_sC_x, 0, 0);

    // The horizontal length between Shoulder Dynamixel center and Shoulder Dynamixel center
    // Matrix
    osg::Matrix trans_sC_to_sC_y =  Matrix::translate(0, conf.jLength.length_y_TCJ_to_TCJ, 0);

    // Trans Matrix from center of the robot to Coxa Dynamixel center
    // The horizontal length between robot center and Coxa Dynamixel center
    double length_rC_to_cC = length_rC_to_sC_x + conf.jLength.length_TCJ_to_CTJ;
    // Matrix
    osg::Matrix trans_rC_to_cC =  Matrix::translate( length_rC_to_cC, 0, 0);

    // Trans Matrix from center of the robot to Femur Dynamixel center
    // The horizontal length between robot center and Femur Dynamixel center
    double length_rC_to_fC_x = conf.jLength.length_x_center_to_TCJ + conf.jLength.length_TCJ_to_CTJ;
    double length_rC_to_fC_z = conf.jLength.length_CTJ_to_FTJ - conf.dyna.length_axis_to_center;
    //double length_rC_to_fC = length_rC_to_cC + conf.jLength.length_CTJ_to_FTJ;
    // Matrix
    osg::Matrix trans_rC_to_fC =  Matrix::translate( length_rC_to_fC_x, 0, length_rC_to_fC_z);

    // Trans Matrix from center of the robot to  Foot Plate center
    // The horizontal length between robot center and Foot Plate center
    double length_rC_to_tC_x = length_rC_to_fC_x + conf.dyna.length_from_axis_to_tip;
    double length_rC_to_tC_z =  conf.jLength.length_CTJ_to_FTJ + (-conf.foot.length + conf.dyna.width)/2.;
    // Matrix
    osg::Matrix trans_rC_to_tC =  Matrix::translate( length_rC_to_tC_x, 0, length_rC_to_tC_z);

    // Trans Matrix from center of the robot to center of the foot sphere
    // Matrix
    osg::Matrix trans_rC_to_fsC =  Matrix::translate( length_rC_to_fC_x, 0, length_rC_to_tC_z - conf.foot.length/2. - conf.foot.footRadius  );

    // Trans Matrix from center of the tibia to center of the foot sphere
    // Matrix
    osg::Matrix trans_tC_to_fsC =  Matrix::translate( - conf.dyna.length_from_axis_to_tip, 0,  - conf.foot.length/2. - conf.foot.footRadius);


    // Trans Matrix from center of the robot to TC joint Center
    // Matrix
    osg::Matrix trans_rC_to_TCj = Matrix::translate( conf.jLength.length_x_center_to_TCJ, 0, 0);

    // Trans Matrix from center of the robot to CT joint Center
    // Matrix
    osg::Matrix trans_rC_to_CTj = Matrix::translate( conf.jLength.length_x_center_to_TCJ + conf.jLength.length_TCJ_to_CTJ, 0, 0);

    // Trans Matrix from center of the robot to FT joint Center
    // Matrix
    osg::Matrix trans_rC_to_FTj = Matrix::translate( conf.jLength.length_x_center_to_TCJ + conf.jLength.length_TCJ_to_CTJ, 0, + conf.jLength.length_CTJ_to_FTJ);


    for(int i = 0; i < LEG_POS_MAX; i++){
      // Name of the Leg
      LegPos leg = LegPos(i);

      // Rotation Matrix : change the rotation direction according to leg number
      // By using this, the direction of leg can be changed.. It is used to adapt to the location of the leg
      Matrix legRotate;
      Matrix legTrans;
      if(leg == L1){
        legRotate = Matrix::rotate(M_PI*1./2., Vec3(0, 0, 1));
        legTrans = Matrix::translate(0, conf.jLength.length_y_TCJ_to_TCJ + conf.y_trans_center, 0);
      }
      else if( leg == L2){
        legRotate = Matrix::rotate(M_PI*1./2., Vec3(0, 0, 1));
        legTrans = Matrix::translate(0, conf.y_trans_center, 0);
      }
      else if(leg == L3 ){
        legRotate = Matrix::rotate(M_PI*1./2., Vec3(0, 0, 1));
        legTrans = Matrix::translate(0, -conf.jLength.length_y_TCJ_to_TCJ +conf.y_trans_center, 0);
      }else if(leg == L4){
        legRotate = Matrix::rotate(-M_PI*1./2., Vec3(0, 0, 1));
        legTrans = Matrix::translate(0, -conf.jLength.length_y_TCJ_to_TCJ - conf.y_trans_center, 0);
      }else if(leg == L5){
        legRotate = Matrix::rotate(-M_PI*1./2., Vec3(0, 0, 1));
        legTrans = Matrix::translate(0, -conf.y_trans_center, 0);
      }else{
        legRotate = Matrix::rotate(-M_PI*1./2., Vec3(0, 0, 1));
        legTrans = Matrix::translate(0, conf.jLength.length_y_TCJ_to_TCJ - conf.y_trans_center, 0);
      }

      // Shoulder ******************************************
      //  We connect the sholder dynamixel to main Body
#ifdef DEBUG_MODE
      cout << "@@@@ Creation of Shoulder starts!! @@@@" << endl;
#endif

      // sholder Dynamixel Box
      Box* dBox =  new Box( conf.dyna.length, conf.dyna.width, conf.dyna.height);
      dBox->getOSGPrimitive()->setTexture("Images/wood.rgb");
      //dBox->setMass(conf.dyna.mass);
       // trans (locate the object on the hexagon plane)
       //  first, I turn the object to leg's direction and translate it to desired position ()
       // mention that this pose matrix is multipled vector from right hand <- it is different from usual one!!
      ImpTransform2* dTrans = new ImpTransform2(trunk.tPlate[0], dBox,
              trans_rC_to_sC_x * trans_rO_to_rC * legTrans * legRotate);
      dTrans->init(odeHandle, conf.dyna.mass, dynaHandle);

      // save to the leg struct
      legs[leg].shoulderBox = dBox;
      legs[leg].shoulder = dTrans;
      // add it to object
      objects.push_back(legs[leg].shoulder);

      // Coxa **********************************************
       // We make the first joint and link of Hexabot
#ifdef DEBUG_MODE
      cout << "@@@@ Creation of Coxa starts!! @@@@" << endl;
#endif

      // Make the Dyanmixel for link
      // Coxa (1st link) Dynamixel Box
      Box* link1dBox = new Box( conf.dyna.length, conf.dyna.width, conf.dyna.height);
      link1dBox->getOSGPrimitive()->setTexture("Images/wood.rgb");
      link1dBox->init(odeHandle, conf.dyna.mass , dynaHandle);
      // about the pose or something
      // set the pose
      //  pose:: pose represent the attitude and position of the object by quotanion
      //         we can use the function rotate and translate as if it is attitude change 4*4 matrix
      //
      // I should say about mechanism of the pose in my understanding.
      //   Pose ; this is the 4 by 4 matrix and it represents the rotation and translation
      //          It can be used as if it is normal 4 by 4 rotation matrix.
      //          But what you should notice is that this matrix is for Row Vector (1 by 4 vector)
      //          So, the row of the calculating is inverse to normal one!!
      //      You should be careful about it

      Matrix l1Pose = Matrix::rotate( M_PI / 2., Vec3(1, 0, 0)) * /* this rotation is used to turn the dymamixel to optimal attitude!! (because, we change the axis of joints) */
                trans_rC_to_cC * trans_rO_to_rC * legTrans* legRotate * pose;  //  first, I turn the object to leg's direction and translate it to desired position ()
      link1dBox->setPose(l1Pose);
      // save it to leg struct
      legs[leg].coxa = link1dBox;
      // add it to object
      objects.push_back(legs[leg].coxa);

      // TC joints *******************************:::::::
       // create the joint of dynamixel on Body (from 1st link to body)
       // calculate the joint pose (attitude and position) by using trans and rotate function
      osg::Matrix j1Pose = trans_rC_to_TCj * trans_rO_to_rC * legTrans* legRotate * pose;
      // To make a joint, we need the position vector only, so multiple nullpos to the pose to get the vector.
      //  the attitude is determined by axis (it is z axis)
      HingeJoint* TCj = new HingeJoint( trunk.tPlate[0], link1dBox,  nullpos * j1Pose, Axis(0,0,1) * legRotate );
      // ^ Notice: When we want to rotate the Axis() like Pose, we have to multiple the rotation matrix from RIGHT SIDE
      //     Not Left side, it is very different from real calculation
      TCj->init(odeHandle, osgHandle, true, conf.rate * 0.04);
      // add the joint to the joint vector
      joints.push_back(TCj);

      // create motor (by using servo motor, we will do position control)
      //OneAxisServo* servo1 = new OneAxisServoVel(odeHandle, TCj, conf.servoParam.TC_angle_MIN, conf.servoParam.TC_angle_MAX, conf.servoParam.power, conf.servoParam.damp, conf.servoParam.maxVel, 1.0);
      //Debug
      OneAxisServo* servo1;
#ifdef HEXABOT_MAIN_VER_1_6
      servo1 = new OneAxisServoVel(odeHandle, TCj, conf.servoParam.TC_angle_MIN, conf.servoParam.TC_angle_MAX, conf.servoParam.power, conf.servoParam.damp, conf.servoParam.maxVel, 1.0);
#else
      servo1 = new OneAxisServoCentered(TCj, conf.servoParam.TC_angle_MIN, conf.servoParam.TC_angle_MAX, conf.servoParam.power, conf.servoParam.damp, conf.servoParam.integ, conf.servoParam.maxVel, 1.0);
#endif

      // save it to leg struct
      legs[leg].tcJoint = TCj;
      legs[leg].tcServo = servo1;
      // add it to servo Map
      servos[getMotorName(leg, TC)] = servo1;

      // create torque sensor
      // In this time, I do not use scaller just get real value
      motorTorqSensors[getMotorName(leg, TC)] = new TorqueSensor(1., 1.);
      // initialize (own is Null, it was not used in simulation)
      motorTorqSensors[getMotorName(leg, TC)]->init(NULL, TCj);


      // Femur **********************************************
      // We make the second joint and link of Hexabot (CT joint and femur)
#ifdef DEBUG_MODE
      cout << "@@@@ Creation of Femur starts!! @@@@" << endl;
#endif

      // Make the Dyanmixel for link
      // Femur (2nd link) Dynamixel Box
      Box* link2dBox = new Box( conf.dyna.length, conf.dyna.width, conf.dyna.height);
      link2dBox->getOSGPrimitive()->setTexture("Images/wood.rgb");
      link2dBox->init(odeHandle, conf.dyna.mass , dynaHandle);
      // set the pose
      //  pose:: pose represent the attitude and position of the object by quotanion
      //         we can use the function rotate and translate as if it is attitude change 4*4 matrix
      osg::Matrix l2Pose = Matrix::rotate( M_PI / 2., Vec3(0, 0, 1)) * Matrix::rotate( M_PI / 2., Vec3(1, 0, 0)) * // this rotation is used to turn the dymamixel to optimal attitude!! (because, we change the axis of joints)
                  trans_rC_to_fC * trans_rO_to_rC * legTrans * legRotate * pose;  //  first, I turn the object to leg's direction and translate it to desired position ()
      link2dBox->setPose(l2Pose);
      // save it to leg struct
      legs[leg].femur = link2dBox;
      // add it to object
      objects.push_back(legs[leg].femur);

      // CT joint :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
      // create the joint of dynamixel on Body (from 2nd link to 1st Link)
      // calculate the joint pose (attitude and position) by using trans and rotate function
      osg::Matrix j2Pose = trans_rC_to_CTj * trans_rO_to_rC * legTrans* legRotate * pose;
      // To make a joint, we need the position vector only, so multiple nullpos to the pose to get the vector.
      //  the attitude is determined by axis (it is z axis)
      HingeJoint* CTj = new HingeJoint( legs[leg].coxa, link2dBox, nullpos * j2Pose,  Axis(0,1,0) * legRotate);
      // ^ Notice: When we want to rotate the Axis() like Pose, we have to multiple the rotation matrix from RIGHT SIDE
      //     Not Left side, it is very different from real calculation
      CTj->init(odeHandle, osgHandle, true, conf.rate * 0.04);
      // add the joint to the joint vector
      joints.push_back(CTj);

      // create motor (by using servo motor, we will do position control)
      // OneAxisServo* servo2 = new OneAxisServoVel(odeHandle, CTj, conf.servoParam.CT_angle_MIN, conf.servoParam.CT_angle_MAX, conf.servoParam.power, conf.servoParam.damp, conf.servoParam.maxVel, 1.0);
      //Debug
      OneAxisServo* servo2;
#ifdef HEXABOT_MAIN_VER_1_6
      servo2 = new OneAxisServoVel(odeHandle, CTj, conf.servoParam.CT_angle_MIN, conf.servoParam.CT_angle_MAX, conf.servoParam.power, conf.servoParam.damp,conf.servoParam.maxVel, 1.0);
#else
      servo2 = new OneAxisServoCentered(CTj, conf.servoParam.CT_angle_MIN, conf.servoParam.CT_angle_MAX, conf.servoParam.power, conf.servoParam.damp, conf.servoParam.integ, conf.servoParam.maxVel, 1.0);
#endif

      // save it to leg struct
      legs[leg].ctJoint = CTj;
      legs[leg].ctServo = servo2;
      // add it to servo Map
      servos[Hexabot::getMotorName(leg, CT)] = servo2;

      // create torque sensor
      // In this time, I do not use scaller just get real value
      motorTorqSensors[getMotorName(leg, CT)] = new TorqueSensor(1., 1.);
      // initialize (own is Null, it was not used in simulation)
      motorTorqSensors[getMotorName(leg, CT)]->init(NULL, CTj);

      // Tibia **********************************************
      // We make the third joint and link of Hexabot (FT joint and femur)
#ifdef DEBUG_MODE
      cout << "@@@@ Creation of Tibia starts!! @@@@" << endl;
#endif

      // Make the Plate
      // Tibia (3rd link) Plate
      Box* link3dBox = new Box( conf.foot.height, conf.foot.width, conf.foot.length);
      link3dBox->getOSGPrimitive()->setTexture("Images/wood.rgb");
      link3dBox->init(odeHandle, conf.foot.mass , tibiaHandle[leg]);
      // set the pose
      //  pose:: pose represent the attitude and position of the object by quotanion
      //         we can use the function rotate and translate as if it is attitude change 4*4 matrix
      osg::Matrix l3Pose = trans_rC_to_tC * trans_rO_to_rC * legTrans* legRotate * pose;  //  first, I turn the object to leg's direction and translate it to desired position ()
      link3dBox->setPose(l3Pose);
      // save it to leg struct
      legs[leg].tibia = link3dBox;
      // add it to object
      objects.push_back(legs[leg].tibia);


      //Make Foot
      // Sphere
      Sphere* foot = new Sphere( conf.foot.footRadius );
      foot->getOSGPrimitive()->setTexture("Images/wood.rgb");
      // Set the substance of foot
      OdeHandle rubberHandle(odeHandle);
      const Substance FootSubstance(3.0, 0.0, 500.0, 0.1);//500
      rubberHandle.substance = FootSubstance;

      legs[leg].footSphere = foot;
      //translate
      legs[leg].foot = new ImpTransform2(legs[leg].tibia, foot, trans_tC_to_fsC);
      // initialize
      legs[leg].foot->init(rubberHandle, 0.0, osgHandle);
      //add it to objects
      objects.push_back(legs[leg].foot);

      // FT joint :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
      // create the joint of dynamixel on Femur (from 3rd link to 2nd Link)
      // calculate the joint pose (attitude and position) by using trans and rotate function
      osg::Matrix j3Pose = trans_rC_to_FTj * trans_rO_to_rC * legTrans* legRotate * pose;
      // To make a joint, we need the position vector only, so multiple nullpos to the pose to get the vector.
      //  the attitude is determined by axis (it is z axis)
      HingeJoint* FTj = new HingeJoint( legs[leg].femur, link3dBox, nullpos * j3Pose, Axis(0,1,0) * legRotate);
      // ^ Notice: When we want to rotate the Axis() like Pose, we have to multiple the rotation matrix from RIGHT SIDE
      //     Not Left side, it is very different from real calculation
      FTj->init(odeHandle, osgHandle, true, conf.rate * 0.04);
      // add the joint to the joint vector
      joints.push_back(FTj);

      // create motor (by using servo motor, we will do position control)
      // OneAxisServo* servo3 = new OneAxisServoVel(odeHandle, FTj, conf.servoParam.FT_angle_MIN, conf.servoParam.FT_angle_MAX, conf.servoParam.power, conf.servoParam.damp, conf.servoParam.maxVel, 1.0);
      //Debug
      OneAxisServo* servo3;
#ifdef HEXABOT_MAIN_VER_1_6
      servo3 = new OneAxisServoVel(odeHandle, FTj, conf.servoParam.FT_angle_MIN, conf.servoParam.FT_angle_MAX, conf.servoParam.power, conf.servoParam.damp,conf.servoParam.maxVel, 1.0);
#else
      servo3 = new OneAxisServoCentered(FTj, conf.servoParam.FT_angle_MIN, conf.servoParam.FT_angle_MAX, conf.servoParam.power, conf.servoParam.damp,conf.servoParam.integ, conf.servoParam.maxVel, 1.0);
#endif

      // save it to leg struct
      legs[leg].ftJoint = FTj;
      legs[leg].ftServo = servo3;
      // add it to servo Map
      servos[Hexabot::getMotorName(leg, FT)] = servo3;

      // create torque sensor
      // In this time, I do not use scaller just get real value
      motorTorqSensors[getMotorName(leg, FT)] = new TorqueSensor(1., 1.);
      // initialize (own is Null, it was not used in simulation)
      motorTorqSensors[getMotorName(leg, FT)]->init(NULL, FTj);

      // Leg contact Sensors (Foot toe)
      legContactSensors[leg] = new ContactSensor(false, 100, conf.foot.footRadius*1.1, false, true, Color(0,5,0));
      //make the sphere a little bit larger than real foot to detect touching 1.01

      //legContactSensors[leg]->update();
      // We set the contact sensor at the point of foot sphere
      //legContactSensors[leg]->init(odeHandle, osgHandle, legs[leg].tibia, true, trans_tC_to_fsC);

      // this is changed to adopt the new version of lpzrobots
      legContactSensors[leg]->setInitData(odeHandle, osgHandle, TRANSM(0, 0, 0));//trans_tC_to_fsC);
      legContactSensors[leg]->init(legs[leg].foot);

      //legContactSensors[leg]->update();
      //odeHandle.addIgnoredPair(legs[leg].foot, legContactSensors[leg]->getTransformObject());
      //legContactSensors[LegPos(i)]->setInitData(odeHandle, osgHandle, TRANSM(0, 0, -(0.5) * l4));
      //legContactSensors[LegPos(i)]->init(foot);
    }

#ifdef DEBUG_MODE
    cout << "@@@@ Creation Phase ends!! @@@@" << endl;
#endif

    created=true;
  }
Пример #2
0
  /** creates vehicle at desired position
      @param pos struct Position with desired position
  */
  void Hexapod::create( const osg::Matrix& pose ){
    if (created) {
      destroy();
    }

    odeHandle.createNewSimpleSpace(parentspace,true);
    // color of joint axis and whiskers
    OsgHandle osgHandleJ = osgHandle.changeColor(Color(72./255.,16./255.,16./255.));
    TwoAxisServoVel* servo;
    OneAxisServo* spring;
    OneAxisServo* spring2;
    FixedJoint* fixedJoint;

    // create body
    double twidth = conf.size * conf.width ;// 1/1.5;
    double theight = conf.size * conf.height; // 1/4;
    trunk = new Box(conf.size, twidth, theight);
    trunk->setTexture("Images/toy_fur3.jpg");
    trunk->init(odeHandle, conf.mass*conf.percentageBodyMass, osgHandle);
    osg::Matrix trunkPos = TRANSM(0,0,conf.legLength)*pose;
    trunk->setPose(trunkPos);
    objects.push_back(trunk);


    if(conf.useBigBox){
      Primitive* pole;
      double poleheight=conf.size*2;
      pole = new Box(poleheight, twidth*3.2, theight*1);
      bigboxtransform= new Transform(trunk,pole, osg::Matrix::translate(0,0,2*theight));
      bigboxtransform->init(odeHandle, 0, osgHandle,Primitive::Geom /*| Primitive::Draw */);
    }else{
      bigboxtransform=0;
    }


    osg::Matrix m0 = pose;

    if(conf.irSensors == true){
      for(int i = -1; i < 2; i+=2){

        irbox = new Box(0.1,0.1,0.1);
        irbox->setTexture("Images/toy_fur3.jpg");
        irbox->init(odeHandle, 0.00001, osgHandle);
        irbox->setPose(ROTM(M_PI/4,0,0,1) * TRANSM(i*conf.size/2,0,theight/2)*trunkPos);
        objects.push_back(irbox);
        fixedJoint = new FixedJoint(trunk,irbox);
        fixedJoint->init(odeHandle, osgHandleJ, true, 0.4);
        joints.push_back(fixedJoint);

      }

      for(int i = -1; i < 2; i+=2){

        irbox = new Box(0.1,0.1,0.15);
        irbox->setTexture("Images/toy_fur3.jpg");
        irbox->init(odeHandle, 0.00001, osgHandle);
        irbox->setPose(TRANSM(0,i*twidth/2,theight/2 + 0.05)*trunkPos);
        objects.push_back(irbox);
        fixedJoint = new FixedJoint(trunk,irbox);
        fixedJoint->init(odeHandle, osgHandleJ, true, 0.4);
        joints.push_back(fixedJoint);

      }


      irSensorBank.init(odeHandle, osgHandle);

      if (conf.irFront){ // add front left and front right infrared sensor to sensorbank if required
             IRSensor* sensor = new IRSensor();
             irSensorBank.registerSensor(sensor, objects[2],
                                         Matrix::rotate(-1*-M_PI/2, Vec3(0,1,0)) *
                                         Matrix::translate(1*0.05,0,0),
                                         conf.irRangeFront, RaySensor::drawAll);
               IRSensor* sensor2 = new IRSensor();
               irSensorBank.registerSensor(sensor2, objects[2],
                                    Matrix::rotate(-1*-M_PI/2, Vec3(0,1,0)) *
                                    Matrix::rotate(1*-M_PI/2, Vec3(0,0,1)) *
                                    Matrix::translate(0,-0.05,0),
                                    conf.irRangeFront, RaySensor::drawAll);

      }
      if (conf.irBack){ // add front left and front right infrared sensor to sensorbank if required

              IRSensor* sensor = new IRSensor();
               irSensorBank.registerSensor(sensor, objects[1],
                                           Matrix::rotate(1*-M_PI/2, Vec3(0,1,0)) *
                                           Matrix::translate(-1*0.05,0,0),
                                           conf.irRangeBack, RaySensor::drawAll);

        IRSensor* sensor2 = new IRSensor();
        irSensorBank.registerSensor(sensor2, objects[1],
                                    Matrix::rotate(1*-M_PI/2, Vec3(0,1,0)) *
                                    Matrix::rotate(1*-M_PI/2, Vec3(0,0,1)) *
                                    Matrix::translate(0,0.05,0),
                                    conf.irRangeBack, RaySensor::drawAll);
      }
      if(conf.irLeft){
        IRSensor* sensor = new IRSensor();
        irSensorBank.registerSensor(sensor, objects[3],
                                    Matrix::rotate(-1*-M_PI/2, Vec3(0,1,0)) *
                                    Matrix::rotate(-M_PI/2, Vec3(0,0,1)) *
                                    Matrix::translate(0,-0.05,0.05),
                                    conf.irRangeLeft, RaySensor::drawAll);

            /* IRSensor* sensor2 = new IRSensor();
           irSensorBank.registerSensor(sensor2, objects[3],
           Matrix::rotate(-1*-M_PI/2, Vec3(0,1,0)) *
           Matrix::rotate(1*-M_PI/2, Vec3(0,0,1)) *
           Matrix::translate(0,-0.05,0),
           conf.irRangeLeft, RaySensor::drawAll);
        */
      }

      if(conf.irRight){
        IRSensor* sensor = new IRSensor();
        irSensorBank.registerSensor(sensor, objects[4],
                                    Matrix::rotate(-1*-M_PI/2, Vec3(0,1,0)) *
                                    Matrix::rotate(M_PI/2, Vec3(0,0,1)) *
                                    Matrix::translate(0,0.05,0.05),
                                    conf.irRangeLeft, RaySensor::drawAll);


        /* IRSensor* sensor2 = new IRSensor();
           irSensorBank.registerSensor(sensor2, objects[4],
           Matrix::rotate(1*-M_PI/2, Vec3(0,1,0)) *
           Matrix::rotate(1*-M_PI/2, Vec3(0,0,1)) *
           Matrix::translate(0,0.05,0),
           conf.irRangeRight, RaySensor::drawAll);
        */
      }
    }


    std::vector<Primitive*> tarsusParts;

    // legs  (counted from back to front)
    double legdist = conf.size*0.9 / (conf.legNumber/2-1);
    for ( int n = 0; n < conf.legNumber; n++ ) {

      int v = n;

      double len1 = conf.legLength*0.5;
      double rad1 = conf.legLength/15;
      double len2 = conf.legLength*0.5;
      double rad2 = conf.legLength/15;

      // upper limp
      Primitive* coxaThorax;
      Pos pos = Pos(-conf.size/(2+0.2) + ((int)n/2) * legdist,
                    n%2==0 ? - twidth/2 : twidth/2,
                    conf.legLength - theight/3);

      osg::Matrix m = ROTM(M_PI/2,v%2==0 ? -1 : 1,0,0) * TRANSM(pos) * pose;
      coxaThorax = new Capsule(rad1, len1);
      coxaThorax->setTexture("Images/toy_fur3.jpg");
      coxaThorax->init(odeHandle, legmass, osgHandle);

      osg::Matrix m1 =  TRANSM(0,0,-len1/2)
        * ROTM(M_PI,0,0,v%2==0 ? -1 : 1)
        * ROTM(2*M_PI,0,v%2==0 ? -1 : 1,0) * m;

      coxaThorax->setPose(m1);
      thoraxPos.push_back(coxaThorax->getPosition());

      thorax.push_back(coxaThorax);

      objects.push_back(coxaThorax);
      legs.push_back(coxaThorax);
      // powered hip joint
      Pos nullpos(0,0,0);

      UniversalJoint* j
        = new UniversalJoint(trunk, coxaThorax, nullpos * m,
                             ROTM(M_PI,0,0,v%2==0 ? -1 : 1) * Axis(v%2==0 ? -1 : 1,0,0) * m,
                             ROTM(M_PI,0,0,v%2==0 ? -1 : 1) * Axis(0,1,0) * m);

      j->init(odeHandle, osgHandleJ, true, rad1 * 2.1);
      joints.push_back(j);

      legContactArray[n].joint = j->getJoint();

      // values will be set in setParam later
      servo =  new TwoAxisServoVel(odeHandle, j,-1,1, 1, -1,1,1,0 );
      //     servo =  new UniversalServo(j,-1,1, 1, -1,1,1,0);
      hipservos.push_back(servo);

      // lower leg
      Primitive* tibia;
      tibia = new Capsule(rad2, len2);
      tibia->setTexture("Images/toy_fur3.jpg");
      tibia->init(odeHandle, legmass, osgHandle);
      osg::Matrix m2 =   TRANSM(0,0,-len2/2) * ROTM(1.5,v%2==0 ? -1 : 1,0,0)
        * TRANSM(0,0,-len1/2) * m1;
      tibia->setPose(m2);
      objects.push_back(tibia);
      legs.push_back(tibia);

      legContactArray[n].legID = n;
      legContactArray[n].geomid = tibia->getGeom();
      legContactArray[n].bodyID = tibia->getBody();

      if(conf.useTebiaJoints){
        // springy knee joint
        HingeJoint* k = new HingeJoint(coxaThorax, tibia, Pos(0,0,-len1/2) * m1,
                                       Axis(v%2==0 ? -1 : 1,0,0) * m1);
        k->init(odeHandle, osgHandleJ, true, rad1 * 2.1);
        // servo used as a spring
        spring = new HingeServo(k, -1, 1, 1, 0.01,0); // parameters are set later
        tebiasprings.push_back(spring);
        joints.push_back(k);
      }else{
        // fixed knee joint
        FixedJoint* k = new FixedJoint(coxaThorax, tibia);
        k->init(odeHandle, osgHandleJ, false, rad1 * 2.1);
        joints.push_back(k);
      }
      // lower limp should not collide with body!
      odeHandle.addIgnoredPair(trunk,tibia);

      if(conf.tarsus){
        // New: tarsus
        Primitive *tarsus;
        double angle = M_PI/12;

        double radius = rad2/2;
        double length = len2/2;
        double mass = legmass/10;
        tarsus = new Capsule(radius,length);
        tarsus->setTexture("Images/toy_fur3.jpg");
        tarsus->init(odeHandle, mass, osgHandle);

        osg::Matrix m4;
        osg::Matrix m3 =
          ROTM(-angle,v%2==0 ? -1 : 1,0,0) *
          TRANSM(0,0,-len2/2) *
          m2;

        if(v < 2){
          m4 = ROTM(v%2==0 ? angle : -angle,0,v%2==0 ? -1 : 1,0) * m3;
        }else if( v > 3){
          m4 = ROTM(v%2==0 ? -angle : angle,0,v%2==0 ? -1 : 1,0) * m3;
        }else{
          m4 = m3;
        }
        m4 =    TRANSM(0,0,-length/2) * m4;

        tarsus->setPose(m4);
        tarsusParts.push_back(tarsus);
        objects.push_back(tarsus);


        if(conf.useTarsusJoints){
          // springy joint
          HingeJoint* k = new HingeJoint(tibia, tarsus, Pos(0,0,-len2/2) * m2,
                                         Axis(v%2==0 ? -1 : 1,0,0) * m2);
          k->init(odeHandle, osgHandleJ, true, rad1 * 2.1);
          // servo used as a spring
          //          spring2 = new HingeServo(k, -1, 1, 1, 0.01,0); // parameters are set later
          spring2 = new OneAxisServoVelocityControlled(odeHandle,k, -1, 1, 1, 0.01); // parameters are set later
          tarsussprings.push_back(spring2);
          joints.push_back(k);

        }else{
          FixedJoint* k = new FixedJoint(tibia, tarsus);
          k->init(odeHandle, osgHandleJ, true, rad1 * 2.1);
          joints.push_back(k);
        }


        Primitive *section = tarsus;
        for(int i = 1; i < conf.numTarsusSections; i++){

          double lengthS = length/1.5;
          double radiusS = radius/1.5;
          section = new Capsule(radiusS,lengthS);
          section->setTexture("Images/toy_fur3.jpg");
          section->init(odeHandle, mass/2, osgHandle);

          osg::Matrix m5;

          if(v < 2){
            m5 =                  TRANSM(0,0,-lengthS/2) *
              ROTM(v%2==0 ? angle : -angle,0,v%2==0 ? -1 : 1,0) *
              ROTM(v%2==0 ? angle : -angle,1,0,0) *
              TRANSM(0,0,-length/2) *
              m4;
          }else if(v > 3){
            m5 =                       TRANSM(0,0,-lengthS/2) *
              ROTM(v%2==0 ? -angle : angle,0,v%2==0 ? -1 : 1,0) *
              ROTM(v%2==0 ? angle : -angle,1,0,0) *
              TRANSM(0,0,-length/2) *
              m4;

          }else{
            m5 =                             TRANSM(0,0,-lengthS/2) *
              ROTM(v%2==0 ? angle : -angle,1,0,0) *
              TRANSM(0,0,-length/2) *
              m4;
          }

          section->setPose(m5);
          objects.push_back(section);
          tarsusParts.push_back(section);



          FixedJoint* fj = new FixedJoint(tarsusParts[i-1], tarsusParts[i]);
          fj->init(odeHandle, osgHandleJ, true, rad1 * 2.1);
          joints.push_back(fj);
          m4 = m5;

        }


        std::cout<< "legContactArray[" << n << "].legID = " << n << std::endl;
        legContactArray[n].legID = n;
        legContactArray[n].geomid = section->getGeom();
        legContactArray[n].bodyID = section->getBody();

        tarsusParts.clear();


      }


    }

    // New: wiskers
    for ( int n = -1; n < 2; n+=2 ) {
      double l1 = conf.legLength*0.5;
      double t1 = conf.legLength/30;

      Primitive* whisker;
      Pos pos = Pos(conf.size/(2)+t1,
                    n*twidth/4,
                    conf.legLength + theight/5);

      osg::Matrix m = ROTM(M_PI/10, n,0,0) * ROTM(M_PI/2+M_PI/10, 0,-1,0) * TRANSM(pos) * pose;
      whisker = new Capsule(t1, l1);
      whisker->init(odeHandle, legmass/10, osgHandleJ);
      osg::Matrix m1 = TRANSM(0,0,-l1/2) * m;
      whisker->setPose(m1);
      objects.push_back(whisker);


      //FixedJoint* k = new FixedJoint(trunk, whisker);
      //k->init(odeHandle, osgHandle, false, 0);
      HingeJoint* k = new HingeJoint(trunk, whisker, Pos(0,0,0) * m,
                                     Axis(1,0,0) * m);
      k->init(odeHandle, osgHandleJ, true, t1 * 2.1);
      // servo used as a spring
      spring = new HingeServo(k, -M_PI/6, M_PI/6, .1, 0.01,0);
      whiskersprings.push_back(spring);
      joints.push_back(k);

      Primitive* whisker2;
      whisker2 = new Capsule(t1/2, l1);
      whisker2->init(odeHandle, legmass/10, osgHandleJ);
      osg::Matrix m2 = TRANSM(0,0,-l1/2)
        * ROTM(M_PI/10, n,0,0)
        * ROTM(M_PI/10, 0,1,0) * TRANSM(0,0,-l1/2) * m1;
      whisker2->setPose(m2);
      objects.push_back(whisker2);


      //      k = new FixedJoint(whisker, whisker2);
      //      k->init(odeHandle, osgHandleJ, false, 0);
      k = new HingeJoint(whisker, whisker2, Pos(0,0,-l1/2) * m1,
                         Axis(0,1,0) * m1);
      k->init(odeHandle, osgHandleJ, true, t1 * 2.1);
      // servo used as a spring
      spring = new HingeServo(k, -M_PI/6, M_PI/6, .05, 0.01,0);
      whiskersprings.push_back(spring);
      joints.push_back(k);


    }


    notifyOnChange("dummy"); // apply all parameters.

    created=true;
  };