We are all in this together. I wanted to take a second to drop some names for everyone. If you need composites work done or molds made at reasonable rates. Call Robert at Mohrbacher Composites he really did a great job on some sick projects. If you have more normal fabrication requirements, the guys at Impact Fab, tell Ross, that the Buzz Labs boys sent you. Ross works wonders with his water jet.
Thanks guys for helping us with my bad ideas!
Friday, October 23, 2009
Phidgets UltraSonic RangeFinder
The rangefinder is not a Phidgets. They are reselling a LV Max Sonar EZ1 from MaxBotix. You get in the bag the sensor (transceiver) and a small wire bundle. The wires need to be soldered into the proper pins. Just for reference from the pin closest to the mounting hole,
black
red
open
green
white
open
open
wire meanings
black - ground
red +5V
green signal to trip the ultrasonic ping, +5V I think, but I do not use it
white 5V signal
This will cable your phidgets three wire signal cable correctly. Remember this is not a normal sensor, it is one of their analog sensors. So you will need one of their a/d boards or interface boards in their terminology. The event that you will want to hook, the SensorChange event. Everything the system reads a new voltage on the port it fires sensor change. See my post on the 888 interface kit to see how to set up the interface kit.
Here is my way of switching the data so you only need one method for any port change.
There are some other details in this code. Since I use a bunch of helper methods to calibrate the data coming out. Remember the values (Args.Value) come out as a double so you can write a simple linear interpolation for you that will get your data back into usable units from Voltage. For simplicity's sake, I have the interpolation points in an xml config file that is read in at start time to handle each of the instruments. That way the values can easily be changed for recalibration.
The code I have presented is good simple code that is quick and should work for almost any purpose and uses solid error trapping techniques.
black
red
open
green
white
open
open
wire meanings
black - ground
red +5V
green signal to trip the ultrasonic ping, +5V I think, but I do not use it
white 5V signal
This will cable your phidgets three wire signal cable correctly. Remember this is not a normal sensor, it is one of their analog sensors. So you will need one of their a/d boards or interface boards in their terminology. The event that you will want to hook, the SensorChange event. Everything the system reads a new voltage on the port it fires sensor change. See my post on the 888 interface kit to see how to set up the interface kit.
Here is my way of switching the data so you only need one method for any port change.
protected void SensorChange(object Sender, SensorChangeEventArgs Args)
{
try
{
InstrumentType _type = InstrumentType.notset;
int _index = 0;
switch (Args.Index)
{
case 7:
_type = InstrumentType.ultrasonicRangeFinder;
_index = 4;
break;
case 6:
_type = InstrumentType.ultrasonicRangeFinder;
_index = 3;
break;
case 5:
_type = InstrumentType.ultrasonicRangeFinder;
_index = 2;
break;
case 4:
_type = InstrumentType.ultrasonicRangeFinder;
_index = 1;
break;
case 3:
_type = InstrumentType.ultrasonicRangeFinder;
_index = 0;
break;
case 2:
_type = InstrumentType.pressureTotal;
totalPressure = convertVoltageToUnit(_type, Args.Value, _index);
speed = getPressureSpeed(totalPressure, staticPressure, staticTemperature);
break;
case 1:
_type = InstrumentType.temperature;
staticTemperature = convertVoltageToUnit(_type, Args.Value, _index);
speed = getPressureSpeed(totalPressure, staticPressure, staticTemperature);
break;
case 0:
_type = InstrumentType.pressureStatic;
staticPressure = convertVoltageToUnit(_type, Args.Value, _index);
speed = getPressureSpeed(totalPressure, staticPressure, staticTemperature);
pressureAltitude = getGeoPotentialAltitude(staticPressure / units.kPaToPsf);
break;
}
if (_type == InstrumentType.ultrasonicRangeFinder)
{
rangeFinders[_index] = convertVoltageToUnit(InstrumentType.ultrasonicRangeFinder, Args.Value, _index);
}
}
catch (Exception _exc)
{
throw new Exception(className + " protected void SensorChange( Sender, Args) :: " + _exc.Message + "\n");
}
}
There are some other details in this code. Since I use a bunch of helper methods to calibrate the data coming out. Remember the values (Args.Value) come out as a double so you can write a simple linear interpolation for you that will get your data back into usable units from Voltage. For simplicity's sake, I have the interpolation points in an xml config file that is read in at start time to handle each of the instruments. That way the values can easily be changed for recalibration.
The code I have presented is good simple code that is quick and should work for almost any purpose and uses solid error trapping techniques.
Do I want to see both sides of your pretty face?
This week I am still waiting for motors. It turns out my motor supplier has been on vacation this week, how dare he? Sorry Dave I just needed to get in the jab. So I had this new idea for how to progress, I was thinking about something someone said to me. They were explaining how someone did not like to fly their great looking soarer because of how much it cost to replace.
Then I sat there looking at the School Girl UAS on the table and thought. ZOMG! It costs like 2-3x as much as the guy's soarer. What the hell am I thinking? I have to make sure that this thing can be showable to other people. It does have to fly, to demonstrate that those Engineering school was not a waste of time. I just want to make sure I do not throw two months of work and a thousand dollars into the ground due to bad luck and clean living. All of my best ideas are inspiration this time, I swear there was no barley soda involved. Ok, maybe some, but it was good stuff. The decision was made to make a new version of the truck so that I could work more on my version of the IMU and control system as well as make a safer platform for developing technologies for the UAS.
Long story short, a new beastie was conceived. Like the sign said, always well conceived, unlike people. Now this new ground guy lets me do lots of experiments with much less of the z-axis problem. The z-axis problem is acceleration due to gravity. Something that drives along the ground can still have great mishaps but it is easier to teach a car to drift a corner than it is to teach a plane to avoid turbulence.
So one of the first things about this idea is how to navigate the buggy. Actually, this is less of an issue than it may seem and allows us to do some much more interesting things. Monitoring the instruments and planning a heading to a goal is mostly done with the code that I have. What does this have to do with my pretty face? Navigation is not as interesting as deciding how to see. Many times navigation is more than careening off in the direction that leads you to the goal the fastest. What if there is a reason to follow a path? How do you find the path?
I sat back and ran through a series of thought experiments on how to execute this. The following questions came to me that needed an answer:
- If there is a reason to follow a path, then how do I find the path?
- If I find a path how often do I have to look for the path?
- Maybe I want the video stream to get back to an operator and still be able to work on the data, how do I do it?
- How much processing is really necessary to find the important elements of a scene?
- An element of a scene is important, how do I decide if it is important for driving or for identifying to an operator?
- This is a lot of processing, how can I reduce it to use lower-powered systems to reduce processing costs?
As a matter of fact, the machine itself cannot make a lot of use of stereoscopic vision. Not that it is not useful, but that is an operator technology not a machine technology. The machine can use the stereoscopic vision to detect objects that may cause negative performance impacts . A really shiny thing in the way could "flash" and make a very small thing seem very big and that would possibly confuse the system, or a shadow may seem like a hole and cause unnecessary course correction. Coordinating objects in the two-camera system will allow false behaviors to be avoided or at least identified. It could also be used to do simple comparisons... is this blob like that one? and then reduce useful processing by discarding one of the copies.
If we can process the scene in such a way that we can slow the effective frame rate down by not checking for the path as often it is one less object in the scene to be processed. Optical flow algorithms will help with this because you can quickly get velocity estimates for a given object relative to your position. As that changes you can say... same element do not reprocess it. If we identify the objects in the scene and discard the ones that are clearly not as important then we can process many fewer regions of the scene and or pass the processing back to an operator.
This is going to be a multi-part post about basic vision systems and how I think it should be brought together and used in many applications without changing the code. How a few observations about what we want to do and what it really means may make a lot of decisions easier in the design. This code will focus on commodity components and instrumentation and control electronics from Phidgets and SparkFun.
Tuesday, October 20, 2009
The Girls Love the Long Ball, But the Boys Love the Spin
Someone once told me that it is not the boom, it is all about the shock wave. I guess that is true, you need to feel the motion of the ocean.
You ask, what does this have to do with gyros? Well, if you cannot figure out how fast it is twisting, there is no way to know how far your ball will go. Yeah, actually a lot, since driving a golf ball is not a momentum problem alone. The dimples hold the boundary layer on and make it go much farther.
Gyroscopes are cool, I have the neat little 300 deg/s board from SparkFun, built on a 3DOF IMU. I soldered on some pins so that it is easier to connect to. Connected the ground to the system ground and connected each of the signal pins to a separate "connector". Really, easy and I am a bit electrically declined.
I then set up an easy pseudo code system to watch the ISensor.DataUpdated method. That lets me see the phidgets.datachanged event in my little API. The delegate that I use for ISensor.DataUpdated feeds my smoothing algorithm. I use the smoothing algorithm to keep out shorts and wonky voltage changes that happen. This would feed the Kalmann filter which I still do not have.
I then feed these data updated events into an ArrayList and do my Runge-Kutta routines on them to integrate the unknown functions. This running integration is how I get an approximation of the position of the gyro. Remember gyros return the rate of change of the gyration, an angular velocity so to speak.
We can do a simple integration to get back to a position.
xi = xdot*dt+xi-1
for constant timestep dt and the previous position, xi-1.
I will put some code together for the next post on this.
You ask, what does this have to do with gyros? Well, if you cannot figure out how fast it is twisting, there is no way to know how far your ball will go. Yeah, actually a lot, since driving a golf ball is not a momentum problem alone. The dimples hold the boundary layer on and make it go much farther.
Gyroscopes are cool, I have the neat little 300 deg/s board from SparkFun, built on a 3DOF IMU. I soldered on some pins so that it is easier to connect to. Connected the ground to the system ground and connected each of the signal pins to a separate "connector". Really, easy and I am a bit electrically declined.
I then set up an easy pseudo code system to watch the ISensor.DataUpdated method. That lets me see the phidgets.datachanged event in my little API. The delegate that I use for ISensor.DataUpdated feeds my smoothing algorithm. I use the smoothing algorithm to keep out shorts and wonky voltage changes that happen. This would feed the Kalmann filter which I still do not have.
I then feed these data updated events into an ArrayList and do my Runge-Kutta routines on them to integrate the unknown functions. This running integration is how I get an approximation of the position of the gyro. Remember gyros return the rate of change of the gyration, an angular velocity so to speak.
We can do a simple integration to get back to a position.
xi = xdot*dt+xi-1
for constant timestep dt and the previous position, xi-1.
I will put some code together for the next post on this.
Friday, October 16, 2009
Phidgets Accelerometers, the Magic of Three-Axes
The three-axis accelerometer is a piezo-electric accelerometer that is about 1" square. It is pretty good and have never seen any issues with drift or orientation issues. It measures each axis in units of g Do not forget to convert to your units, so a reading of 1.2 is actually an acceleration of 38.6 ft/s/s. I just make a little helper function to convert the readings when the phidgets_accelerationchanged method fires.
Hopefully, that will help clean up your code by reducing the risk of double converting units. Even NASA makes this mistake. One of the first things that I set up is a library of unit converstion factors. That way it is less risky if the user wishes to see the measurements in , mks or cgs and my software interanlly uses US Customary slug-ft-lbf. I do not do any conversions in the code. Just read the electrical signals from the transducers and convert them to real units, consistent with the system. Do not try and convert back and forth within the code, it will just be miserable to find.
You convert to any system that is different than your base unit system until you display the data. You can easily set a flag in the display object that shows the data to the user and multiply out the measurements at presentation time via the decoration pattern. To be honest, the Phidgets API is awesome. It makes short work of connecting and managing their instruments, so the code to start an interface kit is not so different from the accelerometer.
Another helper method that is constantly requested is converting from accelerations to roll and pitch. You can do the trigonometry yourself, but if gravitation is assumed to act in the -Z direction you can work out the basic orientation of the accelerating object. This can be fooled by large or quick orientation changes, but for the most part sampling frequency can fix this. So I would make sure that you do as little as possible that may muddy the event handler system. They are really fast and that is a good thing in this case.
The one thing you will notice is that you cannot get the yaw from the accelerations. That makes sense if you think about it, flat rotation perpendicular to gravity would not be measured. I usually run a compass in the systems too. That makes the 3-1-3 rotation easy to move between body reference frames and global reference frames. I would suggest that you multiply out the cells for the rotations in a separate method each so that you can just multiply them by calling each method in turn with an argument of the last rotation.
Hopefully, that will help clean up your code by reducing the risk of double converting units. Even NASA makes this mistake. One of the first things that I set up is a library of unit converstion factors. That way it is less risky if the user wishes to see the measurements in , mks or cgs and my software interanlly uses US Customary slug-ft-lbf. I do not do any conversions in the code. Just read the electrical signals from the transducers and convert them to real units, consistent with the system. Do not try and convert back and forth within the code, it will just be miserable to find.
You convert to any system that is different than your base unit system until you display the data. You can easily set a flag in the display object that shows the data to the user and multiply out the measurements at presentation time via the decoration pattern. To be honest, the Phidgets API is awesome. It makes short work of connecting and managing their instruments, so the code to start an interface kit is not so different from the accelerometer.
do
{
//System.Threading.Thread.Sleep(10);
if (acc0.Attached)
{
Console.WriteLine("_acc0 attached");
//accelerometer events
acc0.Attach += phidgets_Attach;
acc0.Detach += phidgets_Detach;
acc0.Error += phidgets_Error;
acc0.AccelerationChange += _acc0_AccelerationChange;
}
else
{
Console.WriteLine("retry : " + retry + " waiting for acc0 attach");
}
retry++;
} while (retry < 10 && !acc0.Attached); #region helperMethods #region Phidgets event handlers ///
/// handle the phidget device discovery events
///
/// /// protected void phidgets_Attach(object Sender, AttachEventArgs Args)
{
try
{
Console.WriteLine(Args.Device.Type + " attached.");
}
catch (Exception _exc)
{
throw new Exception(className + " protected void phidgets_Attach( Sender, Args) :: " + _exc.Message +
"\n");
}
} //phidgets_Attach
///
/// handle the phidget device discovery events
///
/// /// protected void phidgets_Detach(object Sender, DetachEventArgs Args)
{
try
{
Console.WriteLine(Args.Device.Type + " detached.");
}
catch (Exception _exc)
{
throw new Exception(className + " protected void phidgets_Detach( Sender, Args) :: " + _exc.Message +"\n");
}
} //phidgets_Detach
protected void phidgets_Error(object Sender, ErrorEventArgs Args)
{
try
{
Console.WriteLine("phidgets error : " + Args.Code + " " + Args.Description);
}
catch (Exception _exc)
{
throw new Exception(className + " protected void phidgets_Error( Sender, Args) :: " + _exc.Message +
"\n");
}
} //phidgets_Error
///
/// reads the acceleration from the Phidgets accelerometer
///
/// accelerometer object/// essentially an array of three doubles, one for each direction measuredprotected void _acc0_AccelerationChange(object Sender, AccelerationChangeEventArgs Args)
{
try
{
rawAcc[Args.Index] = Args.Acceleration;
}
catch (Exception _exc)
{
Console.WriteLine(
className + " protected void _acc0_AccelerationChange( Sender, Args) :: " + _exc.Message + "\n"
);
}
} //_acc0_AccelerationChange
#endregion
Another helper method that is constantly requested is converting from accelerations to roll and pitch. You can do the trigonometry yourself, but if gravitation is assumed to act in the -Z direction you can work out the basic orientation of the accelerating object. This can be fooled by large or quick orientation changes, but for the most part sampling frequency can fix this. So I would make sure that you do as little as possible that may muddy the event handler system. They are really fast and that is a good thing in this case.
///
/// calculate the euler angles from the local accelerations
///
/// acceleration toward the right wing, g [gravity multiples]/// acceleration toward the nose, g [gravity multiples]/// acceleration toward the ground, g [gravity multiples]/// headingprivate static void accel2euler(double Ax, double Ay, double Az, double Compass, out double[] EulerAngles)
{
EulerAngles = new double[3];
try
{
double g = Math.Sqrt(Ax * Ax + Ay * Ay + Az * Az);
/* Roll */
if (g != 0)
{
//EulerAngles[0]=Math.Atan2(Ay,Az);
EulerAngles[0] = Math.Atan2(Ay/g, -Az/g);
}else
{
EulerAngles[0] = Math.Atan2(Ay / 1, -Az / 1);
}
/* Pitch */
if (g != 0)
{
//EulerAngles[1] = Math.Asin(Ax/-g);
EulerAngles[1] = Math.Atan2(Ax / g, -Az / g);
}
else
{
EulerAngles[1] = Math.Atan2(Ax / 1, -Az / 1);
}
EulerAngles[2] = Compass; /* Yaw */
}
catch (Exception _exc)
{
throw new Exception(className + " public static void accel2euler( , " + Ax.ToString("0.000") + " , " +
Ay.ToString("0.000") + " , " + Az.ToString("0.000") + " , " +
Compass.ToString("0.000") + " ) :: " + _exc.Message + "\n");
}
}
The one thing you will notice is that you cannot get the yaw from the accelerations. That makes sense if you think about it, flat rotation perpendicular to gravity would not be measured. I usually run a compass in the systems too. That makes the 3-1-3 rotation easy to move between body reference frames and global reference frames. I would suggest that you multiply out the cells for the rotations in a separate method each so that you can just multiply them by calling each method in turn with an argument of the last rotation.
Driving Business to Your Website
This is one of the mor difficult aspects of internet marketing and small businesses. Many others can spend more resrouces to get the word out at any given time. I have tried to approach it from a step-wise perspective. First step was to get the basic website out, without content you have nothing. A buddy of mine said to make sure that you do not make sure that you do not cludder ideas or muddy your message trying to stuff too much on each page. There are plenty of ways to make the search engines pick up your content in systematic ways.
Next, gather up your all of your suppliers or products that you normally use and make a simple page that links out to their official pages, that way your name or website will be linked to theirs. This will not in and of itself make a huge contribution, but if they look up this junk sucks, it will bring up your name. ;) As they say, any advertising where they spell your name correctly, is good advertising.
I am not sure if this next step was the best, but I found some of the low cost tshirt and mouse pad sites and through a bunch of products out there. People in general would not associate technical ideas with a tshirt. However, it gives you a different lane of approach to your content. Make sure that you fill out the description sections of each item and try to make sure your main url shows up in as many places as possible. These link backs help your search engine scores and increase the possibility that someone will click through to your site. Traffic, even bounce traffic is good. You never know whose little brother will see a t-shirt with a logo and pass it onto their brother the director of your next customer's organization.
Another simple and seemingly the most effective plan of attack. Use your open source community. They are mindless minions of habit. Ok, that is a bit harsh. However, Sourceforge, CodePlex and similar sites have huge mostly anonymous traffic, if you can publish any of your source code as a project and link back to your website you will get the word out to a large audience of people
with similar interests. I have found that techies run in circles and that they are inexoribly drawn to cool projects even if they are not in their fields of expertise. Likewise, if you use a product that has a user community, by all means post. Try to be as active as possible and keep posting your url in your signature. That link back thing is the cheapest and simplest advertising you can achieve.
If you can manage it, you may also put up single page advertising sites with kind of universal message information on any of the better trafficked free hosting sites. Google, Microsoft and all of the 500 pound apes have free sites. Free is good, at this point you are trading time for initial expense. So put up your message pages and cross-link them as best as you can without making them look like the original Yahoo. Different url's linking back help increase your score. If they get you 2% more hits every month then you are 2% ahead for copying and pasting an advertisement to a database somewhere. When it gets taken down in six months for lack of updates, oh well, it was free.
Tweets that get sucked into the ether by retweeters are good too. However, it is not as guaranteed a method because they are simple text messages and can carry less information than the free poster sites. By all means, spam the web with your message. With billions if not trillions of pages, make sure that you get your information out there in as many places as possible.
Blogging is my last idea, but it is not as effective. Just from a time perspective you have to keep putting into it and that makes it more expensive than just chucking out some posters. Posters are good because you can have a graphical message. Even back in the day...
Tamany Hall said they did not care what they wrote, their constituents could not read... They could UNDERSTAND pictures.
Next, gather up your all of your suppliers or products that you normally use and make a simple page that links out to their official pages, that way your name or website will be linked to theirs. This will not in and of itself make a huge contribution, but if they look up this junk sucks, it will bring up your name. ;) As they say, any advertising where they spell your name correctly, is good advertising.
I am not sure if this next step was the best, but I found some of the low cost tshirt and mouse pad sites and through a bunch of products out there. People in general would not associate technical ideas with a tshirt. However, it gives you a different lane of approach to your content. Make sure that you fill out the description sections of each item and try to make sure your main url shows up in as many places as possible. These link backs help your search engine scores and increase the possibility that someone will click through to your site. Traffic, even bounce traffic is good. You never know whose little brother will see a t-shirt with a logo and pass it onto their brother the director of your next customer's organization.
Another simple and seemingly the most effective plan of attack. Use your open source community. They are mindless minions of habit. Ok, that is a bit harsh. However, Sourceforge, CodePlex and similar sites have huge mostly anonymous traffic, if you can publish any of your source code as a project and link back to your website you will get the word out to a large audience of people
with similar interests. I have found that techies run in circles and that they are inexoribly drawn to cool projects even if they are not in their fields of expertise. Likewise, if you use a product that has a user community, by all means post. Try to be as active as possible and keep posting your url in your signature. That link back thing is the cheapest and simplest advertising you can achieve.
If you can manage it, you may also put up single page advertising sites with kind of universal message information on any of the better trafficked free hosting sites. Google, Microsoft and all of the 500 pound apes have free sites. Free is good, at this point you are trading time for initial expense. So put up your message pages and cross-link them as best as you can without making them look like the original Yahoo. Different url's linking back help increase your score. If they get you 2% more hits every month then you are 2% ahead for copying and pasting an advertisement to a database somewhere. When it gets taken down in six months for lack of updates, oh well, it was free.
Tweets that get sucked into the ether by retweeters are good too. However, it is not as guaranteed a method because they are simple text messages and can carry less information than the free poster sites. By all means, spam the web with your message. With billions if not trillions of pages, make sure that you get your information out there in as many places as possible.
Blogging is my last idea, but it is not as effective. Just from a time perspective you have to keep putting into it and that makes it more expensive than just chucking out some posters. Posters are good because you can have a graphical message. Even back in the day...
Tamany Hall said they did not care what they wrote, their constituents could not read... They could UNDERSTAND pictures.
Subscribe to:
Posts (Atom)

