void vrpn_Tracker_Crossbow::recalibrate(vrpn_uint16 num_samples) { if (num_samples < 100) { fprintf(stderr, "vrpn_Tracker_Crossbow: Must recalibrate using at least 100 samples\n"); return; } else if (num_samples > 25599) { fprintf(stderr, "vrpn_Tracker_Crossbow: Capping recalibration at 25,500 samples\n"); num_samples = 25500; } vrpn_drain_output_buffer(serial_fd); vrpn_flush_input_buffer(serial_fd); // Prepare zero command unsigned char buffer[2]; buffer[0] = 'z'; buffer[1] = (unsigned char) (num_samples / 100); vrpn_write_characters(serial_fd, buffer, 2); vrpn_drain_output_buffer(serial_fd); vrpn_SleepMsecs(50); // Wait for affirmative response. // Allow two minutes before timing out. // Even 25500 samples should make it with a few seconds to spare. struct timeval timeout; timeout.tv_sec = 120; timeout.tv_usec = 0; if (!vrpn_read_available_characters(serial_fd, buffer, 1, &timeout) || *buffer != 'Z') { fprintf(stderr, "vrpn_Tracker_Crossbow: Failed to recalibrate device\n"); } }
void vrpn_SerialPort::drain_output_buffer() { requiresOpen(); int ret = vrpn_drain_output_buffer(_comm); if (ret == -1) { throw DrainFailure(); } }
int vrpn_Nikon_Controls::set_channel(unsigned chan_num, vrpn_float64 value) { // Ask to change the focus if this was channel 0. Also, store away where we // asked the focus to go to so that we can know where we are when we get there // (the response from the microscope just says "we got here!). if ( (int)chan_num >= o_num_channel ) { char msg[1024]; sprintf(msg,"vrpn_Nikon_Controls::set_channel(): Index out of bounds (%d of %d), value %lg\n", chan_num, o_num_channel, value); vrpn_gettimeofday(&o_timestamp, NULL); send_text_message(msg, o_timestamp, vrpn_TEXT_ERROR); } char msg[256]; sprintf(msg, "fSMV%ld\r", (long)value); #ifdef VERBOSE printf("Nikon Control: Asking to move to %ld with command %s\n", (long)value, msg); #endif if (vrpn_write_characters(serial_fd, (unsigned char *)msg, strlen(msg)) != (int)strlen(msg)) { fprintf(stderr, "vrpn_Nikon_Controls::set_channel(): Can't write command\n"); return -1; } if (vrpn_drain_output_buffer(serial_fd)) { fprintf(stderr, "vrpn_Nikon_Controls::set_channel(): Can't drain command\n"); return -1; } _requested_focus = value; return 0; }
vrpn_Tracker_Flock_Parallel_Slave::~vrpn_Tracker_Flock_Parallel_Slave() { // Some compilers (CenterLine CC on sunos!?) still don't support // automatic aggregate initialization int cLen=0; //unsigned char rgch[2]={'B','G'}; unsigned char rgch [2]; rgch[cLen++] = 'B'; // slaves can't do a sleep // rgch[cLen++] = 'G'; fprintf(stderr,"\nvrpn_Tracker_Flock_Parallel_Slave %d: shutting down ...", d_sensor); // clear output buffer vrpn_flush_output_buffer( serial_fd ); // put the flock to sleep (B to get out of stream mode, G to sleep) if (vrpn_write_characters(serial_fd, (const unsigned char *) rgch, cLen )!=cLen) { fprintf(stderr,"\nvrpn_Tracker_Flock_Parallel_Slave %d: " "failed writing sleep cmd to tracker", d_sensor); status = vrpn_TRACKER_FAIL; return; } // make sure the command is sent out vrpn_drain_output_buffer( serial_fd ); fprintf(stderr, " done.\n"); }
int vrpn_Tracker_Dyna::get_status() { int bytesRead; unsigned char statusBuffer[256]; my_flush(); /* send request for status record */ vrpn_write_characters(serial_fd,(const unsigned char *) "\021", 1); vrpn_drain_output_buffer(serial_fd); vrpn_SleepMsecs(1000.0*2); /* do non-blocking read of status record */ bytesRead = vrpn_read_available_characters(serial_fd, statusBuffer, 8); // T_PDYN_STATUS_RECORD_LENGTH =8; if ( bytesRead == 8 ) { /* we have correct length- check a few chars to make sure this is a valid * record */ if ( ((statusBuffer[0] & lOOO_OOOO) != lOOO_OOOO) || ((statusBuffer[1] & lOOO_OOOO) != lOOO_OOOO) ) return(T_ERROR); /* otherwise, all is well */ return(T_OK); } /* if we get here, we either got too much data or not enough */ /* no data means it's probably disconnected or not turned on */ if ( bytesRead == 0 ) { // fprintf(stderr, "No data\n"); return(T_PDYN_NO_DATA); } /* if we got too much data, chances are that it's in continuous mode */ if ( bytesRead > 8) { fprintf(stderr, "3\n"); return(T_PDYN_SPEW_MODE); } /* if we get here, i have no idea what's going on- could be garbage on the * serial line, wrong baud rate, or that the Dynasight is flaking out. */ return(T_ERROR); } /* t_pdyn_get_status */
void vrpn_Tracker_Liberty::reset() { int i,resetLen,ret; char reset[10]; char errmsg[512]; char outstring1[64],outstring3[64]; //-------------------------------------------------------------------- // This section deals with resetting the tracker to its default state. // Multiple attempts are made to reset, getting more aggressive each // time. This section completes when the tracker reports a valid status // message after the reset has completed. //-------------------------------------------------------------------- // Send the tracker a string that should reset it. The first time we // try this, just do the normal 'c' command to put it into polled mode. // after a few tries with this, use the ^Y reset. Later, try to reset // to the factory defaults. Then toggle the extended mode. // Then put in a carriage return to try and break it out of // a query mode if it is in one. These additions are cumulative: by the // end, we're doing them all. fprintf(stderr,"[DEBUG] Beginning Reset"); resetLen = 0; num_resets++; // We're trying another reset if (num_resets > 0) { // Try to get it out of a query loop if its in one reset[resetLen++] = (char) (13); // Return key -> get ready reset[resetLen++] = 'F'; reset[resetLen++] = '0'; reset[resetLen++] = (char) (13); // Return key -> get ready // reset[resetLen++] = (char) (13); // reset[resetLen++] = (char) (13); } /* XXX These commands are probably never needed, and can cause real headaches for people who are keeping state in their trackers (especially the InterSense trackers). Taking them out in version 05.01; you can put them back in if your tracker isn't resetting as well. if (num_resets > 3) { // Get a little more aggressive reset[resetLen++] = 'W'; // Reset to factory defaults reset[resetLen++] = (char) (11); // Ctrl + k --> Burn settings into EPROM } */ if (num_resets > 2) { reset[resetLen++] = (char) (25); // Ctrl + Y -> reset the tracker reset[resetLen++] = (char) (13); // Return Key } reset[resetLen++] = 'P'; // Put it into polled (not continuous) mode sprintf(errmsg, "Resetting the tracker (attempt %d)", num_resets); VRPN_MSG_WARNING(errmsg); for (i = 0; i < resetLen; i++) { if (vrpn_write_characters(serial_fd, (unsigned char*)&reset[i], 1) == 1) { fprintf(stderr,"."); vrpn_SleepMsecs(1000.0*2); // Wait after each character to give it time to respond } else { perror("Liberty: Failed writing to tracker"); status = vrpn_TRACKER_FAIL; return; } } //XXX Take out the sleep and make it keep spinning quickly // You only need to sleep 10 seconds for an actual Liberty. // For the Intersense trackers, you need to sleep 20. So, // sleeping 20 is the more general solution... if (num_resets > 2) { vrpn_SleepMsecs(1000.0*20); // Sleep to let the reset happen, if we're doing ^Y } fprintf(stderr,"\n"); // Get rid of the characters left over from before the reset vrpn_flush_input_buffer(serial_fd); // Make sure that the tracker has stopped sending characters vrpn_SleepMsecs(1000.0*2); unsigned char scrap[80]; if ( (ret = vrpn_read_available_characters(serial_fd, scrap, 80)) != 0) { sprintf(errmsg,"Got >=%d characters after reset",ret); VRPN_MSG_WARNING(errmsg); for (i = 0; i < ret; i++) { if (isprint(scrap[i])) { fprintf(stderr,"%c",scrap[i]); } else { fprintf(stderr,"[0x%02X]",scrap[i]); } } fprintf(stderr, "\n"); vrpn_flush_input_buffer(serial_fd); // Flush what's left } // Asking for tracker status. S not implemented in Liberty and hence // ^V (WhoAmI) is used. It retruns 196 bytes char statusCommand[2]; statusCommand[0]=(char)(22); // ^V statusCommand[1]=(char)(13); // Return Key if (vrpn_write_characters(serial_fd, (const unsigned char *) &statusCommand[0], 2) == 2) { vrpn_SleepMsecs(1000.0*1); // Sleep for a second to let it respond } else { perror(" Liberty write failed"); status = vrpn_TRACKER_FAIL; return; } // Read Status unsigned char statusmsg[vrpn_LIBERTY_MAX_WHOAMI_LEN+1]; // Attempt to read whoami_len characters. ret = vrpn_read_available_characters(serial_fd, statusmsg, whoami_len); if (ret != whoami_len) { fprintf(stderr," Got %d of %d characters for status\n",ret, whoami_len); } if (ret != -1) { statusmsg[ret] = '\0'; // Null-terminate the string } // It seems like some versions of the tracker report longer // messages; so we reduced this check so that it does not check for the // appropriate length of message or for the last character being a 10, // so that it works more generally. The removed tests are: // || (ret!=whoami_len) || (statusmsg[ret-1]!=(char)(10)) if ( (statusmsg[0]!='0') ) { int i; fprintf(stderr, " Liberty: status is ("); for (i = 0; i < ret; i++) { if (isprint(statusmsg[i])) { fprintf(stderr,"%c",statusmsg[i]); } else { fprintf(stderr,"[0x%02X]",statusmsg[i]); } } fprintf(stderr,"\n)\n"); VRPN_MSG_ERROR("Bad status report from Liberty, retrying reset"); return; } else { VRPN_MSG_WARNING("Liberty/Isense gives status (this is good)"); printf("LIBERTY LATUS STATUS (whoami):\n%s\n\n",statusmsg); num_resets = 0; // Success, use simple reset next time } //-------------------------------------------------------------------- // Now that the tracker has given a valid status report, set all of // the parameters the way we want them. We rely on power-up setting // based on the receiver select switches to turn on the receivers that // the user wants. //-------------------------------------------------------------------- // Set output format for each of the possible stations. for (i = 0; i < num_stations; i++) { if (set_sensor_output_format(i)) { return; } } // Enable filtering if the constructor parameter said to. // Set filtering for both position (X command) and orientation (Y command) // to the values that are recommended as a "jumping off point" in the // Liberty manual. if (do_filter) { if (VRPN_LIBERTY_DEBUG) fprintf(stderr,"[DEBUG]: Enabling filtering\n"); if (vrpn_write_characters(serial_fd, (const unsigned char *)"X0.2,0.2,0.8,0.8\015", 17) == 17) { vrpn_SleepMsecs(1000.0*1); // Sleep for a second to let it respond } else { perror(" Liberty write position filter failed"); status = vrpn_TRACKER_FAIL; return; } if (vrpn_write_characters(serial_fd, (const unsigned char *)"Y0.2,0.2,0.8,0.8\015", 17) == 17) { vrpn_SleepMsecs(1000.0*1); // Sleep for a second to let it respond } else { perror(" Liberty write orientation filter failed"); status = vrpn_TRACKER_FAIL; return; } } else { if (VRPN_LIBERTY_DEBUG) fprintf(stderr,"[DEBUG]: Disabling filtering\n"); if (vrpn_write_characters(serial_fd, (const unsigned char *)"X0,1,0,0\015", 9) == 9) { vrpn_SleepMsecs(1000.0*1); // Sleep for a second to let it respond } else { perror(" Liberty write position filter failed"); status = vrpn_TRACKER_FAIL; return; } if (vrpn_write_characters(serial_fd, (const unsigned char *)"Y0,1,0,0\015", 9) == 9) { vrpn_SleepMsecs(1000.0*1); // Sleep for a second to let it respond } else { perror(" Liberty write orientation filter failed"); status = vrpn_TRACKER_FAIL; return; } } // Send the additional reset commands, if any, to the tracker. // These commands come in lines, with character \015 ending each // line. If a line start with an asterisk (*), treat it as a pause // command, with the number of seconds to wait coming right after // the asterisk. Otherwise, the line is sent directly to the tracker. // Wait a while for them to take effect, then clear the input // buffer. if (strlen(add_reset_cmd) > 0) { char *next_line; char add_cmd_copy[sizeof(add_reset_cmd)]; char string_to_send[sizeof(add_reset_cmd)]; int seconds_to_wait; printf(" Liberty writing extended reset commands...\n"); // Make a copy of the additional reset string, since it is consumed vrpn_strcpy(add_cmd_copy, add_reset_cmd); // Pass through the string, testing each line to see if it is // a sleep command or a line to send to the tracker. Continue until // there are no more line delimiters ('\015'). Be sure to write the // \015 to the end of the string sent to the tracker. // Note that strok() puts a NULL character in place of the delimiter. next_line = strtok(add_cmd_copy, "\015"); while (next_line != NULL) { if (next_line[0] == '*') { // This is a "sleep" line, see how long seconds_to_wait = atoi(&next_line[1]); fprintf(stderr," ...sleeping %d seconds\n",seconds_to_wait); vrpn_SleepMsecs(1000.0*seconds_to_wait); } else { // This is a command line, send it sprintf(string_to_send, "%s\015", next_line); fprintf(stderr, " ...sending command: %s\n", string_to_send); vrpn_write_characters(serial_fd, (const unsigned char *)string_to_send,strlen(string_to_send)); } next_line = strtok(next_line+strlen(next_line)+1, "\015"); } // Sleep a little while to let this finish, then clear the input buffer vrpn_SleepMsecs(1000.0*2); vrpn_flush_input_buffer(serial_fd); } // Set data format to BINARY mode sprintf(outstring1, "F1\r"); if (vrpn_write_characters(serial_fd, (const unsigned char *)outstring1, strlen(outstring1)) == (int)strlen(outstring1)) { fprintf(stderr, " Liberty set to binary mode\n"); } // Set tracker to continuous mode sprintf(outstring3, "C\r"); if (vrpn_write_characters(serial_fd, (const unsigned char *)outstring3, strlen(outstring3)) != (int)strlen(outstring3)) { perror(" Liberty write failed"); status = vrpn_TRACKER_FAIL; return; } else { fprintf(stderr, " Liberty set to continuous mode\n"); } // If we are using the Liberty timestamps, clear the timer on the device and // store the time when we cleared it. First, drain any characters in the output // buffer to ensure we're sending right away. Then, send the reset command and // store the time that we sent it, plus the estimated time for the characters to // get across the serial line to the device at the current baud rate. // Set time units to milliseconds (MT) and reset the time (MZ). char clear_timestamp_cmd[] = "Q0\r"; vrpn_drain_output_buffer(serial_fd); if (vrpn_write_characters(serial_fd, (const unsigned char *)clear_timestamp_cmd, strlen(clear_timestamp_cmd)) != (int)strlen(clear_timestamp_cmd)) { VRPN_MSG_ERROR("Cannot send command to clear timestamp"); status = vrpn_TRACKER_FAIL; return; } // Drain the output buffer again, then record the time as the base time from // the tracker. vrpn_drain_output_buffer(serial_fd); vrpn_gettimeofday(&liberty_zerotime, NULL); // Done with reset. vrpn_gettimeofday(&watchdog_timestamp, NULL); // Set watchdog now VRPN_MSG_WARNING("Reset Completed (this is good)"); status = vrpn_TRACKER_SYNCING; // We're trying for a new reading }
// slave resets are ONLY called by the master void vrpn_Tracker_Flock_Parallel_Slave::reset() { // slaves just flush on a reset and then stream (or poll) // master does all the real resetting // set vars for error handling // set them right away so they are set properly in the // event that we fail during the reset. cResets++; cSyncs=0; fFirstStatusReport=1; // Get rid of the characters left over from before the reset // (make sure they are processed) vrpn_drain_output_buffer(serial_fd); // put back into polled mode (need to stop stream mode // before doing an auto-config) int resetLen=0; unsigned char reset[3]; reset[resetLen++]='B'; // send the poll mode command (cmd and cmd_size are args) if (vrpn_write_characters(serial_fd, (const unsigned char *) reset, resetLen )!=resetLen) { fprintf(stderr,"\nvrpn_Tracker_Flock_Parallel_Slave %d: " "failed writing poll cmd to tracker", d_sensor); status = vrpn_TRACKER_FAIL; return; } // make sure the command is sent out vrpn_drain_output_buffer( serial_fd ); // wait for tracker to respond and flush buffers vrpn_SleepMsecs(500); // clear the input buffer (it will contain a single point // record from the poll command above and garbage from before reset) vrpn_flush_input_buffer(serial_fd); // now start it running resetLen = 0; // either stream or let poll take place later if (fStream==1) { // stream mode reset[resetLen++] = '@'; if (vrpn_write_characters(serial_fd, (const unsigned char *) reset, resetLen )!=resetLen) { fprintf(stderr,"\nvrpn_Tracker_Flock_Parallel_Slave %d: " "failed writing set mode cmds to tracker", d_sensor); status = vrpn_TRACKER_FAIL; return; } // make sure the commands are sent out vrpn_drain_output_buffer( serial_fd ); } else { poll(); } fprintf(stderr,"\nvrpn_Tracker_Flock_Parallel_Slave %d: " "done with reset ... running.\n", d_sensor); vrpn_gettimeofday(×tamp, NULL); // Set watchdog now status = vrpn_TRACKER_SYNCING; // We're trying for a new reading }
void vrpn_Tracker_Crossbow::reset() { const char *cmd; unsigned char recv_buf[8]; struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; #if 0 // doesn't help // First, take the comm port offline for a second vrpn_close_commport(serial_fd); vrpn_SleepMsecs(1000); serial_fd = vrpn_open_commport(portname, baudrate); #endif vrpn_flush_output_buffer(serial_fd); vrpn_flush_input_buffer(serial_fd); // Try resetting by toggling the RTS line of the serial port vrpn_set_rts(serial_fd); vrpn_SleepMsecs(750); vrpn_clear_rts(serial_fd); vrpn_SleepMsecs(250); vrpn_gettimeofday(×tamp, NULL); vrpn_flush_input_buffer(serial_fd); cmd = "P"; vrpn_write_characters(serial_fd, reinterpret_cast<const unsigned char*> (cmd), 1); vrpn_SleepMsecs(50); // Sleep long enough to stop receiving data vrpn_flush_input_buffer(serial_fd); cmd = "RSv"; vrpn_write_characters(serial_fd, reinterpret_cast<const unsigned char*> (cmd), 3); vrpn_drain_output_buffer(serial_fd); if (vrpn_read_available_characters(serial_fd, recv_buf, 8, &timeout) != 8) { fprintf(stderr, "vrpn_Tracker_Crossbow::reset: Crossbow not responding to stimulus\n"); status = vrpn_TRACKER_FAIL; return; } if ((recv_buf[0] != 'H') || (recv_buf[1] != 255) || (recv_buf[7] != 255)) { fprintf(stderr, "vrpn_Tracker_Crossbow::reset: Crossbow gave unexpected ping response\n"); status = vrpn_TRACKER_FAIL; return; } if (recv_buf[6] != ((recv_buf[2] + recv_buf[3] + recv_buf[4] + recv_buf[5]) & 0xFF)) { fprintf(stderr, "vrpn_Tracker_Crossbow::reset: Crossbow gave invalid serial number checksum\n"); status = vrpn_TRACKER_FAIL; return; } const char *bufptr = reinterpret_cast<const char *>(&recv_buf[2]); vrpn_unbuffer(&bufptr, &device_serial); if (0) do { if (!vrpn_read_available_characters(serial_fd, recv_buf, 1, &timeout)) { fprintf(stderr, "vrpn_Tracker_Crossbow::reset: Crossbow not responding to stimulus\n"); status = vrpn_TRACKER_FAIL; return; } } while (*recv_buf != 255); int curSize = 4, curLen = 0; device_version = (char *) realloc(device_version, curSize * sizeof(char)); if (device_version == NULL) { fprintf(stderr, "vrpn_Tracker_Crossbow::reset: Out of memory\n"); status = vrpn_TRACKER_FAIL; return; } do { if (!vrpn_read_available_characters(serial_fd, recv_buf, 1, &timeout)) { fprintf(stderr, "vrpn_Tracker_Crossbow::reset: Crossbow not responding to stimulus\n"); status = vrpn_TRACKER_FAIL; return; } if (*recv_buf != '$') device_version[curLen++] = *recv_buf; if (curLen == curSize) device_version = (char *) realloc(device_version, curSize *= 2); } while (*recv_buf != '$'); // Now null-terminate the version string, expanding it one last time if necessary if (curLen == curSize) device_version = (char *) realloc(device_version, ++curSize); device_version[curLen] = 0; //printf("Serial %u\tVersion '%s'\n", device_serial, device_version); just_read_something = 0; status = vrpn_TRACKER_SYNCING; }