0

I'm writing a method to send continued directions to a dobot. Code is C++:

bool moveBlockManually(tf2::Vector3 location, double rotation)
{
    arm.moveToPositionWithLBlocking(location, rotation);
    ros::Duration(1).sleep();

    double new_location_x = location.x();
    double new_location_y = location.y();
    double new_location_z = location.z();

    tf2::Vector3 nextPosition = tf2::Vector3(new_location_x,new_location_y, new_location_z);

    string direction;
    while(direction.compare("release") != 0){
        cout << "Please enter a direction: ";
        cin >> direction;
        cout <<"you entered : " << direction << " \n";

        if(direction.compare("up") == 0){
            cout <<"moving up: " << " \n";
            nextPosition.setZ(new_location_z + 5.0);
        }else if(direction.compare("down") == 0){
            cout <<"moving down: " << " \n";
            nextPosition.setZ(new_location_z - 5.0);
        }
        arm.moveArmToPosition(nextPosition, 0);
    }
    return true;
}

but when calling this method, I enter "up" in command line, the robot move up, which is what I want, and ask for next direction. If I enter "up" again, nothing happens? Have someone an idea what I'm doing wrong?

sid
  • 1
  • 1
  • Input from `std::cin` will always be blocking. You need to go to a lower level, the operating system level, to be able to *poll* for possible input from standard input. There are higher-level libraries that could help on some operating systems (like ncurses on POSIX systems). – Some programmer dude Oct 10 '19 at 13:04

1 Answers1

0

In ROS, the main paradigm in a node is to have callbacks that get input data, store the data in a global variable, and then perform a computation over all the (most recent) data, either in a timer or as a callback to the most critical input. In your case, you want a timer callback that continuously updates the arm, moving it to the global variable nextPosition, and adjust the value nextPosition based off of the direction.

std::string direction = "";
tf2::Vector3 nextPosition;
void timer_callback(const ros::TimerEvent&);
void cin_callback(const ros::TimerEvent&);
int main(){
...
pnh->param("nextPositionX",nextPosition.x) // However
ros::Timer timer = nh->createTimer(ros::Duration(0.1), timer_callback);
ros::Timer cin_timer = nh->createTimer(ros::Duration(0.1), cin_callback);
}
void timer_callback(const ros::TimerEvent&){
  if (!direction.compare("release") == 0){
    if(direction != "" && direction.compare("up")){ 
      // Change nextPosition
      direction = "";
    }else if(direction != "" && direction.compare("down")){
      // Change nextPosition
      direction = "";
    }
    arm.moveArmToPosition(nextPosition, 0);
  }
}
void cin_callback(const ros::TimerEvent&){
  // Cout your msgs
  // Try a non-blocking read of data
  // update direction with data
}

To do non-blocking IO, there are several native ways. A classic C way is to use select (example) or another C++ way is to use future (example). There's several ways, but remember that using callbacks/timers in ROS is already threaded (or non-blocking) in each.

JWCS
  • 1,120
  • 1
  • 7
  • 17