void laserRequest_and_odom(ArServerClient *client, ArNetPacket *packet) { robot.lock(); ArNetPacket sending; sending.empty(); ArLaser* laser = robot.findLaser(1); if(!laser){ printf("Could not connect to Laser... exiting\n"); Aria::exit(1);} laser->lockDevice(); const std::list<ArSensorReading*> *sensorReadings = laser->getRawReadings(); // see ArRangeDevice interface doc sending.byte4ToBuf((ArTypes::Byte4)(sensorReadings->size())); for (std::list<ArSensorReading*>::const_iterator it2= sensorReadings->begin(); it2 != sensorReadings->end(); ++it2){ ArSensorReading* laserRead =*it2; sending.byte4ToBuf((ArTypes::Byte4)(laserRead->getRange())); //printf("%i,%i:",laserRead->getRange(),laserRead->getIgnoreThisReading()); } sending.byte4ToBuf((ArTypes::Byte4)(robot.getX())); sending.byte4ToBuf((ArTypes::Byte4)(robot.getY())); sending.byte4ToBuf((ArTypes::Byte4)(robot.getTh())); sending.byte4ToBuf((ArTypes::Byte4)(robot.getVel())); sending.byte4ToBuf((ArTypes::Byte4)(robot.getRotVel())); //printf("%1f,%1f,%1f\n",robot.getX(),robot.getY(),robot.getTh()); laser->unlockDevice(); robot.unlock(); sending.finalizePacket(); //sending.printHex(); client->sendPacketTcp(&sending); }
void manualControlHandler(){ if(firstCall){ firstCall=false; showMenu(); } if(keyPressedBefore && !driver->estaEjecutando()){ keyPressedBefore=false; showMenu(); } if(mrpt::system::os::kbhit() ){ char c = mrpt::system::os::getch(); keyPressedBefore=true; switch(c){ case '\033': c=mrpt::system::os::getch(); // skip the [ cout << "Siguiente caracter" << (int)c << endl; double v; switch(mrpt::system::os::getch()) { // the real value case 'A': // code for arrow up v=robot->getVel(); robot->setVel(v+50); break; case 'B': // code for arrow down v=robot->getVel(); robot->setVel(v-50); break; case 'C': // code for arrow right v=robot->getRotVel(); robot->setRotVel(v-5); break; case 'D': // code for arrow left v=robot->getRotVel(); robot->setRotVel(v+5); break; } break; case ' ': robot->stop(); break; case 'x': //Aria::shutdown(); driver->stopRunning(); robot->stopRunning(); break; case 'c': guardarContinuo(); break; case 'p': start(); break; case 'g': guardar(); break; case 'w': guardarTrayectoria(); break; case 't': testParado(); break; case 's': stop(); break; } } }
int main(int argc, char **argv) { Aria::init(); ArRobot robot; ArArgumentParser parser(&argc, argv); parser.loadDefaultArguments(); ArLog::log(ArLog::Terse, "WARNING: this program does no sensing or avoiding of obstacles, the robot WILL collide with any objects in the way! Make sure the robot has approximately 3 meters of free space on all sides."); // ArRobotConnector connects to the robot, get some initial data from it such as type and name, // and then loads parameter files for this robot. ArRobotConnector robotConnector(&parser, &robot); if(!robotConnector.connectRobot()) { ArLog::log(ArLog::Terse, "simpleMotionCommands: Could not connect to the robot."); if(parser.checkHelpAndWarnUnparsed()) { Aria::logOptions(); Aria::exit(1); return 1; } } if (!Aria::parseArgs()) { Aria::logOptions(); Aria::exit(1); return 1; } ArLog::log(ArLog::Normal, "simpleMotionCommands: Connected."); // Start the robot processing cycle running in the background. // True parameter means that if the connection is lost, then the // run loop ends. robot.runAsync(true); // Print out some data from the SIP. // We must "lock" the ArRobot object // before calling its methods, and "unlock" when done, to prevent conflicts // with the background thread started by the call to robot.runAsync() above. // See the section on threading in the manual for more about this. // Make sure you unlock before any sleep() call or any other code that will // take some time; if the robot remains locked during that time, then // ArRobot's background thread will be blocked and unable to communicate with // the robot, call tasks, etc. robot.lock(); ArLog::log(ArLog::Normal, "simpleMotionCommands: Pose=(%.2f,%.2f,%.2f), Trans. Vel=%.2f, Rot. Vel=%.2f, Battery=%.2fV", robot.getX(), robot.getY(), robot.getTh(), robot.getVel(), robot.getRotVel(), robot.getBatteryVoltage()); robot.unlock(); // Sleep for 3 seconds. ArLog::log(ArLog::Normal, "simpleMotionCommands: Will start driving in 3 seconds..."); ArUtil::sleep(3000); // Set forward velocity to 50 mm/s ArLog::log(ArLog::Normal, "simpleMotionCommands: Driving forward at 250 mm/s for 5 sec..."); robot.lock(); robot.enableMotors(); robot.setVel(250); robot.unlock(); ArUtil::sleep(5000); ArLog::log(ArLog::Normal, "simpleMotionCommands: Stopping."); robot.lock(); robot.stop(); robot.unlock(); ArUtil::sleep(1000); ArLog::log(ArLog::Normal, "simpleMotionCommands: Rotating at 10 deg/s for 5 sec..."); robot.lock(); robot.setRotVel(10); robot.unlock(); ArUtil::sleep(5000); ArLog::log(ArLog::Normal, "simpleMotionCommands: Rotating at -10 deg/s for 10 sec..."); robot.lock(); robot.setRotVel(-10); robot.unlock(); ArUtil::sleep(10000); ArLog::log(ArLog::Normal, "simpleMotionCommands: Driving forward at 150 mm/s for 5 sec..."); robot.lock(); robot.setRotVel(0); robot.setVel(150); robot.unlock(); ArUtil::sleep(5000); ArLog::log(ArLog::Normal, "simpleMotionCommands: Stopping."); robot.lock(); robot.stop(); robot.unlock(); ArUtil::sleep(1000); // Other motion command functions include move(), setHeading(), // setDeltaHeading(). You can also adjust acceleration and deceleration // values used by the robot with setAccel(), setDecel(), setRotAccel(), // setRotDecel(). See the ArRobot class documentation for more. robot.lock(); ArLog::log(ArLog::Normal, "simpleMotionCommands: Pose=(%.2f,%.2f,%.2f), Trans. Vel=%.2f, Rot. Vel=%.2f, Battery=%.2fV", robot.getX(), robot.getY(), robot.getTh(), robot.getVel(), robot.getRotVel(), robot.getBatteryVoltage()); robot.unlock(); ArLog::log(ArLog::Normal, "simpleMotionCommands: Ending robot thread..."); robot.stopRunning(); // wait for the thread to stop robot.waitForRunExit(); // exit ArLog::log(ArLog::Normal, "simpleMotionCommands: Exiting."); Aria::exit(0); return 0; }
void RosAriaNode::publish() { // Note, this is called via SensorInterpTask callback (myPublishCB, named "ROSPublishingTask"). ArRobot object 'robot' sholud not be locked or unlocked. pos = robot->getPose(); tf::poseTFToMsg(tf::Transform(tf::createQuaternionFromYaw(pos.getTh()*M_PI/180), tf::Vector3(pos.getX()/1000, pos.getY()/1000, 0)), position.pose.pose); //Aria returns pose in mm. position.twist.twist.linear.x = robot->getVel()/1000; //Aria returns velocity in mm/s. position.twist.twist.linear.y = robot->getLatVel()/1000.0; position.twist.twist.angular.z = robot->getRotVel()*M_PI/180; position.header.frame_id = frame_id_odom; position.child_frame_id = frame_id_base_link; position.header.stamp = ros::Time::now(); pose_pub.publish(position); ROS_DEBUG("RosAria: publish: (time %f) pose x: %f, y: %f, angle: %f; linear vel x: %f, y: %f; angular vel z: %f", position.header.stamp.toSec(), (double)position.pose.pose.position.x, (double)position.pose.pose.position.y, (double)position.pose.pose.orientation.w, (double) position.twist.twist.linear.x, (double) position.twist.twist.linear.y, (double) position.twist.twist.angular.z ); // publishing transform odom->base_link odom_trans.header.stamp = ros::Time::now(); odom_trans.header.frame_id = frame_id_odom; odom_trans.child_frame_id = frame_id_base_link; odom_trans.transform.translation.x = pos.getX()/1000; odom_trans.transform.translation.y = pos.getY()/1000; odom_trans.transform.translation.z = 0.0; odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(pos.getTh()*M_PI/180); odom_broadcaster.sendTransform(odom_trans); // getStallValue returns 2 bytes with stall bit and bumper bits, packed as (00 00 FrontBumpers RearBumpers) int stall = robot->getStallValue(); unsigned char front_bumpers = (unsigned char)(stall >> 8); unsigned char rear_bumpers = (unsigned char)(stall); bumpers.header.frame_id = frame_id_bumper; bumpers.header.stamp = ros::Time::now(); std::stringstream bumper_info(std::stringstream::out); // Bit 0 is for stall, next bits are for bumpers (leftmost is LSB) for (unsigned int i=0; i<robot->getNumFrontBumpers(); i++) { bumpers.front_bumpers[i] = (front_bumpers & (1 << (i+1))) == 0 ? 0 : 1; bumper_info << " " << (front_bumpers & (1 << (i+1))); } ROS_DEBUG("RosAria: Front bumpers:%s", bumper_info.str().c_str()); bumper_info.str(""); // Rear bumpers have reverse order (rightmost is LSB) unsigned int numRearBumpers = robot->getNumRearBumpers(); for (unsigned int i=0; i<numRearBumpers; i++) { bumpers.rear_bumpers[i] = (rear_bumpers & (1 << (numRearBumpers-i))) == 0 ? 0 : 1; bumper_info << " " << (rear_bumpers & (1 << (numRearBumpers-i))); } ROS_DEBUG("RosAria: Rear bumpers:%s", bumper_info.str().c_str()); bumpers_pub.publish(bumpers); //Publish battery information // TODO: Decide if BatteryVoltageNow (normalized to (0,12)V) is a better option std_msgs::Float64 batteryVoltage; batteryVoltage.data = robot->getRealBatteryVoltageNow(); voltage_pub.publish(batteryVoltage); if(robot->haveStateOfCharge()) { std_msgs::Float32 soc; soc.data = robot->getStateOfCharge()/100.0; state_of_charge_pub.publish(soc); } // publish recharge state if changed char s = robot->getChargeState(); if(s != recharge_state.data) { ROS_INFO("RosAria: publishing new recharge state %d.", s); recharge_state.data = s; recharge_state_pub.publish(recharge_state); } // publish motors state if changed bool e = robot->areMotorsEnabled(); if(e != motors_state.data || !published_motors_state) { ROS_INFO("RosAria: publishing new motors state %d.", e); motors_state.data = e; motors_state_pub.publish(motors_state); published_motors_state = true; } // Publish sonar information, if enabled. if (use_sonar) { sensor_msgs::PointCloud cloud; //sonar readings. cloud.header.stamp = position.header.stamp; //copy time. // sonar sensors relative to base_link cloud.header.frame_id = frame_id_sonar; // Log debugging info std::stringstream sonar_debug_info; sonar_debug_info << "Sonar readings: "; for (int i = 0; i < robot->getNumSonar(); i++) { ArSensorReading* reading = NULL; reading = robot->getSonarReading(i); if(!reading) { ROS_WARN("RosAria: Did not receive a sonar reading."); continue; } // getRange() will return an integer between 0 and 5000 (5m) sonar_debug_info << reading->getRange() << " "; // local (x,y). Appears to be from the centre of the robot, since values may // exceed 5000. This is good, since it means we only need 1 transform. // x & y seem to be swapped though, i.e. if the robot is driving north // x is north/south and y is east/west. // //ArPose sensor = reading->getSensorPosition(); //position of sensor. // sonar_debug_info << "(" << reading->getLocalX() // << ", " << reading->getLocalY() // << ") from (" << sensor.getX() << ", " // << sensor.getY() << ") ;; " ; //add sonar readings (robot-local coordinate frame) to cloud geometry_msgs::Point32 p; p.x = reading->getLocalX() / 1000.0; p.y = reading->getLocalY() / 1000.0; p.z = 0.0; cloud.points.push_back(p); } ROS_DEBUG_STREAM(sonar_debug_info.str()); sonar_pub.publish(cloud); } }
int main(int argc, char **argv) { std::string str; int ret; ArTime start; // connection to the robot ArSerialConnection con; // the robot ArRobot robot; // the connection handler from above ConnHandler ch(&robot); // init area with a dedicated signal handling thread Aria::init(Aria::SIGHANDLE_THREAD); // open the connection with the defaults, exit if failed if ((ret = con.open()) != 0) { str = con.getOpenMessage(ret); printf("Open failed: %s\n", str.c_str()); Aria::shutdown(); return 1; } // set the robots connection robot.setDeviceConnection(&con); // try to connect, if we fail, the connection handler should bail if (!robot.blockingConnect()) { // this should have been taken care of by the connection handler // but just in case printf( "asyncConnect failed because robot is not running in its own thread.\n"); Aria::shutdown(); return 1; } // run the robot in its own thread, so it gets and processes packets and such robot.runAsync(false); // just a big long set of printfs, direct motion commands and sleeps, // it should be self-explanatory printf("Telling the robot to go 300 mm for 5 seconds\n"); robot.lock(); robot.setVel(500); robot.unlock(); start.setToNow(); while (1) { robot.lock(); if (start.mSecSince() > 5000) { robot.unlock(); break; } printf("Trans: %10g Rot: %10g\n", robot.getVel(), robot.getRotVel()); robot.unlock(); ArUtil::sleep(100); } printf("Telling the robot to turn at 50 deg/sec for 10 seconds\n"); robot.lock(); robot.setVel(0); robot.setRotVel(50); robot.unlock(); start.setToNow(); while (1) { robot.lock(); if (start.mSecSince() > 10000) { robot.unlock(); break; } printf("Trans: %10g Rot: %10g\n", robot.getVel(), robot.getRotVel()); robot.unlock(); ArUtil::sleep(100); } printf("Telling the robot to turn at 100 deg/sec for 10 seconds\n"); robot.lock(); robot.setVel(0); robot.setRotVel(100); robot.unlock(); start.setToNow(); while (1) { robot.lock(); if (start.mSecSince() > 10000) { robot.unlock(); break; } printf("Trans: %10g Rot: %10g\n", robot.getVel(), robot.getRotVel()); robot.unlock(); ArUtil::sleep(100); } printf("Done with tests, exiting\n"); robot.disconnect(); // shutdown and ge tout Aria::shutdown(); return 0; }
void RosAriaNode::publish() { // Note, this is called via SensorInterpTask callback (myPublishCB, named "ROSPublishingTask"). ArRobot object 'robot' sholud not be locked or unlocked. pos = robot->getPose(); tf::poseTFToMsg(tf::Transform(tf::createQuaternionFromYaw(pos.getTh()*M_PI/180), tf::Vector3(pos.getX()/1000, pos.getY()/1000, 0)), position.pose.pose); //Aria returns pose in mm. position.twist.twist.linear.x = robot->getVel()/1000; //Aria returns velocity in mm/s. position.twist.twist.angular.z = robot->getRotVel()*M_PI/180; position.header.frame_id = frame_id_odom; position.child_frame_id = frame_id_base_link; position.header.stamp = ros::Time::now(); pose_pub.publish(position); ROS_DEBUG("RosAria: publish: (time %f) pose x: %f, y: %f, angle: %f; linear vel x: %f, y: %f; angular vel z: %f", position.header.stamp.toSec(), (double)position.pose.pose.position.x, (double)position.pose.pose.position.y, (double)position.pose.pose.orientation.w, (double) position.twist.twist.linear.x, (double) position.twist.twist.linear.y, (double) position.twist.twist.angular.z ); // publishing transform odom->base_link odom_trans.header.stamp = ros::Time::now(); odom_trans.header.frame_id = frame_id_odom; odom_trans.child_frame_id = frame_id_base_link; odom_trans.transform.translation.x = pos.getX()/1000; odom_trans.transform.translation.y = pos.getY()/1000; odom_trans.transform.translation.z = 0.0; odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(pos.getTh()*M_PI/180); odom_broadcaster.sendTransform(odom_trans); // getStallValue returns 2 bytes with stall bit and bumper bits, packed as (00 00 FrontBumpers RearBumpers) int stall = robot->getStallValue(); unsigned char front_bumpers = (unsigned char)(stall >> 8); unsigned char rear_bumpers = (unsigned char)(stall); bumpers.header.frame_id = frame_id_bumper; bumpers.header.stamp = ros::Time::now(); std::stringstream bumper_info(std::stringstream::out); // Bit 0 is for stall, next bits are for bumpers (leftmost is LSB) for (unsigned int i=0; i<robot->getNumFrontBumpers(); i++) { bumpers.front_bumpers[i] = (front_bumpers & (1 << (i+1))) == 0 ? 0 : 1; bumper_info << " " << (front_bumpers & (1 << (i+1))); } ROS_DEBUG("RosAria: Front bumpers:%s", bumper_info.str().c_str()); bumper_info.str(""); // Rear bumpers have reverse order (rightmost is LSB) unsigned int numRearBumpers = robot->getNumRearBumpers(); for (unsigned int i=0; i<numRearBumpers; i++) { bumpers.rear_bumpers[i] = (rear_bumpers & (1 << (numRearBumpers-i))) == 0 ? 0 : 1; bumper_info << " " << (rear_bumpers & (1 << (numRearBumpers-i))); } ROS_DEBUG("RosAria: Rear bumpers:%s", bumper_info.str().c_str()); bumpers_pub.publish(bumpers); //Publish battery information // TODO: Decide if BatteryVoltageNow (normalized to (0,12)V) is a better option std_msgs::Float64 batteryVoltage; batteryVoltage.data = robot->getRealBatteryVoltageNow(); voltage_pub.publish(batteryVoltage); if(robot->haveStateOfCharge()) { std_msgs::Float32 soc; soc.data = robot->getStateOfCharge()/100.0; state_of_charge_pub.publish(soc); } // publish recharge state if changed char s = robot->getChargeState(); if(s != recharge_state.data) { ROS_INFO("RosAria: publishing new recharge state %d.", s); recharge_state.data = s; recharge_state_pub.publish(recharge_state); } // publish motors state if changed bool e = robot->areMotorsEnabled(); if(e != motors_state.data || !published_motors_state) { ROS_INFO("RosAria: publishing new motors state %d.", e); motors_state.data = e; motors_state_pub.publish(motors_state); published_motors_state = true; } if (robot->areSonarsEnabled()) { int i = 0; int j = 0; ArSensorReading* reading = NULL; if(sonars__crossed_the_streams) { i = 8; j = 8; } for(; i < 16; i++) { ranges.data[i].header.stamp = ros::Time::now(); ArSensorReading* _reading = NULL; _reading = robot->getSonarReading(i-j); ranges.data[i].range = _reading->getRange() / 1000.0f; range_pub[i].publish(ranges.data[i]); } ranges.header.stamp = ros::Time::now(); combined_range_pub.publish(ranges); } }