// the important function
void KeyPTU::drive(void)
{
  // if the PTU isn't initialized, initialize it here... it has to be 
  // done here instead of above because it needs to be done when the 
  // robot is connected
  if (!myPTUInitRequested && !myPTU.isInitted() && myRobot->isConnected())
  {
    printf("\nWaiting for Camera to Initialize\n");
    myAbsolute = true;
    myPTUInitRequested = true;
    myPTU.init();
  }

  // if the camera hasn't initialized yet, then just return
  if (myPTUInitRequested && !myPTU.isInitted())
  {
    return;
  }

  if (myPTUInitRequested && myPTU.isInitted())
  {
    myPTUInitRequested = false;
    myPanSlew = myPTU.getPanSlew();
    myTiltSlew = myPTU.getTiltSlew();
    printf("Done.\n");
    question();
  }

  if (myExerciseTime.secSince() > 5 && myExercise)
  {
    int pan,tilt;

    if (ArMath::random()%2)
      pan = ArMath::random()%((int)myPTU.getMaxPosPan());
    else
      pan = -ArMath::random()%((int)myPTU.getMaxNegPan());

    if (ArMath::random()%2)
      tilt = ArMath::random()%((int)myPTU.getMaxPosTilt());
    else
      tilt = -ArMath::random()%((int)myPTU.getMaxNegTilt());

    myPTU.panTilt(pan, tilt);
    //printf("** %d\n", myRobot->getEstop());
    //printf("--> %x\n", myRobot->getFlags());
    myExerciseTime.setToNow();
  }

}
Exemple #2
0
int main(int argc, char** argv)
{
  Aria::init();
  ArLog::init(ArLog::StdErr, ArLog::Normal);

  ArArgumentParser argParser(&argc, argv);
  argParser.loadDefaultArguments();
  ArSimpleConnector connector(&argParser);
  ArGPSConnector gpsConnector(&argParser);

  if(!Aria::parseArgs() || !argParser.checkHelpAndWarnUnparsed())
  {
    Aria::logOptions();
    ArLog::log(ArLog::Terse, "gpsExample options:\n  -printTable   Print data to standard output in regular columns rather than a refreshing terminal display, and print more digits of precision");
    return 1;
  }

  // Try connecting to robot 
  ArRobot robot;
  if(!connector.connectRobot(&robot))
  {
    ArLog::log(ArLog::Terse, "gpsExample: Warning: Could not connect to robot.  Will not be able to switch GPS power on, or load GPS options from this robot's parameter file.");
  }
  else
  {
    ArLog::log(ArLog::Normal, "gpsExample: Connected to robot.");
    robot.runAsync(true);
  }

  // check command line arguments for -printTable
  bool printTable = argParser.checkArgument("printTable");

  // On the Seekur, power to the GPS receiver is switched on by this command.
  // (A third argument of 0 would turn it off). On other robots this command is
  // ignored.
  robot.com2Bytes(116, 6, 1);

  // Try connecting to a GPS. We pass the robot pointetr to the connector so it
  // can check the robot parameters for this robot type for default values for
  // GPS device connection information (receiver type, serial port, etc.)
  ArLog::log(ArLog::Normal, "gpsExample: Connecting to GPS, it may take a few seconds...");
  ArGPS *gps = gpsConnector.createGPS(&robot);
  if(!gps || !gps->connect())
  {
    ArLog::log(ArLog::Terse, "gpsExample: Error connecting to GPS device.  Try -gpsType, -gpsPort, and/or -gpsBaud command-line arguments. Use -help for help.");
    return -1;
  }


  ArLog::log(ArLog::Normal, "gpsExample: Reading data...");
  ArTime lastReadTime;
  if(printTable)
    gps->printDataLabelsHeader();
  while(true)
  {
    int r = gps->read();
    if(r & ArGPS::ReadError)
    {
      ArLog::log(ArLog::Terse, "gpsExample: Warning: error reading GPS data.");
      ArUtil::sleep(1000);
      continue;
    }


    if(r & ArGPS::ReadUpdated)
    {
      if(printTable)
      {
        gps->printData(false);
        printf("\n");
      }
      else
      {
        gps->printData();
        printf("\r");
      }
      fflush(stdout);
      ArUtil::sleep(500);
      lastReadTime.setToNow();
      continue;
    } else {
      if(lastReadTime.secSince() >= 5) {
        ArLog::log(ArLog::Terse, "gpsExample: Warning: haven't recieved any data from GPS for more than 5 seconds!");
      }
      ArUtil::sleep(1000);
      continue;
    }

  }
  return 0;
}
void *KinectArVideoServer::runThread(void*)
{
  // TODO might need to move initialization to separate function

  /* Open Kinect */

/*
  int ndevs = freenect2.enumerateDevices();
  printf("KinectArVideoServer: %d devices\n", ndevs);
  std::string serial = freenect2.getDefaultDeviceSerialNumber();
  printf("KinectArVideoServer: device serial number is %s\n", serial.c_str());
*/

  freenect_dev = freenect2.openDefaultDevice();

  if(!freenect_dev)
  {
    std::cout << "KinectArVideoServer: no kinect2 device connected or failure opening the default one!" << std::endl;
    return 0;
  }

  shutdown = false;


  /* Set up libfreenect listeners, start capturing  */

  //libfreenect2::SyncMultiFrameListener listener(libfreenect2::Frame::Color | libfreenect2::Frame::Ir | libfreenect2::Frame::Depth);
  libfreenect2::SyncMultiFrameListener listener(libfreenect2::Frame::Color | libfreenect2::Frame::Depth);
  libfreenect2::FrameMap frames;

  freenect_dev->setColorFrameListener(&listener);
  freenect_dev->setIrAndDepthFrameListener(&listener);

  assert(freenect_dev);
  if(! freenect_dev->start() )
  {
    std::cout << "KinectArVideoServer: Error starting stream from kinect!" << std::endl;
    return NULL;
  }

  std::cout << "kinect device serial: " << freenect_dev->getSerialNumber() << std::endl;
  std::cout << "kinect device firmware: " << freenect_dev->getFirmwareVersion() << std::endl;

  // TODO set up registration in libfreenect2

  ArVideoOpenCV kinectDepthSource("Kinect_Depth|libfreenect2|OpenCV");
  ArVideo::createVideoServer(server, &kinectDepthSource, "Kinect_Depth|libfreenect2|OpenCV", "freenect2|Depth|OpenCV");

  ArVideoOpenCV kinectRGBSource("Kinect_RGB|libfreenect2|OpenCV");
  ArVideo::createVideoServer(server, &kinectRGBSource, "Kinect_RGB|libfreenect2|OpenCV", "freenect2|RGB|OpenCV");

//  ArVideoOpenCV kinectThreshSource("Kinect_Depth|libfreenect2|OpenCV_threshold");
//  ArVideo::createVideoServer(&server, &kinectThreshSource, "Kinect_Depth|libfreenect2|OpenCV_threshold", "Kinect depth data with basic threshold applied");


  /* Main loop, capture images from kinect, display, copy to ArVideo sources */

  bool first = true;
  cv::Mat rgbm_small(resize_to_width, resize_to_height, CV_8UC3);
  cv::Mat depthm_small(resize_to_width, resize_to_height, CV_8UC3);
  cv::Mat rgbm_flip(resize_to_width, resize_to_height, CV_8UC3);
  cv::Mat depthm_flip(resize_to_width, resize_to_height, CV_8UC3);

  while(!shutdown)
  {
//    std::cout << "." << std::flush;
    ArTime t;
    listener.waitForNewFrame(frames); //, 30000);
    if(t.secSince() >= 28) 
    {  
      std::cout << "KinectArVideoServer: Warning: took more than 30 seconds to receive a frame from Kinect!" << std::endl;
      //shutdown = true;
      //continue;
    }
    
    
//    printf("%d\n", t.secSince());
    libfreenect2::Frame *rgb = frames[libfreenect2::Frame::Color];
//    libfreenect2::Frame *ir = frames[libfreenect2::Frame::Ir];
    libfreenect2::Frame *depth = frames[libfreenect2::Frame::Depth];

    // todo don't recreate Mat objects each time
    cv::Mat rgbm(rgb->height, rgb->width, CV_8UC4, rgb->data);
    cv::resize (rgbm, rgbm_small, cv::Size(resize_to_width, resize_to_height));
    cv::flip(rgbm_small, rgbm_flip, 1);

    cv::Mat depthm(depth->height, depth->width, CV_32FC1, depth->data);
    cv::resize(depthm, depthm_small, cv::Size(resize_to_width, resize_to_height));
    cv::flip(depthm_small, depthm_flip, 1);


//    cv::Mat depth_thresh(depth->height, depth->width, CV_32FC1, depth->data);
//    cv::threshold(depthm, depth_thresh, 0.4, 1.0, CV_THRESH_BINARY_INV);

//    cv::imshow("rgb", rgbm_small);
//    cv::imshow("ir", cv::Mat(ir->height, ir->width, CV_32FC1, ir->data) / 20000.0f);
//    cv::imshow("depth", depthm / 4500.0f);

    if(!kinectRGBSource.updateVideoDataCopy(rgbm_flip, 1, CV_BGR2RGB))
      std::cout << "KinectArVideoServer: Warning: error copying rgb data to ArVideo source" << std::endl;
    if(!kinectDepthSource.updateVideoDataCopy(depthm_flip/4500.0f, 255,
/*(1/255.0),*/ CV_GRAY2RGB))
      std::cout << "KinectArVideoServer: Warning: error copying depth data to ArVideo source" << std::endl;
//    if(!kinectThreshSource.updateVideoDataCopy(depth_thresh, 255, CV_GRAY2RGB))
//      std::cout << "Warning error copying depth thresholded data to ArVideo source" << std::endl;
    

    listener.release(frames);
    //libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(100));

//    if(first)
//    {
//      first = false;
//      cv::moveWindow("rgb",   90, 85); 
//      cv::moveWindow("depth", 90, 599);
//    }

    //ArUtil::sleep(1);
  }


  close();

  // TODO destroy ArVideo servers created

  return 0;
}
bool ArUrg::internalConnect(void)

{
  bool ret = true;
  char buf[1024];

  ArSerialConnection *serConn = NULL;
  serConn = dynamic_cast<ArSerialConnection *>(myConn);

  bool alreadyAtAutobaud = false;

  // empty the buffer...
  buf[0] = '\0';
  while (readLine(buf, sizeof(buf), 1));

  if (!(ret = sendCommandAndRecvStatus(
		"V", "version request", 
		buf, sizeof(buf), 10000)) || 
      strcasecmp(buf, "0") != 0)      
  {
    // if we didn't get it, try it at what the autobaud rate is
    if (serConn != NULL)
    {
      alreadyAtAutobaud = true;
      serConn->setBaud(atoi(getAutoBaudChoice()));
      ArUtil::sleep(100);

      if (!(ret = sendCommandAndRecvStatus(
		"V", "version request after falling back to autobaudchoice", 
		buf, sizeof(buf), 10000)) || 
	  strcasecmp(buf, "0") != 0)      
      {
	if (ret && strcasecmp(buf, "0") != 0)      
	  ArLog::log(ArLog::Normal, 
		     "%s::blockingConnect: Bad status on version response after falling back to autobaudchoice", 
		     getName());
	return false;
      }
    }
    // if we don't have a serial port, then we can't change the baud,
    // so just fail
    else
    {
      if (ret && strcasecmp(buf, "0") != 0)      
	ArLog::log(ArLog::Normal, 
		   "%s::blockingConnect: Bad status on version response (%s)",
		   getName(), buf);
      return false;
    }
  }

  if (!alreadyAtAutobaud && serConn != NULL)
  {

    // empty the buffer from the last version request
    while (readLine(buf, sizeof(buf), 100));

    // now change the baud...
    sprintf(buf, "S%06d7654321", atoi(getAutoBaudChoice()));
    if (!writeLine(buf))
      return false;

    ArUtil::sleep(100);

    //serConn->setBaud(115200);
    serConn->setBaud(atoi(getAutoBaudChoice()));
    // wait a second for the baud to change...
    ArUtil::sleep(100);

    // empty the buffer from the baud change
    while (readLine(buf, sizeof(buf), 100));

    if (!(ret = sendCommandAndRecvStatus(
		  "V", "version request after switching to autobaudchoice", 
		  buf, sizeof(buf), 10000)) || 
	strcasecmp(buf, "0") != 0)      
    {
      if (ret && strcasecmp(buf, "0") != 0)      
	ArLog::log(ArLog::Normal, 
		   "%s::blockingConnect: Bad status on version response after switching to autobaudchoice", 
		   getName());
      return false;
    }

    ArLog::log(ArLog::Normal, "%s: Switched to %s baud rate",
	       getName(), getAutoBaudChoice());
  }

  while (readLine(buf, sizeof(buf), 10000))
  {
    /// MPL put this in instead of the following because of the
    /// behavior change of readline
    if (strlen(buf) == 0)
      break;

    if (strncasecmp(buf, "VEND:", strlen("VEND:")) == 0)
      myVendor = &buf[5];
    else if (strncasecmp(buf, "PROD:", strlen("PROD:")) == 0)
      myProduct = &buf[5];
    else if (strncasecmp(buf, "FIRM:", strlen("FIRM:")) == 0)
      myFirmwareVersion = &buf[5];
    else if (strncasecmp(buf, "PROT:", strlen("PROT:")) == 0)
      myProtocolVersion = &buf[5];
    else if (strncasecmp(buf, "SERI:", strlen("SERI:")) == 0)
      mySerialNumber = &buf[5];
    else if (strncasecmp(buf, "STAT:", strlen("STAT:")) == 0)
      myStat = &buf[5];
  }

  if (myVendor.empty() || myProduct.empty() || myFirmwareVersion.empty() || 
      myProtocolVersion.empty() || mySerialNumber.empty())
  {
    ArLog::log(ArLog::Normal, 
	       "%s::blockingConnect: Missing information in version response",
	       getName());
    return false;
  }

  log();

  myLogMore = true;
  //  myLogMore = false;
  ArUtil::sleep(100);
  
  
  printf("myRequestString %s\n", myRequestString);


  if (!(ret = sendCommandAndRecvStatus(
		myRequestString, "request distance reading", 
		buf, sizeof(buf), 10000)) || 
      strcasecmp(buf, "0") != 0)
  {
    if (ret && strcasecmp(buf, "0") != 0) 
      ArLog::log(ArLog::Normal, 
	 "%s::blockingConnect: Bad status on distance reading response (%c)",
		 getName(), buf[0]);
    return false;
  }
  
  myLogMore = false;

  ArTime started;
  started.setToNow();
  while (started.secSince() < 10 && readLine(buf, sizeof(buf), 10000))
  {
    if (strlen(buf) == 0)
      return true;
  }

  ArLog::log(ArLog::Normal, "%s::blockingConnect: Did not get distance reading back",
	     getName(), buf[0]);
  return false;
}
bool ArUrg_2_0::internalConnect(void)

{
  bool ret = true;
  char buf[1024];
  

  ArSerialConnection *serConn = NULL;
  serConn = dynamic_cast<ArSerialConnection *>(myConn);

  bool alreadyAtAutobaud = false;



  // empty the buffer...
  /*
  sendCommandAndRecvStatus(
	  "RS", "reset", 
	  buf, sizeof(buf), 1000);
  readLine(buf, sizeof(buf), 1, true, false);

  sendCommandAndRecvStatus(
	  "SCIP2.0", "SCIP 2.0 request", 
	  buf, sizeof(buf), 1000);
  */

  writeLine("RS");
  ArUtil::sleep(100);

  writeLine("SCIP2.0");
  ArUtil::sleep(100);

  ArTime startedFlushing;

  while (readLine(buf, sizeof(buf), 1, true, false) ||
	 startedFlushing.mSecSince() < 1000);

  buf[0] = '\0';

  if (!(ret = sendCommandAndRecvStatus(
		"VV", "version request", 
		buf, sizeof(buf), 10000)) || 
      strcasecmp(buf, "00") != 0)      
  {
    // if we didn't get it and have an autobaud, try it at what the autobaud rate is
    if (serConn != NULL && atoi(getAutoBaudChoice()) > 0)
    {
      alreadyAtAutobaud = true;
      serConn->setBaud(atoi(getAutoBaudChoice()));
      ArUtil::sleep(100);

      writeLine("RS");
      ArUtil::sleep(100);
      
      writeLine("SCIP2.0");
      ArUtil::sleep(100);
      
      startedFlushing.setToNow();
      while (readLine(buf, sizeof(buf), 1, true, false) ||
	     startedFlushing.mSecSince() < 1000);
      
      if (!(ret = sendCommandAndRecvStatus(
		"VV", "version request after falling back to autobaudchoice", 
		buf, sizeof(buf), 10000)) || 
	  strcasecmp(buf, "00") != 0)      
      {
	if (ret && strcasecmp(buf, "00") != 0)      
	  ArLog::log(ArLog::Normal, 
		     "%s::blockingConnect: Bad status on version response after falling back to autobaudchoice", 
		     getName());
	return false;
      }
    }
    // if we don't have a serial port or no autobaud then we can't
    // change the baud, so just fail
    else
    {
      if (ret && strcasecmp(buf, "00") != 0)      
	ArLog::log(ArLog::Normal, 
		   "%s::blockingConnect: Bad status on version response (%s)",
		   getName(), buf);
      return false;
    }
  }

  // if we want to autobaud, then give it a whirl
  if (!alreadyAtAutobaud && serConn != NULL && atoi(getAutoBaudChoice()) > 0)
  {

    // empty the buffer from the last version request
    while (readLine(buf, sizeof(buf), 100, true, false));

    // now change the baud...
    sprintf(buf, "SS%06d", atoi(getAutoBaudChoice()));
    if (!writeLine(buf))
      return false;

    ArUtil::sleep(100);

    //serConn->setBaud(115200);
    serConn->setBaud(atoi(getAutoBaudChoice()));
    // wait a second for the baud to change...
    ArUtil::sleep(100);

    // empty the buffer from the baud change
    while (readLine(buf, sizeof(buf), 100, true, false));
    
    if (!(ret = sendCommandAndRecvStatus(
		  "VV", "version request after switching to autobaudchoice", 
		  buf, sizeof(buf), 10000)) || 
	strcasecmp(buf, "00") != 0)      
    {
      if (ret && strcasecmp(buf, "00") != 0)      
	ArLog::log(ArLog::Normal, 
		   "%s::blockingConnect: Bad status on version response after switching to autobaudchoice", 
		   getName());
      return false;
    }

    ArLog::log(ArLog::Verbose, "%s: Switched to %s baud rate",
	       getName(), getAutoBaudChoice());
  }

  while (readLine(buf, sizeof(buf), 10000, false, true))
  {
    if (strlen(buf) == 0)
      break;

    if (strncasecmp(buf, "VEND:", strlen("VEND:")) == 0)
      myVendor = &buf[5];
    else if (strncasecmp(buf, "PROD:", strlen("PROD:")) == 0)
      myProduct = &buf[5];
    else if (strncasecmp(buf, "FIRM:", strlen("FIRM:")) == 0)
      myFirmwareVersion = &buf[5];
    else if (strncasecmp(buf, "PROT:", strlen("PROT:")) == 0)
      myProtocolVersion = &buf[5];
    else if (strncasecmp(buf, "SERI:", strlen("SERI:")) == 0)
      mySerialNumber = &buf[5];
    else if (strncasecmp(buf, "STAT:", strlen("STAT:")) == 0)
      myStat = &buf[5];
  }

  if (myVendor.empty() || myProduct.empty() || myFirmwareVersion.empty() || 
      myProtocolVersion.empty() || mySerialNumber.empty())
  {
    ArLog::log(ArLog::Normal, 
	       "%s::blockingConnect: Missing information in version response",
	       getName());
    return false;
  }

  if (!(ret = sendCommandAndRecvStatus(
		"PP", "parameter info request", 
		buf, sizeof(buf), 10000)) || 
      strcasecmp(buf, "00") != 0)      
  {
    ArLog::log(ArLog::Normal, 
	       "%s::blockingConnect: Bad response to parameter info request",
	       getName());
    return false;
  }

  while (readLine(buf, sizeof(buf), 10000, false, true))
  {
    if (strlen(buf) == 0)
      break;

    if (strncasecmp(buf, "MODL:", strlen("MODL:")) == 0)
      myModel = &buf[5];
    else if (strncasecmp(buf, "DMIN:", strlen("DMIN:")) == 0)
      myDMin = atoi(&buf[5]);
    else if (strncasecmp(buf, "DMAX:", strlen("DMAX:")) == 0)
      myDMax = atoi(&buf[5]);
    else if (strncasecmp(buf, "ARES:", strlen("ARES:")) == 0)
      myARes = atoi(&buf[5]);
    else if (strncasecmp(buf, "AMIN:", strlen("AMIN:")) == 0)
      myAMin = atoi(&buf[5]);
    else if (strncasecmp(buf, "AMAX:", strlen("AMAX:")) == 0)
      myAMax = atoi(&buf[5]);
    else if (strncasecmp(buf, "AFRT:", strlen("AFRT:")) == 0)
      myAFront = atoi(&buf[5]);
    else if (strncasecmp(buf, "SCAN:", strlen("SCAN:")) == 0)
      myScan = atoi(&buf[5]);
  }

  if (myModel.empty() || myDMin == 0 || myDMax == 0 || myARes == 0 ||
      myAMin == 0 || myAMax == 0 || myAFront == 0 || myScan == 0)
  {
    ArLog::log(ArLog::Normal, 
	       "%s::blockingConnect: Missing information in parameter info response",
	       getName());
    return false;
  }

  myStepSize = 360.0 / myARes;
  myStepFirst = myAFront * myStepSize;
  
  if (myMaxRange > myDMax)
    setMaxRange(myDMax);

  //log();

  setParams(getStartDegrees(), getEndDegrees(), getIncrement(), getFlipped());

  //myLogMore = true;
  //  myLogMore = false;
  ArUtil::sleep(100);
  
  
  //printf("myRequestString %s\n", myRequestString);

  if (!(ret = sendCommandAndRecvStatus(
		myRequestString, "request distance reading", 
		buf, sizeof(buf), 10000)) || 
      strcasecmp(buf, "00") != 0)
  {
    if (ret && strcasecmp(buf, "00") != 0) 
      ArLog::log(ArLog::Normal, 
	 "%s::blockingConnect: Bad status on distance reading response (%s)",
		 getName(), buf);
    return false;
  }
  
  //myLogMore = false;

  ArTime started;
  started.setToNow();
  while (started.secSince() < 10 && 
	 readLine(buf, sizeof(buf), 10000, true, false))
  {
    if (strlen(buf) == 0)
      return true;
  }

  ArLog::log(ArLog::Normal, "%s::blockingConnect: Did not get distance reading back",
	     getName());
  return false;
}
int main(int argc, char **argv)
{
  int ret;
  std::string str;
  ArSerialConnection con;
  ArSickPacket sick;
  ArSickPacket *packet;
  ArSickPacketReceiver receiver(&con);
  ArTime start;
  unsigned int value;
  int numReadings;
  ArTime lastReading;
  ArTime packetTime;

  start.setToNow();

  // open the connection, if it fails, exit
  if ((ret = con.open()) != 0)
  {
    str = con.getOpenMessage(ret);
    printf("Open failed: %s\n", str.c_str());
    Aria::shutdown();
    return 1;
  }

  start.setToNow();

  printf("Waiting for laser to power on\n");
  sick.empty();
  sick.uByteToBuf(0x10);
  sick.finalizePacket();
  con.write(sick.getBuf(), sick.getLength());

  while (start.secSince() < 70 && 
	 ((packet = receiver.receivePacket(100)) == NULL
	  ||  (packet->getID() != 0x90)));
  if (packet != NULL)
    printf("Laser powered on\n");
  else
    exit(1);

  printf("Changing baud\n");
  sick.empty();
  sick.byteToBuf(0x20);
  sick.byteToBuf(0x40);
  sick.finalizePacket();
  con.write(sick.getBuf(), sick.getLength());

  ArUtil::sleep(10);
  if (!con.setBaud(38400))
  {
    printf("Could not set baud, exiting\n");
  }
  
  
  /*packet = receiver.receivePacket(100);
  if (packet != NULL) 
    packet->log();
  */
  sick.empty();
  sick.uByteToBuf(0x3B);
  sick.uByte2ToBuf(180);
  sick.uByte2ToBuf(100);
  sick.finalizePacket();
  con.write(sick.getBuf(), sick.getLength());

  packet = receiver.receivePacket(100);
  if (packet != NULL) 
    packet->log();

  sick.empty();
  sick.byteToBuf(0x20);
  sick.byteToBuf(0x24);
  sick.finalizePacket();
  con.write(sick.getBuf(), sick.getLength());

  packet = receiver.receivePacket(100);
  if (packet != NULL) 
    packet->log();



  printf("Starting to report back from port, it took %ld ms to get here:\n",
	 start.mSecSince());
  start.setToNow();
  while (start.secSince() < 6)
  {
    packetTime.setToNow();
    packet = receiver.receivePacket();
    if (packet != NULL)
      printf("####### %ld ms was how long the packet took\n", packetTime.mSecSince());
    if (packet != NULL)
    {
      if (packet->getLength() < 10)
	packet->log();
      else if (packet->getID() == 0x90)
      {
	char strBuf[512];
	packet->log();
	//printf("%x\n", packet->bufToUByte());
	packet->bufToStr(strBuf, 512);
	printf("0x%x %s\n", packet->getID(), strBuf);
	sick.empty();
	sick.uByteToBuf(0x3B);
	sick.uByte2ToBuf(180);
	sick.uByte2ToBuf(100);
	sick.finalizePacket();
	con.write(sick.getBuf(), sick.getLength());
	packet = receiver.receivePacket(100);
	sick.empty();
	sick.uByteToBuf(0x20);
	sick.uByteToBuf(0x24);
	sick.finalizePacket();
	con.write(sick.getBuf(), sick.getLength());
      }
      else
      {
	value = packet->bufToUByte2();
	numReadings = value & 0x3ff;
	printf("%ld ms after last reading.\n", lastReading.mSecSince());
	/*
	printf("Reading number %d, complete %d, unit: %d %d:\n", value & 0x3ff, !(bool)(value & ArUtil::BIT13), (bool)(value & ArUtil::BIT14), (bool)(value & ArUtil::BIT15));
	for (i = 0; i < numReadings; i++)
	{
	  value = packet->bufToUByte2();
	  if (value & ArUtil::BIT13)
	    printf("D");
	  printf("%d ", value & 0x1fff);
	}
	printf("\n");
	*/
	lastReading.setToNow();
      }
    }
    else
    {
      //printf("No packet\n");
    }
  }
}
bool tryport(const char *port, bool is422, int baud, char **argv, int argc, int maxread, int timeout)
{
  ArSerialConnection ser1(is422);
  ser1.setPort(port);
  ser1.setBaud(baud);
  printf("Trying %s port %s at baud rate %d:\n", is422?"RS-422":"RS-232", port, baud);

  if (!ser1.openSimple())
  {
    ArLog::logErrorFromOS(ArLog::Terse, "Error opening %s.", port);
    return false;
  }

  if (argc > 0)
  {
    printf("-> %3d bytes: ", argc);
    fflush(stdout);
  }

  for (int i = 0; i < argc; ++i)
  {
    int d = strtol(argv[i], NULL, 0);
    if (d == 0 && errno != 0)
    {
      ArLog::logErrorFromOS(ArLog::Terse, "error parsing command argument %d (\"%s\"). Must be decimal, hexidecimal, or octal number.", i, argv[i]);
      Aria::exit(3);
    }
    unsigned char c = (unsigned char)d;
    printf("0x%.2X %c ", (unsigned char) c, (c >= ' ' && c <= '~') ? c : ' ');
    fflush(stdout);
    ser1.write((char*)&c, 1);
  }

  if (argc > 0)
    puts("");

  char buf[256];
  int n = 0;
  ArTime t;
  while (1)
  {
    ArUtil::sleep(1);
    int r = 0;
    if ((r = ser1.read(buf, sizeof(buf))) < 0)
    {
      puts("Error reading data from serial port.");
      return false;
    }
    else if (r > 0)
    {
      printf("<- %3d bytes: ", r);
      for (int i = 0; i < r; ++i)
      {
        //printf("[%d] ", i); fflush(stdout);
        char c = buf[i];
        printf("0x%.2X %c ", (unsigned char)c, (c >= ' ' && c <= '~') ? c : ' ');
        if ((i+1) % 8 == 0)
          printf("\n              ");
      }
      printf("\n");
    }
    if ((n += r) >= maxread)
    {
      puts("max");
      return true;
    }
    if (t.secSince() > timeout)
    {
      puts("timeout");
      return false;
    }
  }
  return true;
}