|
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectcom.brianziman.robotics.SCIP11
public class SCIP11
Copyright 2007 - Brian Ziman
This class implements the SCIP 1.1 protocol for the Hokuyo URG-04LX Laser sensor. It communicates over a socket to Prof. Sean Luke's serialdaemon utility which communicates directly with the serial port.
The JavaDoc for the public methods will provide useful information for end users. The more useful public methods may throw a runtime exception, SCIPException is something weird happens, for example, if the connection to the serialdaemon dies, or if invalid data is received from the laser. The response in these situations is undefined, which is why it is a runtime exception that does not and should not be explicitely caught, unless you're really sure you know how to handle it.
Each function returns a status code, which according to the spec, indicates merely success or failure. Whenever a failure is recorded, a message is sent to standard output. On the off chance that the status code is important, there is a public method to retreive the last error status, which resets the status field to zero. I wouldn't count on it having anything meaningful, though.
This interface is implemented precisely according to the SCIP spec, however there are at least a few obvious mistakes in the spec, and a few things that are probably mistakes. In cases where I wasn't sure, I followed the spec, and I'm hoping testing will reveal whether the spec was indeed correct, or not.
The following information is based on the URG Series Communication Protocol Specification (SCIP Version 1.1).
Host to Sensor commands are in the format:
|Command|Parameter|LF/CR|
The Sensor will then respond in the format:
|Command|Parameter|LF|Status|LF|Data|LF|LF|
Command is 'V' (0x56) No parameter. Request is: |'V'|LF/CR| Response is: |'V' |LF| |Status |LF| |Vendor Info |LF| |Product Info|LF| |Firmware Ver|LF| |Protocol Ver|LF| |Serial Num |LF|LF|
Command is 'L' (0x4C) Parameter is 1 byte Control Code. '1' switches laser on. '0' switches laser off. (Are these 0x31 and 0x30? or 0x01 and 0x00? Need to check.) Request is: |'L'|'0'/'1'|LF/CR| Response is: |'L'|'0'/'1'|LF|Status|LF|LF|
Command is 'S' (0x53) Parameter is 6 ascii digit baud rate, followed by 7 digit reserved. "019200" sets 19.2kbps (default) "057600" sets 57.6kbps "115200" sets 115.2kbps "250000" sets 250.0kbps "500000" sets 500.0kbps "750000" sets 750.0kbps Request is: |'S'|aaaaaa|rrrrrrr|LF/CR| Response is: |'S'|aaaaaa|rrrrrrr|Status|LF|LF| (why is there no LF before Status here?)
Command is 'G' (0x47) Parameters are 3 digit starting point, 3 digit ending point, and 2 digit cluster count. Starting and ending point range from 0..768. Cluster count is from 0..99. (Encoded using ascii digits 0x30-0x39). Request is: |'G'|sss|eee|cc|LF/CR| Response is: |'G'|sss|eee|cc|LF|Status|Data|LF|LF| Where data is broken into blocks of 64 bytes followed by LF. Sensor measures range of 4095mm with 1mm resolution. Data point is expressed with 12 bits (0..4095). 12 bit value is encoded as follows: 1234mm = 010011 010010(binary) = 0x13 0x12 +0x30 = 0x43 0x42 = 'C','D' (ascii) Starting and ending point refer to steps in the field of angular detection. This field is a range of 240 degrees, with a dead zone of 120 degrees at the rear. Step 0 is at -135 degrees from front (right), Step 384 is at 0 degrees (facing front), and Step 768 is at +135 degrees (left). Step 0 and 768 are both in the deadzone. Measurable range is from Step 44 to Step 725. Each step has a resolution of 360deg/1024 = 0.3515625 deg. I assume that the "cluster" parameter, which refers to the number of neighboring points that are grouped as a cluster would reduce the amount of data returned. For example, if start is at "44" and end is at "725" and cluster is "01", then you would expect some 680 data points. If cluster were "20", then you might expect only 34 data points, each of which is perhaps the average of a 7 degree arc? Sensors will return values between 20mm and 4094mm. Anything less than 20mm will result in an error code at that data point. Error codes for data points are (don't ask me what they mean): 0 "Possibility of detected object is at 22m" 1-5 "Reflected light has low intensity" 6 "Possibility of detected object is at 5.7m" 7 "Distance data on the preceding and succeeding steps have errors" 8 "Others" 9 "The same step had error in the last two scan" 10-15 "Others" 16 "Possibility of detected object is in the range 4096mm" 17 "Others" 18 "Unspecified" 19 "Non-Measurable Distance"
Field Summary | |
---|---|
static java.lang.String |
BAUD_019200
19.2kbps baud rate. |
static java.lang.String |
BAUD_057600
57.6kbps baud rate. |
static java.lang.String |
BAUD_115200
115.2kbps baud rate. |
static java.lang.String |
BAUD_250000
250kbps baud rate. |
static java.lang.String |
BAUD_500000
500kbps baud rate. |
static java.lang.String |
BAUD_750000
750kbps baud rate. |
static java.lang.String |
KEY_FIRMWARE
Firmware Version. |
static java.lang.String |
KEY_PRODUCT
Product Information. |
static java.lang.String |
KEY_PROTOCOL
Protocol Version. |
static java.lang.String |
KEY_SERIAL
Sensor Serial Number. |
static java.lang.String |
KEY_STATUS
Undocumented Status Field. |
static java.lang.String |
KEY_VENDOR
Vendor Information. |
static int |
MAX_CLUSTER
Largest number of clusters permitted. |
static int |
MAX_STEP
Maximum step value for laser that corresponds with 135 degrees to the left of forward. |
static int |
MIN_CLUSTER
Smallest number of clusters permitted. |
static int |
MIN_STEP
Minimum step value for laser that corresponds with -135 degrees to the right of forward. |
Constructor Summary | |
---|---|
SCIP11(int port)
|
Method Summary | |
---|---|
void |
disable()
Disable the laser. |
java.util.ArrayList<java.lang.Integer> |
doDistanceCommand(int start,
int end,
int cluster)
Internal method to request sensor data from the laser. |
void |
doLaserCommand(boolean enable)
Internal method to enable or disable the laser. |
void |
doSettingsCommand(java.lang.String baud)
Internal method to configures the baud rate of the device. |
java.util.HashMap<java.lang.String,java.lang.String> |
doVersionCommand()
Internal method to return a map of version info from the laser. |
void |
enable()
Enable the laser. |
double |
getAngleOffset()
Retreive the angle offset. |
static java.lang.String |
getErrorFromData(int c)
If a data point less than 20 is returned, it corresponds to an error code as documented. |
java.lang.String |
getFirmwareVersion()
Returns static firmware version from laser. |
byte |
getLastError()
Return the last error code byte generated by the laser and clear the code. |
java.lang.String |
getProductInfo()
Returns static product information from laser. |
java.lang.String |
getProtocolVersion()
Returns static protocol version from laser. |
int |
getRange(double angle)
Returns the range detected at the given angle, measured in degrees, and within the angular range of the sensor, -120 degrees to +120 degrees. |
long |
getScanTime()
|
java.lang.String |
getSensorSerialNumber()
Returns static sensor serial number from laser. |
java.lang.String |
getSensorStatus()
Returns undocumented static status field laser. |
java.lang.String |
getVendorInfo()
Returns static vendor information from laser. |
static void |
main(java.lang.String[] args)
Only useful for testing. |
void |
setAngleOffset(double d)
The Hokuyo laser ranger considers forward to be zero degrees, however, some systems, such as the sensor array on the Pioneer robots, consider zero degrees to be in other locations (for the Pioneers, that would be on the right). |
void |
setBaud(java.lang.String baud)
Set the baud rate using one of the BAUD_n constants. |
void |
setScanTime(long l)
This method specifies the number of milliseconds per scan of the laser. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
public static final int MIN_STEP
public static final int MAX_STEP
public static final int MIN_CLUSTER
public static final int MAX_CLUSTER
public static final java.lang.String KEY_VENDOR
public static final java.lang.String KEY_PRODUCT
public static final java.lang.String KEY_FIRMWARE
public static final java.lang.String KEY_PROTOCOL
public static final java.lang.String KEY_SERIAL
public static final java.lang.String KEY_STATUS
public static final java.lang.String BAUD_019200
public static final java.lang.String BAUD_057600
public static final java.lang.String BAUD_115200
public static final java.lang.String BAUD_250000
public static final java.lang.String BAUD_500000
public static final java.lang.String BAUD_750000
Constructor Detail |
---|
public SCIP11(int port) throws java.io.IOException
java.io.IOException
Method Detail |
---|
public void enable()
public void disable()
public void setBaud(java.lang.String baud)
public java.lang.String getVendorInfo()
public java.lang.String getProductInfo()
public java.lang.String getFirmwareVersion()
public java.lang.String getProtocolVersion()
public java.lang.String getSensorSerialNumber()
public java.lang.String getSensorStatus()
public int getRange(double angle)
public void setScanTime(long l)
public long getScanTime()
public void setAngleOffset(double d)
public double getAngleOffset()
public java.util.HashMap<java.lang.String,java.lang.String> doVersionCommand()
Internal method to return a map of version info from the laser. Most users should access this data via getVendorInfo(), getProductInfo(), getFirmwareVersion(), getProtocolVersion(), and getSensorSerialNumber().
The keys are: KEY_VENDOR = "Vender Information" // sic KEY_PRODUCT = "Product Information" KEY_FIRMWARE = "Firmware Version" KEY_PROTOCOL = "Protocol Version" KEY_SERIAL = "Sensor Serial Number" KEY_STATUS = "Undocumented Status Field" The values are informational strings.
public void doLaserCommand(boolean enable)
public void doSettingsCommand(java.lang.String baud)
public java.util.ArrayList<java.lang.Integer> doDistanceCommand(int start, int end, int cluster)
Internal method to request sensor data from the laser. The getRange() method provides simpler access to range data.
Starting and ending point range from 0..768. Cluster count is from 0..99.
Sensor measures range of 4095mm with 1mm resolution.
Starting and ending point refer to steps in the field of angular detection. This field is a range of 240 degrees, with a dead zone of 120 degrees at the rear. Step 0 is at -135 degrees from front (right), Step 384 is at 0 degrees (facing front), and Step 768 is at +135 degrees (left). Step 0 and 768 are both in the deadzone. Measurable range is from Step 44 to Step 725. Each step has a resolution of 360deg/1024 = 0.3515625 deg.
I assume that the "cluster" parameter, which refers to the number of neighboring points that are grouped as a cluster would reduce the amount of data returned.
For example, if start is at "44" and end is at "725" and cluster is "01", then you would expect some 680 data points.
If cluster were "20", then you might expect only 34 data points, each of which is perhaps the average of a 7 degree arc?
Sensors will return values between 20mm and 4094mm. Anything less than 20mm will result in an error code at that data point.
Error codes for data points are (don't ask me what they mean):
0 "Possibility of detected object is at 22m" 1-5 "Reflected light has low intensity" 6 "Possibility of detected object is at 5.7m" 7 "Distance data on the preceding and succeeding steps have errors" 8 "Others" 9 "The same step had error in the last two scan" 10-15 "Others" 16 "Possibility of detected object is in the range 4096mm" 17 "Others" 18 "Unspecified" 19 "Non-Measurable Distance"
public byte getLastError()
public static void main(java.lang.String[] args) throws java.lang.Exception
java.lang.Exception
public static final java.lang.String getErrorFromData(int c)
|
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |