Discretizing Motion - ksoltan/RoboFish GitHub Wiki
A real fish is flexible and its movement is modeled with a smooth, continuous function, often a sinusoid. To replicate its movement in a robotic, multi-jointed fish, the smooth function needs to be discretized to find where each of the joints should be positioned to best approximate the movement. One of the possible advantages of putting a soft skin around these rigid linkages is that it will smooth the transition between each discrete joint's position.
Liu and Hu's paper, Biological Inspiration: From Carangiform Fish to Multi-Joint Robotic Fish, describes an algorithm for approximating a smooth swimming pattern with a multi-jointed fish. It uses a different error function, as opposed to root mean square method (RMS), which produces a more accurate approximation of the function.
Each behavior, or different type of motion, like cruising straight, has a different model or formula that defines at each point in time where each part of the body of the fish wants to be. Each joint has a certain length and must be straight for that length, so the trick is to position the joint in such a way that the least square mean is minimized between that section of curve and the straight line joint. Although our fish should not be rigid, this algorithm is at least a place to start; parameters can be fine tuned later. One question I have is whether this least mean is only for that section of curve or for the whole structure. Presumably it’s the first, because it would be computationally hard to run through every possible combination of the joints. I will for now assume this, should check in paper.
To make the algorithm simple, three points are defined on each joint: the front, cross, and back. For each consecutive joint, the back and front are the same, so starting from the first joint, once you have it aligned, the front for the next joint is defined and you simply have to figure out where to put the back point. The first joint’s front starts on the sinusoid. Minimizing the error with the whole back point is hard because the point could be anywhere in space. To restrict the number of possible places it could, the cross point comes into play. The cross point is where the joint crosses, or is tangent to, the sinusoid. The ratio of the length of the segment to the cross point to the length of the joint can be cycled through, from 0 to 1. Given each length, you can calculate where the joint must intersect the curve for the ratio to be valid. (if the curve is continuous, there should be a solution for every single ratio, but this may create problems in discrete things like Matlab). Although you could theoretically just go along the curve until the distance from the curve to the front point exceeds the length of the joint, this would not weight each ratio equally, and would be hard to control in terms of how far along the curve do you need to go, possibly iterating through more points than you need to (but, perhaps finding the intersection for each point is harder…)(Hmm, I’m actually not convinced anymore that using the cross ratio is better.) Once you calculate the cross point, it is extremely simple to find the end point and then calculate the error. After each end point is minimized in error, you can get the angle relative to the joint, which is just the slope of the joint relative to horizontal.
So far, I have implemented an approximation of the joints to a specific posture. I do not take into account the entire body, and simply minimize the error in the first joint and then keep going. This may not be a good approach because it may be ignoring the optimizations that could happen from a not perfect minimized angle on the first joint. I also am not sure what is happening in the paper, and what exactly they mean about minimizing the magnitude of the error because my error is not a vector, it’s a scalar...Also, how do they compensate for the head movement/added-mass (that’s the vector question).