在步进电机位置-电阻映射数组中求特定距离的第二大峰值
Nice project! Let's break down how to pinpoint the cricoid cartilage (your "lower point")—the second highest resistance peak that also meets specific distance requirements from the thyroid cartilage (your "upper point") stored in your points[stepper_motor_location][resistance] HashMap.
Here's a practical, Arduino-focused solution with two approaches depending on your peak definition:
1. First, Capture the Upper Peak (Thyroid Cartilage)
You already know how to do this, but we need to store both its resistance value and stepper position for later distance checks:
#include <HashMap.h> // Assuming your HashMap is structured as: key = stepper position, value = resistance HashMap<int, int> points; int maxResistance = 0; int maxPosition = -1; // First pass: Locate the highest resistance peak (thyroid cartilage) for (auto it = points.begin(); it != points.end(); ++it) { int currentPos = it->first; int currentRes = it->second; if (currentRes > maxResistance) { maxResistance = currentRes; maxPosition = currentPos; } }
2. Option 1: Find the Second Highest Global Resistance (With Distance Check)
If your cricoid cartilage's resistance is simply the second highest overall (not just a local peak), use this second pass to filter candidates that fit your distance constraints:
int secondMaxResistance = 0; int secondMaxPosition = -1; // Adjust these values to match your project's anatomical requirements const int MIN_VALID_DISTANCE = 5; // Example: minimum 5 stepper steps apart const int MAX_VALID_DISTANCE = 20; // Example: maximum 20 stepper steps apart // Second pass: Hunt for the valid second-highest resistance for (auto it = points.begin(); it != points.end(); ++it) { int currentPos = it->first; int currentRes = it->second; int positionDistance = abs(currentPos - maxPosition); // Skip the upper peak's position, check resistance hierarchy, and validate distance if (currentPos != maxPosition && currentRes < maxResistance && currentRes > secondMaxResistance && positionDistance >= MIN_VALID_DISTANCE && positionDistance <= MAX_VALID_DISTANCE) { secondMaxResistance = currentRes; secondMaxPosition = currentPos; } } // Validate and output the result if (secondMaxPosition != -1) { Serial.print("Cricoid cartilage found at position: "); Serial.println(secondMaxPosition); Serial.print("Resistance value: "); Serial.println(secondMaxResistance); } else { Serial.println("No valid cricoid candidate found—check distance thresholds or sensor data."); }
3. Option 2: Find the Second Highest Local Peak (More Anatomically Accurate)
In real-world scenarios, the cricoid cartilage is likely a local peak (higher resistance than its adjacent positions) rather than just the second highest global value. Here's how to handle this:
Step 3.1: Collect All Local Peaks
First, identify all positions where resistance is higher than both neighboring positions:
#include <vector> #include <algorithm> vector<pair<int, int>> allPeaks; // Stores (position, resistance) for each peak // Sort stepper positions to ensure we can check adjacent points vector<int> sortedPositions; for (auto it = points.begin(); it != points.end(); ++it) { sortedPositions.push_back(it->first); } sort(sortedPositions.begin(), sortedPositions.end()); // Detect all local peaks for (int i = 0; i < sortedPositions.size(); ++i) { int currentPos = sortedPositions[i]; int currentRes = points[currentPos]; bool isPeak = false; // Check first position (only compare to next) if (i == 0 && sortedPositions.size() > 1) { int nextRes = points[sortedPositions[i+1]]; isPeak = (currentRes > nextRes); } // Check last position (only compare to previous) else if (i == sortedPositions.size() - 1 && sortedPositions.size() > 1) { int prevRes = points[sortedPositions[i-1]]; isPeak = (currentRes > prevRes); } // Check middle positions (compare to both neighbors) else if (i > 0 && i < sortedPositions.size() - 1) { int prevRes = points[sortedPositions[i-1]]; int nextRes = points[sortedPositions[i+1]]; isPeak = (currentRes > prevRes && currentRes > nextRes); } if (isPeak) { allPeaks.push_back({currentPos, currentRes}); } }
Step 3.2: Sort Peaks and Filter for Distance
Sort peaks by resistance (highest to lowest), then pick the first valid candidate that meets your distance rule:
// Sort peaks in descending order of resistance sort(allPeaks.begin(), allPeaks.end(), [](const pair<int, int>& a, const pair<int, int>& b) { return a.second > b.second; }); int cricoidPos = -1; int cricoidRes = 0; // Skip the upper peak, find the next valid candidate for (int i = 1; i < allPeaks.size(); ++i) { int peakPos = allPeaks[i].first; int peakRes = allPeaks[i].second; int distance = abs(peakPos - allPeaks[0].first); if (distance >= MIN_VALID_DISTANCE && distance <= MAX_VALID_DISTANCE) { cricoidPos = peakPos; cricoidRes = peakRes; break; } } // Output the result if (cricoidPos != -1) { Serial.print("Valid cricoid peak at position: "); Serial.println(cricoidPos); Serial.print("Resistance: "); Serial.println(cricoidRes); } else { Serial.println("No valid cricoid peak found. Adjust thresholds or check sensor noise."); }
Key Tips for Success
- Filter Noise: Add a simple moving average to your resistance readings before storing them—this will reduce false peaks from sensor interference.
- Calibrate Thresholds: Test with known anatomical positions to set
MIN_VALID_DISTANCEandMAX_VALID_DISTANCEto match real neck anatomy. - Handle Edge Cases: If no valid candidate is found, add fallback logic (e.g., re-sample data, adjust thresholds) to keep your project running smoothly.
内容的提问来源于stack exchange,提问作者Xaiko

