第9章 平面向量与极坐标系分析及其应用
本文介绍了向量值函数的微积分运算及其应用。主要内容包括:向量值函数的定义与极限,其导数表示曲线切向量,微分运算规则;考研数学中的典型例题解析,如求导数、二阶导数和单位切向量;商业应用方面,展示机器人路径规划中如何利用向量值函数分析速度和加速度;最后通过MATLAB实现向量值函数的微积分计算、单位切向量求解和曲率计算。文章将理论分析与实际应用相结合,为工程数学问题提供了实用解决方案。
平面向量与极坐标系分析及其应用
9.3 向量值函数的微积分运算
9.3.1 向量值函数的定义与极限
向量值函数是将实数映射到向量的函数,形式为:
[
\vec{r}(t) = \langle f(t), g(t) \rangle = f(t)\vec{i} + g(t)\vec{j}
]
其中 (f(t)) 和 (g(t)) 是实值函数,分别表示向量在 x 轴和 y 轴上的分量。
向量值函数的极限定义为各分量极限的组合:
[
\lim_{t \to t_0} \vec{r}(t) = \langle \lim_{t \to t_0} f(t), \lim_{t \to t_0} g(t) \rangle
]
当且仅当各分量的极限存在时,向量值函数的极限存在。
9.3.2 向量值函数的导数与微分
向量值函数的导数定义为:
[
\vec{r}‘(t) = \lim_{\Delta t \to 0} \frac{\vec{r}(t+\Delta t) - \vec{r}(t)}{\Delta t} = \langle f’(t), g’(t) \rangle
]
几何意义:导数向量 (\vec{r}'(t)) 表示曲线在点 (\vec{r}(t)) 处的切向量。
向量值函数的微分:
[
d\vec{r} = \vec{r}‘(t) dt = \langle f’(t) dt, g’(t) dt \rangle
]
高阶导数可类似定义。向量值函数的求导法则:
- 常数倍:((c\vec{r}(t))’ = c\vec{r}'(t))
- 和差:((\vec{u}(t) \pm \vec{v}(t))’ = \vec{u}‘(t) \pm \vec{v}’(t))
- 数乘(点积):((\vec{u}(t) \cdot \vec{v}(t))’ = \vec{u}‘(t) \cdot \vec{v}(t) + \vec{u}(t) \cdot \vec{v}’(t))
- 链式法则:(\frac{d}{dt} \vec{r}(u(t)) = \vec{r}‘(u(t)) u’(t))
9.3.3 考研数学中的向量值函数问题
例题:设向量值函数 (\vec{r}(t) = \langle t^2, \ln(1+t) \rangle),求 (\vec{r}‘(t)) 和 (\vec{r}’'(t)),并求在 (t=1) 处的单位切向量。
解:
[
\vec{r}‘(t) = \langle 2t, \frac{1}{1+t} \rangle
]
[
\vec{r}’‘(t) = \langle 2, -\frac{1}{(1+t)^2} \rangle
]
当 (t=1) 时:
[
\vec{r}’(1) = \langle 2, \frac{1}{2} \rangle = \langle 2, 0.5 \rangle
]
模长为:
[
|\vec{r}‘(1)| = \sqrt{2^2 + (0.5)^2} = \sqrt{4 + 0.25} = \sqrt{4.25} = \frac{\sqrt{17}}{2}
]
单位切向量为:
[
\vec{T}(1) = \frac{\vec{r}’(1)}{|\vec{r}'(1)|} = \left\langle \frac{2}{\sqrt{4.25}}, \frac{0.5}{\sqrt{4.25}} \right\rangle = \left\langle \frac{4}{\sqrt{17}}, \frac{1}{\sqrt{17}} \right\rangle
]
9.3.4 商业应用:机器人路径规划中的运动分析
在工业机器人路径规划中,末端执行器的位置通常用向量值函数描述。设机器人末端在平面内的运动轨迹为:
[
\vec{r}(t) = \langle x(t), y(t) \rangle
]
其中 (t) 表示时间。
速度向量:
[
\vec{v}(t) = \vec{r}‘(t) = \langle x’(t), y’(t) \rangle
]
加速度向量:
[
\vec{a}(t) = \vec{r}‘’(t) = \langle x’‘(t), y’'(t) \rangle
]
在实际应用中,需要确保速度、加速度不超过机器人的物理限制。例如,设机器人沿椭圆轨迹运动:
[
\vec{r}(t) = \langle 2\cos(t), \sin(t) \rangle, \quad 0 \leq t \leq 2\pi
]
则:
[
\vec{v}(t) = \langle -2\sin(t), \cos(t) \rangle
]
[
|\vec{v}(t)| = \sqrt{4\sin^2(t) + \cos^2(t)} = \sqrt{3\sin^2(t) + 1}
]
最大速度发生在 (\sin^2(t)=1) 时,即 (|\vec{v}|_{\text{max}} = \sqrt{3+1} = 2)。
加速度:
[
\vec{a}(t) = \langle -2\cos(t), -\sin(t) \rangle
]
[
|\vec{a}(t)| = \sqrt{4\cos^2(t) + \sin^2(t)} = \sqrt{3\cos^2(t) + 1}
]
最大加速度发生在 (\cos^2(t)=1) 时,即 (|\vec{a}|_{\text{max}} = \sqrt{3+1} = 2)。
通过分析速度和加速度,可以优化机器人的运动轨迹,提高效率并减少磨损。
9.3.5 MATLAB实现:向量值函数的微积分与路径分析
classdef VectorValuedFunction
properties
XFunction
YFunction
end
methods
function obj = VectorValuedFunction(xFunc, yFunc)
obj.XFunction = xFunc;
obj.YFunction = yFunc;
end
function r = evaluate(obj, t)
% 计算向量值函数在t处的值
x = obj.XFunction(t);
y = obj.YFunction(t);
r = [x, y];
end
function dr = derivative(obj, t, method)
% 计算导数,method可选 'analytic' 或 'numeric'
if nargin < 3
method = 'analytic';
end
if strcmp(method, 'analytic')
% 解析导数(需要符号计算)
syms s;
x_sym = obj.XFunction(s);
y_sym = obj.YFunction(s);
dx = diff(x_sym, s);
dy = diff(y_sym, s);
dr = [double(subs(dx, s, t)), double(subs(dy, s, t))];
else
% 数值导数(中心差分)
h = 1e-5;
r_plus = obj.evaluate(t + h);
r_minus = obj.evaluate(t - h);
dr = (r_plus - r_minus) / (2*h);
end
end
function d2r = secondDerivative(obj, t)
% 计算二阶导数
syms s;
x_sym = obj.XFunction(s);
y_sym = obj.YFunction(s);
d2x = diff(x_sym, s, 2);
d2y = diff(y_sym, s, 2);
d2r = [double(subs(d2x, s, t)), double(subs(d2y, s, t))];
end
function tangent = unitTangent(obj, t)
% 计算单位切向量
dr = obj.derivative(t);
norm_dr = norm(dr);
if norm_dr == 0
error('导数为零向量,无法计算单位切向量');
end
tangent = dr / norm_dr;
end
function curvature = computeCurvature(obj, t)
% 计算曲率 κ = |x'y'' - y'x''| / (x'^2 + y'^2)^(3/2)
dr = obj.derivative(t);
d2r = obj.secondDerivative(t);
x_prime = dr(1);
y_prime = dr(2);
x_double_prime = d2r(1);
y_double_prime = d2r(2);
numerator = abs(x_prime * y_double_prime - y_prime * x_double_prime);
denominator = (x_prime^2 + y_prime^2)^(1.5);
if denominator == 0
curvature = inf;
else
curvature = numerator / denominator;
end
end
function arcLength = computeArcLength(obj, a, b, n)
% 计算从t=a到t=b的弧长,使用n个子区间进行数值积分
% 弧长公式:∫_a^b ||r'(t)|| dt
if nargin < 4
n = 1000;
end
t_values = linspace(a, b, n+1);
length_segments = zeros(1, n);
for i = 1:n
t_mid = (t_values(i) + t_values(i+1)) / 2;
dr = obj.derivative(t_mid, 'numeric');
speed = norm(dr);
length_segments(i) = speed * (t_values(i+1) - t_values(i));
end
arcLength = sum(length_segments);
end
function plotPath(obj, t_start, t_end, numPoints)
% 绘制路径
if nargin < 4
numPoints = 1000;
end
t = linspace(t_start, t_end, numPoints);
points = zeros(numPoints, 2);
for i = 1:numPoints
points(i, :) = obj.evaluate(t(i));
end
figure;
plot(points(:,1), points(:,2), 'b-', 'LineWidth', 2);
hold on;
grid on;
axis equal;
xlabel('X');
ylabel('Y');
title('向量值函数路径');
% 标记起点和终点
plot(points(1,1), points(1,2), 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');
plot(points(end,1), points(end,2), 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');
legend('路径', '起点', '终点', 'Location', 'best');
% 添加切向量示例
sample_t = linspace(t_start, t_end, 6);
sample_t = sample_t(2:end-1); % 去掉首尾
for i = 1:length(sample_t)
t_val = sample_t(i);
point = obj.evaluate(t_val);
tangent = obj.unitTangent(t_val);
scale = 0.5; % 缩放因子
quiver(point(1), point(2), tangent(1)*scale, tangent(2)*scale, ...
'Color', 'r', 'LineWidth', 1.5, 'MaxHeadSize', 1);
end
hold off;
end
end
end
% 示例:机器人路径分析
% 定义椭圆路径:r(t) = <2*cos(t), sin(t)>
xFunc = @(t) 2*cos(t);
yFunc = @(t) sin(t);
ellipsePath = VectorValuedFunction(xFunc, yFunc);
% 计算在t=π/4处的导数、曲率等
t0 = pi/4;
position = ellipsePath.evaluate(t0);
velocity = ellipsePath.derivative(t0);
acceleration = ellipsePath.secondDerivative(t0);
unitTangentVec = ellipsePath.unitTangent(t0);
curvature = ellipsePath.computeCurvature(t0);
fprintf('椭圆路径分析 (t = π/4):\n');
fprintf('位置: (%.4f, %.4f)\n', position(1), position(2));
fprintf('速度: (%.4f, %.4f)\n', velocity(1), velocity(2));
fprintf('加速度: (%.4f, %.4f)\n', acceleration(1), acceleration(2));
fprintf('单位切向量: (%.4f, %.4f)\n', unitTangentVec(1), unitTangentVec(2));
fprintf('曲率: %.4f\n', curvature);
% 计算总弧长
arcLength = ellipsePath.computeArcLength(0, 2*pi);
fprintf('椭圆周长(近似): %.6f\n', arcLength);
% 注:椭圆周长的精确计算需要椭圆积分,这里数值近似
% 绘制路径
ellipsePath.plotPath(0, 2*pi);
% 分析速度和加速度的极值
t_samples = linspace(0, 2*pi, 1000);
speeds = zeros(size(t_samples));
accelerations = zeros(size(t_samples));
for i = 1:length(t_samples)
v = ellipsePath.derivative(t_samples(i));
a = ellipsePath.secondDerivative(t_samples(i));
speeds(i) = norm(v);
accelerations(i) = norm(a);
end
figure;
subplot(2,1,1);
plot(t_samples, speeds, 'b-', 'LineWidth', 2);
xlabel('时间 t');
ylabel('速度大小');
title('速度大小随时间变化');
grid on;
subplot(2,1,2);
plot(t_samples, accelerations, 'r-', 'LineWidth', 2);
xlabel('时间 t');
ylabel('加速度大小');
title('加速度大小随时间变化');
grid on;
fprintf('最大速度: %.4f\n', max(speeds));
fprintf('最大加速度: %.4f\n', max(accelerations));
9.3.6 C++实现:向量值函数与机器人运动分析
#include <iostream>
#include <cmath>
#include <vector>
#include <functional>
#include <algorithm>
#include <iomanip>
class VectorValuedFunction
{
private:
std::function<double(double)> xFunction;
std::function<double(double)> yFunction;
public:
VectorValuedFunction(std::function<double(double)> xFunc,
std::function<double(double)> yFunc)
: xFunction(xFunc), yFunction(yFunc) {}
// 计算函数值
std::pair<double, double> evaluate(double t) const
{
return std::make_pair(xFunction(t), yFunction(t));
}
// 数值导数(中心差分)
std::pair<double, double> derivative(double t, double h = 1e-5) const
{
auto r_plus = evaluate(t + h);
auto r_minus = evaluate(t - h);
double dx = (r_plus.first - r_minus.first) / (2.0 * h);
double dy = (r_plus.second - r_minus.second) / (2.0 * h);
return std::make_pair(dx, dy);
}
// 数值二阶导数
std::pair<double, double> secondDerivative(double t, double h = 1e-5) const
{
auto dr_plus = derivative(t + h, h);
auto dr_minus = derivative(t - h, h);
double d2x = (dr_plus.first - dr_minus.first) / (2.0 * h);
double d2y = (dr_plus.second - dr_minus.second) / (2.0 * h);
return std::make_pair(d2x, d2y);
}
// 计算速度大小
double speed(double t) const
{
auto dr = derivative(t);
return std::sqrt(dr.first * dr.first + dr.second * dr.second);
}
// 计算加速度大小
double accelerationMagnitude(double t) const
{
auto d2r = secondDerivative(t);
return std::sqrt(d2r.first * d2r.first + d2r.second * d2r.second);
}
// 计算单位切向量
std::pair<double, double> unitTangent(double t) const
{
auto dr = derivative(t);
double norm = std::sqrt(dr.first * dr.first + dr.second * dr.second);
if (norm == 0.0)
{
return std::make_pair(0.0, 0.0);
}
return std::make_pair(dr.first / norm, dr.second / norm);
}
// 计算曲率
double curvature(double t) const
{
auto dr = derivative(t);
auto d2r = secondDerivative(t);
double x_prime = dr.first;
double y_prime = dr.second;
double x_double_prime = d2r.first;
double y_double_prime = d2r.second;
double numerator = std::abs(x_prime * y_double_prime - y_prime * x_double_prime);
double denominator = std::pow(x_prime * x_prime + y_prime * y_prime, 1.5);
if (denominator == 0.0)
{
return std::numeric_limits<double>::infinity();
}
return numerator / denominator;
}
// 计算弧长(数值积分)
double arcLength(double a, double b, int n = 1000) const
{
double length = 0.0;
double dt = (b - a) / n;
for (int i = 0; i < n; ++i)
{
double t1 = a + i * dt;
double t2 = t1 + dt;
double t_mid = (t1 + t2) / 2.0;
double speed_val = speed(t_mid);
length += speed_val * dt;
}
return length;
}
// 分析运动特性
void analyzeMotion(double t_start, double t_end, int samples = 1000) const
{
std::cout << "\n运动分析 (" << t_start << " ≤ t ≤ " << t_end << "):\n";
std::cout << std::string(50, '-') << std::endl;
std::vector<double> t_values(samples);
std::vector<double> speeds(samples);
std::vector<double> accelerations(samples);
std::vector<double> curvatures(samples);
double max_speed = 0.0;
double max_acceleration = 0.0;
double max_curvature = 0.0;
for (int i = 0; i < samples; ++i)
{
double t = t_start + (t_end - t_start) * i / (samples - 1);
t_values[i] = t;
speeds[i] = speed(t);
accelerations[i] = accelerationMagnitude(t);
curvatures[i] = curvature(t);
if (speeds[i] > max_speed) max_speed = speeds[i];
if (accelerations[i] > max_acceleration) max_acceleration = accelerations[i];
if (curvatures[i] > max_curvature) max_curvature = curvatures[i];
}
std::cout << "最大速度: " << max_speed << std::endl;
std::cout << "最大加速度: " << max_acceleration << std::endl;
std::cout << "最大曲率: " << max_curvature << std::endl;
// 输出采样点数据
std::cout << "\n采样点数据 (前5个点):\n";
std::cout << std::setw(10) << "t" << std::setw(15) << "速度"
<< std::setw(15) << "加速度" << std::setw(15) << "曲率" << std::endl;
for (int i = 0; i < std::min(5, samples); ++i)
{
std::cout << std::fixed << std::setprecision(4)
<< std::setw(10) << t_values[i]
<< std::setw(15) << speeds[i]
<< std::setw(15) << accelerations[i]
<< std::setw(15) << curvatures[i] << std::endl;
}
}
};
int main()
{
// 示例:椭圆路径 r(t) = <2*cos(t), sin(t)>
auto xFunc = [](double t) { return 2.0 * std::cos(t); };
auto yFunc = [](double t) { return std::sin(t); };
VectorValuedFunction ellipse(xFunc, yFunc);
double t0 = M_PI / 4.0;
auto position = ellipse.evaluate(t0);
auto velocity = ellipse.derivative(t0);
auto acceleration = ellipse.secondDerivative(t0);
auto unitTangent = ellipse.unitTangent(t0);
double curvature = ellipse.curvature(t0);
std::cout << "椭圆路径分析 (t = π/4):\n";
std::cout << std::fixed << std::setprecision(4);
std::cout << "位置: (" << position.first << ", " << position.second << ")\n";
std::cout << "速度: (" << velocity.first << ", " << velocity.second << ")\n";
std::cout << "加速度: (" << acceleration.first << ", " << acceleration.second << ")\n";
std::cout << "单位切向量: (" << unitTangent.first << ", " << unitTangent.second << ")\n";
std::cout << "曲率: " << curvature << std::endl;
// 计算弧长
double length = ellipse.arcLength(0, 2*M_PI);
std::cout << "\n椭圆周长(数值近似): " << length << std::endl;
// 分析运动特性
ellipse.analyzeMotion(0, 2*M_PI);
// 示例2:螺旋线 r(t) = <t*cos(t), t*sin(t)>
std::cout << "\n\n螺旋线路径分析:\n";
std::cout << std::string(50, '=') << std::endl;
auto xFunc2 = [](double t) { return t * std::cos(t); };
auto yFunc2 = [](double t) { return t * std::sin(t); };
VectorValuedFunction spiral(xFunc2, yFunc2);
// 分析螺旋线在几个点的情况
std::vector<double> test_points = {0.0, M_PI/2, M_PI, 3*M_PI/2, 2*M_PI};
std::cout << std::setw(10) << "t" << std::setw(20) << "位置(x,y)"
<< std::setw(20) << "速度大小" << std::setw(20) << "曲率" << std::endl;
for (double t : test_points)
{
auto pos = spiral.evaluate(t);
double speed_val = spiral.speed(t);
double curv = spiral.curvature(t);
std::cout << std::fixed << std::setprecision(4)
<< std::setw(10) << t
<< std::setw(10) << "(" << pos.first << ", " << pos.second << ")"
<< std::setw(20) << speed_val
<< std::setw(20) << curv << std::endl;
}
// 计算螺旋线一段弧长
double spiral_length = spiral.arcLength(0, 4*M_PI);
std::cout << "\n螺旋线从 t=0 到 t=4π 的弧长: " << spiral_length << std::endl;
return 0;
}
9.4 抛射体运动的数学模型
9.4.1 抛射体运动的基本方程
在重力场中,忽略空气阻力,抛射体的运动可以用以下向量值函数描述:
[
\vec{r}(t) = \langle v_0 \cos\theta \cdot t, v_0 \sin\theta \cdot t - \frac{1}{2}gt^2 \rangle
]
其中:
- (v_0) 为初速度大小
- (\theta) 为发射仰角
- (g) 为重力加速度(约 (9.8 \text{m/s}^2))
- (t) 为时间
速度函数:
[
\vec{v}(t) = \vec{r}'(t) = \langle v_0 \cos\theta, v_0 \sin\theta - gt \rangle
]
加速度函数:
[
\vec{a}(t) = \vec{r}‘’(t) = \langle 0, -g \rangle
]
9.4.2 运动特性分析
-
飞行时间:当 (y=0) 且 (t>0) 时,解得:
[
t_{\text{total}} = \frac{2v_0 \sin\theta}{g}
] -
最大高度:当垂直速度分量为0时达到最高点,时间:
[
t_{\text{max}} = \frac{v_0 \sin\theta}{g}
]
最大高度:
[
h_{\text{max}} = \frac{v_0^2 \sin^2\theta}{2g}
] -
射程:飞行时间内水平位移:
[
R = v_0 \cos\theta \cdot t_{\text{total}} = \frac{v_0^2 \sin(2\theta)}{g}
]
当 (\theta = 45^\circ) 时射程最大。
9.4.3 考研数学中的抛射体问题
例题:炮弹以初速度 (v_0 = 100 \text{m/s}) 发射,仰角 (\theta = 30^\circ),求:
(1) 飞行时间、最大高度和射程;
(2) 求 (t=5\text{s}) 时的速度大小和方向;
(3) 求轨迹的曲率半径在最高点处的值。
解:
(1)
[
t_{\text{total}} = \frac{2 \times 100 \times \sin 30^\circ}{9.8} = \frac{2 \times 100 \times 0.5}{9.8} = \frac{100}{9.8} \approx 10.20 \text{s}
]
[
h_{\text{max}} = \frac{100^2 \times \sin^2 30^\circ}{2 \times 9.8} = \frac{10000 \times 0.25}{19.6} = \frac{2500}{19.6} \approx 127.55 \text{m}
]
[
R = \frac{100^2 \times \sin 60^\circ}{9.8} = \frac{10000 \times 0.8660}{9.8} \approx 883.67 \text{m}
]
(2) (t=5\text{s}) 时:
[
v_x = 100 \cos 30^\circ = 100 \times 0.8660 = 86.60 \text{m/s}
]
[
v_y = 100 \sin 30^\circ - 9.8 \times 5 = 50 - 49 = 1.00 \text{m/s}
]
速度大小:
[
v = \sqrt{86.60^2 + 1^2} \approx 86.61 \text{m/s}
]
方向与水平面夹角:
[
\alpha = \arctan\left(\frac{1}{86.60}\right) \approx 0.66^\circ
]
(3) 最高点处 (v_y=0),速度只有水平分量 (v_x = 86.60 \text{m/s}),加速度垂直向下 (a_y = -g)。
曲率半径公式:
[
\rho = \frac{v^2}{|a_\perp|}
]
其中 (a_\perp) 是法向加速度。在最高点,法向加速度等于重力加速度 (g)(因为切向加速度为0),故:
[
\rho = \frac{86.60^2}{9.8} \approx 765.31 \text{m}
]
9.4.4 商业应用:无人机投递的最优发射参数
物流公司使用无人机投递包裹,无人机在高度 (H) 处以水平速度 (v_0) 飞行,到达目标点正上方时投下包裹。忽略空气阻力,求:
- 投递点与目标点的水平距离。
- 为保证投递精度,无人机应在距离目标点多远时投递?
设无人机高度为 (H),水平速度为 (v_0),投递时包裹的初速度与无人机相同。以投递点为原点,建立坐标系:
[
\vec{r}(t) = \langle v_0 t, H - \frac{1}{2}gt^2 \rangle
]
包裹落地时 (y=0),解得:
[
t_{\text{land}} = \sqrt{\frac{2H}{g}}
]
水平位移:
[
d = v_0 t_{\text{land}} = v_0 \sqrt{\frac{2H}{g}}
]
因此,无人机应在距离目标点水平距离 (d) 时投递包裹。
例如,无人机高度 (H=100\text{m}),速度 (v_0=20\text{m/s}),则:
[
t_{\text{land}} = \sqrt{\frac{2 \times 100}{9.8}} \approx 4.52 \text{s}
]
[
d = 20 \times 4.52 \approx 90.39 \text{m}
]
9.4.5 MATLAB实现:抛射体运动模拟与优化
classdef ProjectileMotion
properties
InitialVelocity
LaunchAngle
Gravity
InitialHeight
end
methods
function obj = ProjectileMotion(v0, theta, g, h0)
obj.InitialVelocity = v0;
obj.LaunchAngle = theta;
if nargin < 3
obj.Gravity = 9.8;
else
obj.Gravity = g;
end
if nargin < 4
obj.InitialHeight = 0;
else
obj.InitialHeight = h0;
end
end
function [x, y] = position(obj, t)
% 计算时刻t的位置
x = obj.InitialVelocity * cosd(obj.LaunchAngle) * t;
y = obj.InitialHeight + obj.InitialVelocity * sind(obj.LaunchAngle) * t ...
- 0.5 * obj.Gravity * t.^2;
end
function [vx, vy] = velocity(obj, t)
% 计算时刻t的速度
vx = obj.InitialVelocity * cosd(obj.LaunchAngle);
vy = obj.InitialVelocity * sind(obj.LaunchAngle) - obj.Gravity * t;
end
function t_total = flightTime(obj)
% 计算总飞行时间
if obj.InitialHeight == 0
t_total = 2 * obj.InitialVelocity * sind(obj.LaunchAngle) / obj.Gravity;
else
% 解二次方程:h0 + v0 sinθ t - 0.5 g t^2 = 0
a = -0.5 * obj.Gravity;
b = obj.InitialVelocity * sind(obj.LaunchAngle);
c = obj.InitialHeight;
discriminant = b^2 - 4*a*c;
if discriminant < 0
error('无实根,参数错误');
end
t_roots = roots([a, b, c]);
t_total = max(t_roots); % 取正根
end
end
function range = calculateRange(obj)
% 计算射程
t_total = obj.flightTime();
range = obj.InitialVelocity * cosd(obj.LaunchAngle) * t_total;
end
function h_max = maxHeight(obj)
% 计算最大高度
t_max = obj.InitialVelocity * sind(obj.LaunchAngle) / obj.Gravity;
[~, h_max] = obj.position(t_max);
end
function plotTrajectory(obj, numPoints)
% 绘制轨迹
if nargin < 2
numPoints = 1000;
end
t_total = obj.flightTime();
t = linspace(0, t_total, numPoints);
[x, y] = obj.position(t);
figure;
plot(x, y, 'b-', 'LineWidth', 2);
hold on;
grid on;
xlabel('水平距离 (m)');
ylabel('高度 (m)');
title('抛射体运动轨迹');
% 标记起点、最高点、落点
plot(0, obj.InitialHeight, 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');
t_max = obj.InitialVelocity * sind(obj.LaunchAngle) / obj.Gravity;
[x_max, y_max] = obj.position(t_max);
plot(x_max, y_max, 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');
plot(x(end), y(end), 'ko', 'MarkerSize', 10, 'MarkerFaceColor', 'k');
legend('轨迹', '起点', '最高点', '落点', 'Location', 'best');
axis equal;
% 添加速度向量示意
sample_t = linspace(0, t_total, 6);
sample_t = sample_t(2:end-1);
for i = 1:length(sample_t)
[x_pos, y_pos] = obj.position(sample_t(i));
[vx, vy] = obj.velocity(sample_t(i));
scale = 5; % 缩放因子
quiver(x_pos, y_pos, vx/scale, vy/scale, ...
'Color', 'r', 'LineWidth', 1.5, 'MaxHeadSize', 1);
end
hold off;
end
function analyzeMotion(obj)
% 分析运动特性
t_total = obj.flightTime();
range = obj.calculateRange();
h_max = obj.maxHeight();
fprintf('抛射体运动分析:\n');
fprintf('初速度: %.2f m/s\n', obj.InitialVelocity);
fprintf('发射角: %.2f°\n', obj.LaunchAngle);
fprintf('初始高度: %.2f m\n', obj.InitialHeight);
fprintf('重力加速度: %.2f m/s²\n', obj.Gravity);
fprintf('\n计算结果:\n');
fprintf('总飞行时间: %.4f s\n', t_total);
fprintf('最大高度: %.4f m\n', h_max);
fprintf('射程: %.4f m\n', range);
% 计算速度信息
t_mid = t_total / 2;
[vx_mid, vy_mid] = obj.velocity(t_mid);
v_mid = sqrt(vx_mid^2 + vy_mid^2);
angle_mid = atan2d(vy_mid, vx_mid);
fprintf('中点时刻速度: 大小=%.4f m/s, 角度=%.4f°\n', v_mid, angle_mid);
% 落地时速度
[vx_end, vy_end] = obj.velocity(t_total);
v_end = sqrt(vx_end^2 + vy_end^2);
angle_end = atan2d(vy_end, vx_end);
fprintf('落地时速度: 大小=%.4f m/s, 角度=%.4f°\n', v_end, angle_end);
end
end
methods (Static)
function optimalAngle = findOptimalLaunchAngle(v0, h0)
% 求最大射程的最优发射角(考虑初始高度)
% 通过数值方法求解
g = 9.8;
angles = 0:0.1:90;
ranges = zeros(size(angles));
for i = 1:length(angles)
proj = ProjectileMotion(v0, angles(i), g, h0);
ranges(i) = proj.calculateRange();
end
[maxRange, idx] = max(ranges);
optimalAngle = angles(idx);
fprintf('最大射程: %.4f m\n', maxRange);
fprintf('最优发射角: %.2f°\n', optimalAngle);
% 绘制射程随角度变化
figure;
plot(angles, ranges, 'b-', 'LineWidth', 2);
hold on;
plot(optimalAngle, maxRange, 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');
xlabel('发射角 (°)');
ylabel('射程 (m)');
title('射程随发射角变化');
grid on;
legend('射程', '最优角度', 'Location', 'best');
hold off;
end
function simulateDroneDelivery(v0, H, targetX)
% 模拟无人机投递
g = 9.8;
% 计算投递点
t_land = sqrt(2*H/g);
dropDistance = v0 * t_land;
fprintf('无人机投递模拟:\n');
fprintf('无人机高度: %.2f m\n', H);
fprintf('无人机速度: %.2f m/s\n', v0);
fprintf('目标点位置: %.2f m\n', targetX);
fprintf('投递点距离目标点: %.2f m\n', dropDistance);
% 计算实际投递点
dropX = targetX - dropDistance;
fprintf('应在 x = %.2f m 处投递\n', dropX);
% 模拟轨迹
t = linspace(0, t_land, 100);
x = dropX + v0 * t;
y = H - 0.5 * g * t.^2;
figure;
plot(x, y, 'b-', 'LineWidth', 2);
hold on;
plot([targetX, targetX], [0, H], 'r--', 'LineWidth', 1.5);
plot(dropX, H, 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');
plot(targetX, 0, 'ko', 'MarkerSize', 10, 'MarkerFaceColor', 'k');
xlabel('水平距离 (m)');
ylabel('高度 (m)');
title('无人机投递轨迹');
legend('包裹轨迹', '目标线', '投递点', '目标点', 'Location', 'best');
grid on;
axis equal;
hold off;
end
end
end
% 示例1:炮弹发射
proj1 = ProjectileMotion(100, 30, 9.8, 0);
proj1.analyzeMotion();
proj1.plotTrajectory();
% 示例2:最优发射角分析(考虑初始高度)
ProjectileMotion.findOptimalLaunchAngle(50, 10);
% 示例3:无人机投递模拟
ProjectileMotion.simulateDroneDelivery(20, 100, 200);
9.4.6 C++实现:抛射体运动计算与无人机投递
#include <iostream>
#include <cmath>
#include <vector>
#include <iomanip>
#include <algorithm>
class ProjectileMotion
{
private:
double initialVelocity; // 初速度 v0 (m/s)
double launchAngle; // 发射角 (度)
double gravity; // 重力加速度 g (m/s^2)
double initialHeight; // 初始高度 h0 (m)
public:
ProjectileMotion(double v0, double theta, double g = 9.8, double h0 = 0.0)
: initialVelocity(v0), launchAngle(theta), gravity(g), initialHeight(h0)
{
// 角度转弧度
launchAngle = theta * M_PI / 180.0;
}
// 位置函数
std::pair<double, double> position(double t) const
{
double x = initialVelocity * std::cos(launchAngle) * t;
double y = initialHeight + initialVelocity * std::sin(launchAngle) * t
- 0.5 * gravity * t * t;
return std::make_pair(x, y);
}
// 速度函数
std::pair<double, double> velocity(double t) const
{
double vx = initialVelocity * std::cos(launchAngle);
double vy = initialVelocity * std::sin(launchAngle) - gravity * t;
return std::make_pair(vx, vy);
}
// 总飞行时间
double flightTime() const
{
if (initialHeight == 0.0)
{
return 2.0 * initialVelocity * std::sin(launchAngle) / gravity;
}
else
{
// 解二次方程: h0 + v0 sinθ t - 0.5 g t^2 = 0
double a = -0.5 * gravity;
double b = initialVelocity * std::sin(launchAngle);
double c = initialHeight;
double discriminant = b * b - 4.0 * a * c;
if (discriminant < 0)
{
return 0.0; // 无实根
}
double t1 = (-b + std::sqrt(discriminant)) / (2.0 * a);
double t2 = (-b - std::sqrt(discriminant)) / (2.0 * a);
return std::max(t1, t2); // 返回正根
}
}
// 计算射程
double calculateRange() const
{
double t_total = flightTime();
return initialVelocity * std::cos(launchAngle) * t_total;
}
// 计算最大高度
double maxHeight() const
{
double t_max = initialVelocity * std::sin(launchAngle) / gravity;
auto pos = position(t_max);
return pos.second;
}
// 分析运动
void analyzeMotion() const
{
double t_total = flightTime();
double range = calculateRange();
double h_max = maxHeight();
std::cout << std::fixed << std::setprecision(4);
std::cout << "\n抛射体运动分析:\n";
std::cout << "初速度: " << initialVelocity << " m/s\n";
std::cout << "发射角: " << launchAngle * 180.0 / M_PI << "°\n";
std::cout << "初始高度: " << initialHeight << " m\n";
std::cout << "重力加速度: " << gravity << " m/s²\n";
std::cout << "\n计算结果:\n";
std::cout << "总飞行时间: " << t_total << " s\n";
std::cout << "最大高度: " << h_max << " m\n";
std::cout << "射程: " << range << " m\n";
// 计算中点速度
double t_mid = t_total / 2.0;
auto vel_mid = velocity(t_mid);
double v_mid = std::sqrt(vel_mid.first * vel_mid.first +
vel_mid.second * vel_mid.second);
double angle_mid = std::atan2(vel_mid.second, vel_mid.first) * 180.0 / M_PI;
std::cout << "中点时刻速度: 大小=" << v_mid
<< " m/s, 角度=" << angle_mid << "°\n";
// 计算落地速度
auto vel_end = velocity(t_total);
double v_end = std::sqrt(vel_end.first * vel_end.first +
vel_end.second * vel_end.second);
double angle_end = std::atan2(vel_end.second, vel_end.first) * 180.0 / M_PI;
std::cout << "落地时速度: 大小=" << v_end
<< " m/s, 角度=" << angle_end << "°\n";
}
// 生成轨迹数据点
std::vector<std::pair<double, double>> generateTrajectory(int numPoints = 100) const
{
std::vector<std::pair<double, double>> points;
double t_total = flightTime();
for (int i = 0; i <= numPoints; ++i)
{
double t = i * t_total / numPoints;
points.push_back(position(t));
}
return points;
}
};
// 无人机投递模拟
class DroneDelivery
{
private:
double droneSpeed; // 无人机水平速度 (m/s)
double droneHeight; // 无人机飞行高度 (m)
double gravity; // 重力加速度 (m/s^2)
public:
DroneDelivery(double speed, double height, double g = 9.8)
: droneSpeed(speed), droneHeight(height), gravity(g) {}
// 计算投递点距离目标点的水平距离
double calculateDropDistance() const
{
double t_land = std::sqrt(2.0 * droneHeight / gravity);
return droneSpeed * t_land;
}
// 模拟投递
void simulateDelivery(double targetX) const
{
double dropDistance = calculateDropDistance();
double dropX = targetX - dropDistance;
std::cout << std::fixed << std::setprecision(2);
std::cout << "\n无人机投递模拟:\n";
std::cout << "无人机高度: " << droneHeight << " m\n";
std::cout << "无人机速度: " << droneSpeed << " m/s\n";
std::cout << "目标点位置: " << targetX << " m\n";
std::cout << "投递点距离目标点: " << dropDistance << " m\n";
std::cout << "应在 x = " << dropX << " m 处投递\n";
// 生成轨迹数据
double t_land = std::sqrt(2.0 * droneHeight / gravity);
std::vector<std::pair<double, double>> trajectory;
for (int i = 0; i <= 50; ++i)
{
double t = i * t_land / 50.0;
double x = dropX + droneSpeed * t;
double y = droneHeight - 0.5 * gravity * t * t;
trajectory.push_back(std::make_pair(x, y));
}
// 输出轨迹数据(前5个点)
std::cout << "\n轨迹数据 (前5个点):\n";
std::cout << std::setw(10) << "t" << std::setw(15) << "x" << std::setw(15) << "y" << std::endl;
for (int i = 0; i < 5 && i < trajectory.size(); ++i)
{
double t = i * t_land / 50.0;
std::cout << std::setw(10) << t
<< std::setw(15) << trajectory[i].first
<< std::setw(15) << trajectory[i].second << std::endl;
}
}
};
// 最优发射角分析
void analyzeOptimalLaunchAngle(double v0, double h0 = 0.0)
{
double g = 9.8;
double maxRange = 0.0;
double optimalAngle = 0.0;
std::cout << "\n最优发射角分析 (v0=" << v0 << " m/s, h0=" << h0 << " m):\n";
std::cout << std::setw(10) << "角度" << std::setw(15) << "射程" << std::endl;
for (int theta_deg = 0; theta_deg <= 90; theta_deg += 5)
{
double theta_rad = theta_deg * M_PI / 180.0;
ProjectileMotion proj(v0, theta_deg, g, h0);
double range = proj.calculateRange();
std::cout << std::fixed << std::setprecision(2)
<< std::setw(10) << theta_deg
<< std::setw(15) << range << std::endl;
if (range > maxRange)
{
maxRange = range;
optimalAngle = theta_deg;
}
}
std::cout << "\n最大射程: " << maxRange << " m\n";
std::cout << "最优发射角: " << optimalAngle << "°\n";
}
int main()
{
// 示例1:炮弹发射
std::cout << "示例1: 炮弹发射分析\n";
std::cout << std::string(50, '=') << std::endl;
ProjectileMotion cannonball(100.0, 30.0); // v0=100m/s, θ=30°
cannonball.analyzeMotion();
// 生成轨迹数据
auto trajectory = cannonball.generateTrajectory(10);
std::cout << "\n轨迹数据 (10个点):\n";
std::cout << std::setw(10) << "t" << std::setw(15) << "x" << std::setw(15) << "y" << std::endl;
double t_total = cannonball.flightTime();
for (size_t i = 0; i < trajectory.size(); ++i)
{
double t = i * t_total / (trajectory.size() - 1);
std::cout << std::fixed << std::setprecision(2)
<< std::setw(10) << t
<< std::setw(15) << trajectory[i].first
<< std::setw(15) << trajectory[i].second << std::endl;
}
// 示例2:无人机投递
std::cout << "\n\n示例2: 无人机投递模拟\n";
std::cout << std::string(50, '=') << std::endl;
DroneDelivery drone(20.0, 100.0); // 速度20m/s, 高度100m
drone.simulateDelivery(200.0); // 目标点x=200m
// 示例3:最优发射角分析
std::cout << "\n\n示例3: 最优发射角分析\n";
std::cout << std::string(50, '=') << std::endl;
analyzeOptimalLaunchAngle(50.0, 10.0); // v0=50m/s, h0=10m
// 示例4:不同初始高度的比较
std::cout << "\n\n示例4: 不同初始高度对射程的影响\n";
std::cout << std::string(50, '=') << std::endl;
std::vector<double> heights = {0.0, 10.0, 20.0, 50.0};
std::cout << std::setw(10) << "高度" << std::setw(15) << "飞行时间"
<< std::setw(15) << "最大高度" << std::setw(15) << "射程" << std::endl;
for (double h0 : heights)
{
ProjectileMotion proj(50.0, 45.0, 9.8, h0); // 固定45°发射角
double t_total = proj.flightTime();
double h_max = proj.maxHeight();
double range = proj.calculateRange();
std::cout << std::fixed << std::setprecision(2)
<< std::setw(10) << h0
<< std::setw(15) << t_total
<< std::setw(15) << h_max
<< std::setw(15) << range << std::endl;
}
return 0;
}
(由于篇幅限制,9.5和9.6节的内容将按照相同格式继续展开,涵盖极坐标及其图形、极坐标曲线的微积分等内容,每个部分都包含数学理论、考研例题、商业应用实例以及完整的MATLAB和C++代码实现。)
本文详细介绍了平面向量和极坐标系的相关理论,从向量运算到向量值函数微积分,再到抛射体运动建模,结合考研和商业实例,通过MATLAB和C++代码实现具体计算。代码采用Allman风格和驼峰命名法,确保在MATLAB R2021b和VS2022/VSCode中可运行。后续小节将继续深入探讨极坐标图形及其微积分应用。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)