#ifndef _GraspDemo_h_ #define _GraspDemo_h_ #include "Behaviors/Nodes/MotionSequenceNode.h" #include "Behaviors/Nodes/WalkNode.h" #include "Behaviors/Transitions/CompletionTrans.h" #include "Behaviors/Transitions/NullTrans.h" #include "Behaviors/Transitions/SignalTrans.h" #include "Behaviors/Transitions/TimeOutTrans.h" #include "Events/DataEvent.h" #include "Events/LocomotionEvent.h" #include "Motion/HeadPointerMC.h" #include "Motion/WalkMC.h" #include "Motion/MMAccessor.h" #include "Shared/WorldState.h" #include "DualCoding/DualCoding.h" using namespace DualCoding; enum TargetAction { approach, acquire }; std::istream& operator>>(std::istream &s, TargetAction &); //**************** TrackBone **************** //! Keep the camera pointed at the bone class TrackBone : public VisualRoutinesStateNode { public: TrackBone() : VisualRoutinesStateNode("TrackBone"), head_mc(), head_id(MotionManager::invalid_MC_ID) {} void DoStart() { VisualRoutinesStateNode::DoStart(); cout << "TrackBone starting up." << endl; head_id = motman->addPersistentMotion(head_mc); erouter->addTimer(this,1,500,true); } void DoStop() { motman->removeMotion(head_id); cout << "TrackBone stopped." << endl; VisualRoutinesStateNode::DoStop(); } void processEvent(const EventBase &) { camShS.clear(); const color_index pink_index = ProjectInterface::getColorIndex("pink"); NEW_SHAPEVEC(pinkblobs, BlobData, getBlobsFromRegionGenerator(pink_index,30,BlobData::groundplane,1)); projectToGround(); if ( groundShS.allShapes().size() == 0 ) { // cout << "TrackBone found no pink blob" << endl; return; } Shape groundbone = ShapeRootType(groundShS.allShapes()[0],BlobData); Point target = groundbone->getCentroid(); // cout << "TrackBone target = " << target << endl; MMAccessor(head_id)->lookAtPoint(target.coordX(),target.coordY(),target.coordZ()); } private: SharedObject head_mc; MotionManager::MC_ID head_id; }; #define CALC_ORIENT \ GET_SHAPE(pt1,PointData,localShS); \ GET_SHAPE(pt2,PointData,localShS); \ Point const midpt = (pt1->getCentroid() + pt2->getCentroid())/2; \ AngSignPi const midbearing = atan2(midpt.coordY(),midpt.coordX()); \ Point const diff = (pt2->getCentroid() - pt1->getCentroid()); \ AngPi const local_orient = atan2(diff.coordY(),diff.coordX()); \ AngSignPi const perp_heading = float(local_orient) - AngPi(M_PI/2); \ AngSignPi const adist = midbearing + perp_heading; \ float const dist = 150; \ /* cout << "midbearing = " << float(midbearing)*180/M_PI \ << " local_orient = " << float(local_orient)*180/M_PI \ << " perp_heading = " << float(perp_heading)*180/M_PI \ << " adist = " << float(adist)*180/M_PI << endl; */ //**************** CalcDest **************** //! Calculate destination point for approach class CalcDest : public VisualRoutinesStateNode { public: CalcDest() : VisualRoutinesStateNode("CalcDest") {} void DoStart() { VisualRoutinesStateNode::DoStart(); camSkS.clear(); camShS.clear(); const color_index pink_index = ProjectInterface::getColorIndex("pink"); NEW_SHAPEVEC(pinkblobs, BlobData, getBlobsFromRegionGenerator(pink_index,30,BlobData::groundplane,1)); if ( pinkblobs.size() == 0 ) { cout << "CalcDest: no pink blobs" << endl; DoStop(); return; } Shape cambone = pinkblobs[0];; NEW_SKETCH(pinkrend,bool,cambone->getRendering()); Region bone_reg(camSkS); bone_reg.addIndices(pinkrend); const AngPi cam_orient = bone_reg.findPrincipalAxisOrientation(); cout << "CalcDest: bone orientation in cam space = " << float(cam_orient)*180/M_PI << " deg" << endl; if ( cam_orient > M_PI/2 ) { NEW_SHAPE(pt1, PointData, new PointData(camShS, cambone->bottomLeft)); NEW_SHAPE(pt2, PointData, new PointData(camShS, cambone->topRight)); } else { NEW_SHAPE(pt1, PointData, new PointData(camShS, cambone->topLeft)); NEW_SHAPE(pt2, PointData, new PointData(camShS, cambone->bottomRight)); } groundShS.clear(); projectToGround(); localShS.clear(); localShS.importShapes(groundShS); CALC_ORIENT float const dx = dist * cos(perp_heading); float const dy = dist * sin(perp_heading); Point destpoint = midpt - Point(dx,dy,0); NEW_SHAPE(dest,PointData,new PointData(localShS, destpoint)); const TargetAction a = ( fabs(destpoint.coordX()-dist) > 30 || fabs(destpoint.coordY()) > 60 || fabs(adist) > 0.75 ) ? approach : acquire; erouter->postEvent(DataEvent(a,EventBase::stateSignalEGID,(unsigned int)this,EventBase::statusETID)); } }; //**************** ApproachTarget **************** class ApproachTarget : public WalkEngineNode, public VRmixin { public: ApproachTarget() : WalkEngineNode("ApproachTarget",0,0,0) {} void DoStart() { WalkEngineNode::DoStart(); GET_SHAPE(dest,PointData,localShS); if ( ! dest.isValid() ) { cout << "ApproachTarget couldn't find 'dest' in localShS" << endl; postCompletionEvent(); return; } Point const destpoint = dest->getCentroid(); CALC_ORIENT float dx=0, dy=0, da=0; if ( destpoint.coordX() > dist ) dx = min(50.f,destpoint.coordX()-dist); else if ( destpoint.coordX() < dist-50.f ) dx = max(-50.f,dist-destpoint.coordX()); if ( destpoint.coordX() < 400 ) if ( destpoint.coordY() > 30.f) dy = min(destpoint.coordY()/2,30.f); else if ( destpoint.coordY() < -5) dy = max(destpoint.coordY()/2,-30.f); if ( fabs(destpoint.coordX()-dist) < 100 ) da = max(-0.2f, min(0.2f, float(adist)/4)); cout << "Approach: dx = " << dx << " dy = " << dy << " da = " << float(da)*180/M_PI << endl; getMC()->setSlowMo(0.5); getMC()->setTargetDisplacement(dx,dy,da,2); } }; //**************** FindCone **************** class FindCone : public VisualRoutinesStateNode { public: FindCone() : VisualRoutinesStateNode("FindCone"), head_mc(), head_id(MotionManager::invalid_MC_ID), gaze_index(0) {} void DoStart() { cout << "FindCone starting." << endl; VisualRoutinesStateNode::DoStart(); head_id = motman->addPersistentMotion(head_mc); erouter->addListener(this,EventBase::motmanEGID,head_id,EventBase::statusETID); moveToNextGazePoint(); } void DoStop() { motman->removeMotion(head_id); VisualRoutinesStateNode::DoStop(); } void processEvent(const EventBase &event) { if ( event.getGeneratorID() == EventBase::motmanEGID ) { erouter->addTimer(this,1,1000); return; } // event was a timer expiration: ready to take a picture now localShS.clear(); int const orange_index = ProjectInterface::getColorIndex("orange"); NEW_SHAPEVEC(oblobs,BlobData,getBlobsFromRegionGenerator(orange_index,200,BlobData::groundplane,1)); if ( oblobs.size() == 0 ) moveToNextGazePoint(); else postCompletionEvent(); } void moveToNextGazePoint() { MMAccessor(head_id)->setJoints(0,gaze_points[gaze_index],0); // cout << "FindCone gazing at " << gaze_points[gaze_index]*180/M_PI << endl; if ( gaze_points[++gaze_index] == 999 ) gaze_index = 0; } private: SharedObject head_mc; MotionManager::MC_ID head_id; int gaze_index; static float const gaze_points[]; }; //**************** PushToCone **************** class PushToCone : public VisualRoutinesStateNode { public: PushToCone() : VisualRoutinesStateNode("PushToCone"), head_mc(), head_id(MotionManager::invalid_MC_ID), walk_mc(), walk_id(MotionManager::invalid_MC_ID) {} void DoStart() { VisualRoutinesStateNode::DoStart(); head_mc->setJoints(0,state->outputs[HeadOffset+PanOffset],0); head_id = motman->addPersistentMotion(head_mc); walk_mc->LoadFile("bone/grasp.prm"); walk_mc->setSlowMo(0.5); walk_id = motman->addPersistentMotion(walk_mc); erouter->addTimer(this,1,500,true); } void DoStop() { motman->removeMotion(walk_id); motman->removeMotion(head_id); VisualRoutinesStateNode::DoStop(); } void processEvent(const EventBase&) { camShS.clear(); int const orange_index = ProjectInterface::getColorIndex("orange"); NEW_SHAPEVEC(oblobs,BlobData,getBlobsFromRegionGenerator(orange_index,200,BlobData::groundplane,1)); if ( oblobs.size() == 0 ) return; Point opoint = oblobs[0]->getCentroid(); // cout << "Orange blob at " << opoint <outputs[HeadOffset+PanOffset]; double const head_move = (camSkS.getWidth()/2 - opoint.coordX()) / camSkS.getWidth() * CameraFOV; // cout << "head_pan_angle = " << head_pan_angle*180/M_PI // << " head_move = " << head_move*180/M_PI << endl; double new_pan = head_pan_angle + head_move; MMAccessor(head_id)->setJoints(0,new_pan,0); MMAccessor(walk_id)->setTargetVelocity(80,0,new_pan/2); } private: SharedObject head_mc; MotionManager::MC_ID head_id; SharedObject walk_mc; MotionManager::MC_ID walk_id; }; //**************** GraspDemo **************** class GraspDemo : public VisualRoutinesStateNode { public: GraspDemo() : VisualRoutinesStateNode("GraspDemo") {} void setup() { #statemachine start: StateNode == multistart:NullTrans ==> TrackBone() == ftrans:CompletionTrans($,1) ==> FindCone() == CompletionTrans ==> PushToCone() multistart ==> calcdest: CalcDest() == SignalTrans($,approach) ==> ApproachTarget() == CompletionTrans ==> StateNode == TimeOutTrans($,500) ==> calcdest calcdest == SignalTrans($,acquire) ==> TinyMotionSequenceNode("$","bone/acquire.mot") == CompletionTrans ==> WalkEngineNode() [getMC()->LoadFile("bone/acquire.prm"); getMC()->setSlowMo(0.5); setDisplacement(175, 0, 0, 5); ] == CompletionTrans ==> TinyMotionSequenceNode("$","bone/grasp.mot") == ftrans #endstatemachine startnode = start; } void DoStart() { cout << "GraspDemo starting up" << endl; VisualRoutinesStateNode::DoStart(); erouter->addListener(this,EventBase::textmsgEGID); } GraspDemo(const GraspDemo&); //!< do not call GraspDemo& operator=(const GraspDemo&); //!< do not call }; #endif