时间积分结果异常:基于Pandas的加速度转位置计算偏差问题
Fixing Acceleration Integration for Position Calculation: Correcting Scipy & Resampling Logic
Let's break down what's going wrong in your code and fix it step by step—your approach is on the right track, but a few key missteps are causing the incorrect results.
What's Wrong With the Original Code?
- Misusing Rolling Window Integration: The
rolling().apply(integrate.trapz)call computes the integral over a sliding window, not the cumulative integral from the start time to the current time. This leads to repeated calculations and inflated values, which explains why your results are way larger than manual Excel calculations. - Undefined
timedelta_base: Your code references this variable but doesn't define it—this would cause unpredictable resampling intervals, messing up the entire workflow. - Ignoring Initial Conditions: Integration requires starting values (initial velocity and position, usually 0 if not specified), which weren't explicitly handled.
- Zero Results Without Resampling: When you skip resampling, the rolling window likely only includes a single data point each time. The trapezoidal integral of a single point is zero, hence the all-zero DataFrame.
Corrected Code
Here's a revised version that fixes all these issues and aligns with your goal of generating position data for Blender keyframes:
import pandas as pd from scipy import integrate # 1. Configure Blender frame rate and time base cur_fps = 25 # Match your Blender scene's FPS frame_interval = 1 / cur_fps # Time per frame (e.g., 0.04s for 25fps) timedelta_us = frame_interval * 1_000_000 # Convert to microseconds for pandas resample # 2. Load acceleration data acc_table = pd.read_excel("C:/Temp/exampleaccelerations.xlsx", index_col=0) # Convert numeric time (seconds) to pandas timedelta for reliable resampling acc_table.index = pd.to_timedelta(acc_table.index, unit="s") # 3. Resample to Blender's frame interval (linear interpolation to fill gaps) acc_interpolated = acc_table.resample(f"{timedelta_us}us").interpolate(method="linear") # 4. Calculate time intervals (in seconds) for integration dt = acc_interpolated.index.total_seconds().diff().fillna(0) # 5. First integral: Acceleration → Velocity (cumulative trapezoidal integration) vel_x = integrate.cumulative_trapezoid(acc_interpolated["acc_x"], dx=dt, initial=0) vel_y = integrate.cumulative_trapezoid(acc_interpolated["acc_y"], dx=dt, initial=0) vel_table = pd.DataFrame({"vel_x": vel_x, "vel_y": vel_y}, index=acc_interpolated.index) # 6. Second integral: Velocity → Position (cumulative trapezoidal integration) pos_x = integrate.cumulative_trapezoid(vel_table["vel_x"], dx=dt, initial=0) pos_y = integrate.cumulative_trapezoid(vel_table["vel_y"], dx=dt, initial=0) pos_table = pd.DataFrame({"pos_x": pos_x, "pos_y": pos_y}, index=acc_interpolated.index) # 7. Prepare data for Blender keyframes (align with frame numbers) pos_for_blender = pos_table.resample(f"{timedelta_us}us").first() pos_for_blender["frame"] = range(1, len(pos_for_blender) + 1) print(pos_for_blender)
Key Improvements Explained
- Cumulative Integration:
scipy.integrate.cumulative_trapezoidis designed exactly for this use case—it computes the integral from the start of the dataset to each point, which is what we need to get velocity from acceleration, then position from velocity. No more sliding window errors. - Explicit Time Handling: Converting the time index to
timedeltaensures pandas resamples correctly, avoiding confusion between numeric seconds and datetime formats. - Accurate Time Intervals: Calculating
dtdirectly from the interpolated time index ensures we use the exact time between each data point for integration, which is critical for accuracy. - Initial Conditions: The
initial=0parameter sets starting velocity and position to 0 (adjust this if your object has an initial velocity/position). - Blender Alignment: Resampling to the exact frame interval ensures each row in
pos_for_blendercorresponds to a Blender frame, making it easy to import as keyframes.
How to Verify
To check if the results are correct, compare the first few values to manual calculations. For example:
- Between 0.1s and 0.2s, the x-acceleration goes from 0 to -0.98. The trapezoidal integral (velocity change) is
(0 + (-0.98)) * 0.1 / 2 = -0.049—yourvel_xvalue at 0.2s should match this.
内容的提问来源于stack exchange,提问作者haarigertroll
相关产品推荐
相关产品推荐

