You will recall that in my initial sensing application I failed to check to see if I could detect buttsex. Well, I am pleased to report that I have progressed somewhat from that! It took a while for me to work up the nerve, because my mold is a little thick and it’s been a while, if you know what I mean.
Anyway, science and a little boredom gave me the opportunity to test the insertable toy with all three gestures I wanted to detect.
You may recall that a hand job is quite unique with very clear signals from all of the sensors:
What is especially unique about the hand job is typically the hand can’t stimulate the entire shaft when it’s fully “in” this results in the tip of the toy poking out of your hand. Even if you had a particularly large hand, i would hazard that because of the shape of your hand, the tip would still lose stimulus at the peak of the “in” stroke.
A blow job is similar except that the tip gets stimulated in varied and complex ways when it enters the mouth, likely due to saliva. Also, I personally wasn’t about to uniformly stimulate the base of the shaft with my mouth alone.
Finally, the data you have all been waiting for. Insertion into the butt looks like so:
Note that it’s a very different story to the previous two data sets. the tip is stimulated on entry and is essentially always stimulated throughout. This is even when I withdrew it as far as I dared. I think this is because even when it’s no longer inserted, your body is still close enough to the device to act as a capacitive body, even without direct contact or pressure.
With the above data I was able to crudely detect the difference between a hand job and butt stuff using the DTW algorithm “most of the time”. Evidence suggests I will need to improve my normalisation algorithm because in cases where a dataset is “flat” (e.g. as in the butt stuff), the normalisation tends to unnecessarily amplify noise, which can result in false positives. I also suspect that the 8 point moving average might be a little too aggressive.
After my little stint of research, I set about putting the theory into practice. Before I go into it, here is a video of detection working (warning, contains bodily fluids).
Warning, this video contains bodily fluids.
Fluids in order: water, lube, salt water, urine, semen.
My laptop keyboard still has suspicious fluids on it…
Please note the above video is a best case scenario and a lot of testing is still required!
My first attempt was to just pass 5v into various samples and see what they did. I used the #2 digital output pin on the Arduino to control whether or not any power was sent to the sample and a 10 kΩ shunt resistor so I could measure the current across the sample by reading the A0 analog in for the Arduino. I measured the current once every 10 ms for 2 seconds, then rested the sample for 2 seconds.
The results were encouraging.
The graph below shows one round of stimulation of a sample of water, the orange line represents voltage in (5v) and the blue line is the current measurement. You can see I rest the sample between trials for 2 seconds (important).
The following shows the change in current measured in a sample of cum.
So, there’s definitely something happening, the current across the sample is changing for the duration of the stimulation (2 seconds), but how to get a more meaningful comparison? I knew that I needed at least 1.23 v to electrolise water into into oxygen and hydrogen, but I didn’t want to use much more than that. I used a simple voltage divider made from two 22 k Ω resistors, resulting in something close to 1.8 v across the sample, which seemed to work OK.
After taking many samples and calculating an average for each sample, I could say with confidence that on average, a 2 second stimulation of the various samples looks like this:
Now, it looks pretty cut & dry: cum has on average a much much lower final current after 2 seconds. Why not just measure the current value after 2 seconds of stimulation and if it’s below a threshold (say 35 in the example above), then it’s cum? Well, the problem is that this is an average, the real data is a whole lot messier:
The fact that cum has a very distinctive “shape” on the average graph gave me the encouragement to try harder to untangle signal from the noise.
To overcome the variability in the data I did two things: firstly I took a 5 point moving average for all points, to smooth them out a little. I then expressed every set of 5 points as a ratio of the first 5 points. So, to get the value for point 8, I would calculate Average(Points(8-12))/Average(Points(1-5)), which is actually the same as Sum(Points(8-12))/Sum(Points(1-5)).
This resulted in the following graph (once again, taken as an average):
That’s all very well, but this is still an average, how do we handle the fact that each trial (each time I stimulate a sample) may have variability to it? Looking at the minimum and maximums rather than the averages, we get this:
If you look carefully, you can see at about 10 or 15 (between 100 and 150 ms), there’s a promising gap between all other minimums and the maximum value for cum. I focused my attention on this ratio.
So, that’s it right? If the ratio between the first 5 points and points 10-15 is less than 0.8, we have cum! Well, yes and no. As I said before, by passing a current through the sample, we are actually changing it, so we need to consider how the nature of the sample changes over time. Also, I wanted to speed up the time taken to get a result, up until now, I was stimulating for 2 seconds and resting for 2 seconds, that was quite slow for the detection I wanted.
So, I sped it up, this time allowing the sample to rest only 100 ms and stimulating for only 200. I then recorded the ratio and plotted it over time. So, the graph below is showing many hundreds of trials (a cycle of stimulation and rest for the sample), where the x-axis is the trial number.
Saliva appears to be quite unstable over time. All other samples I used appear to stabilise well above the ratio for cum. Saliva, however, comes dangerously close. To be fair, I don’t mind so much if I get false positives on saliva since I am not expecting saliva to find it’s way inside the masturbator toy.
I am still worried that the samples do change a fair bit over time, making stable readings difficult. I also note that my simple copper electrodes may not be good enough. The positive electrode slowly builds up a black layer of oxidation, probably from the electrolysis.
Simple code for the detector is here: voltammetry2.sdf.ino
It’s been referred to as the “holy grail” of teledildonics, and in my hubris, I want to have a go at detecting male ejaculation. Why ejaculation? Well, this is specifically for uses where someone is playing with a male masturbator toy and they climax. Wouldn’t it be great if they got some kind of feedback for their effort? Maybe the game gives them a reward or the content changes somewhat. Without detecting their climax, there’s no way for the system to do so.
Such a detector would need to be:
I set about researching a number of techniques which I thought would bear fruit:
Florescence: The first thought one might have is to do what they do in the movies and use “black light” or UV. From reading this post on the florescence of semen, it turns out that you need Luminol to trigger semen’s fluorescence with UV, though it sill fluoresce under blue light. Besides all that, these fluorescence based tests only appear to work on dry semen, not liquid semen. This fails the “immediate” test.
pH: At between 7 and 8 on the pH scale, semen is slightly basic, but not enough that using a pH sensor is going to give you a distinguishing marker verus, say, tap water. Also, this pH would probably can vary from person to person. Finally, the pH sensors I have seen are rather bulky.
Spectral Analysis: From semen’s spectral response it looks like the 1650 cm-1 wave number range is good for detecting cum. Detection works this way because certain organic compounds in semen vibrate at a certain frequency. These compounds are found in many other organic samples. The problem with this approach is, this frequency is in the mid-range IR, which is very expensive to produce and detect since it’s so close to heat. It would require expensive specialised apparatus to do it this way and it would most likely both destroy the sample and possibly burn your penis in the process.
Resistance: I tried measuring the resistance of cum using various approaches, but just when I thought I understood how it related to other fluids, I got different readings. Besides which, urine (at approximately 70k ohms) is quite a good conductor compared to cum (about 700k ohms).
Electro-chemical: After reading this paper about detecting chemicals. It made sense to me that whatever technique is used to detect glucose in blood or specific ions in solution should be able to work with cum, because I knew cum contained some salts, in particular sodium and potassium ions (see Biochemistry of semen and the Wikipedia page for semen). We were finally getting somewhere!
Voltammetry: A technique known as Voltammetry, passes a known voltage through a sample and observes how the current through the sample changes over time. This recognises the fact that the act of passing a current through a solution will perform some kind of electrolysis on the solution.
Finally, the phenomenon where semen’s resistance changed over time made sense! You see, whenever you pass a current (no matter how small) through a sample such as semen, you are going to change its chemical composition somewhat. We can measure that change by measuring a change in current.
Next, I actually implement a voltammetric apparatus for detecting cum.
So, I have gesture detection working relatively well, the next hurdle is speed of the gesture. It sounds like a relatively simple problem to solve, but it’s deceptively complex, especially since we’re dealing with a series of data points.
In the video above, I am using a simple moving average on stream 3 of the input. Whenever the current data point drops below the moving average, that’s considered an “out”, when it drops above, that’s considered an “in”, the result is data that looks something like this:
Whenever the data value crosses the moving average in any direction, I consider that a “tick”. I then count the number of ticks in the last n samples to get an average speed during those samples.
It works surprisingly well, you could increase the number of samples to get a smoother speed calculation, but I think a responsive value is better. I am currently summing across 16 ticks.
In theory, a Fast Fourier Transform should be able to give me the frequency of the signal I am recording and that frequency could be used to approximate speed of the “hand job” gesture. In practice, I think the moving average approach is relatively computationally cheap as well as robust.
I am pleased to report that the stream of data I have been collecting off the insertable device can be used to detect different user gestures. Gestures you ask? Well, I want to be able to tell what the user is doing with the device (e.g. blowjob, licking, hand job and penetrative buttsex). Not sure if I can tell the difference between a vagina and a butt, but why not try?
The video below shows the device distinguishing between blow jobs and hand jobs.
The detection algorithm is taken from the excellent Kinect DTW implementation.
Dynamic Time Warping (or DTW) is a great little solution for matching time-series data where the data points might be stretched or squashed over time. Apart from detecting blow jobs it has been used for speech recognition among other things.
I retrieve the stream of 8 data points from the device, let’s call a collection of these 8 data points a set. I get a set every 100 ms. When I have more than 8 sets of data, I attempt to match those 8 sets of 8 data points to a prerecorded “example” sequence of 32 sets in memory using the Dynamic Time Warping algorithm.
The image below is an example sequence of a “hand job” gesture:
Because lube and other environmental factors can change the baseline considerably, I “normalise” the data to a value from 0 to 1 for each independent stream (line) of data. This seems to be a pretty robust approach.
Normalising in this way is helpful, especially if you consider that the conductive silicone will also have a capacitance and due to my imperfect construction process, I can’t guarantee this will be consistent in any way.
A last step (which I haven’t yet tried but will shortly) is to apply a simple moving average to smooth the data out. This should result in more reliable matches.
I have been able to get this same algorithm working in C# as well as Renpy, a Python based gaming engine I intend to use for a game that interacts with the device. Unfortunately Renpy is a little too slow for the processing and is not really designed for this kind of real-time processing anyway.
move the gesture recognition processing onto the arduino itself for performance reasons. Turns out there’s not enough memory to implement a DTW algorithm for more than one gesture on an arduino. Never mind, I learnt how to do threads in Renpy instead (renpy.invoke_in_thread).