Basic Control Containment基本的控制容器[1]

本文详细解析了CWindow中的窗口过程调用机制,包括如何通过StartWindowProc处理消息,以及thunk机制的应用。同时介绍了CAxHostWindow对象的创建流程,涉及窗口类注册、控制项创建及接口调用等关键步骤。

首先回顾一下CWindow中的窗口过程:

 

#define DECLARE_WND_CLASS(WndClassName) /
static ATL::CWndClassInfo& GetWndClassInfo() /
{ /
static ATL::CWndClassInfo wc = /
{ /
{ sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, /
0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, /
NULL, NULL, IDC_ARROW, TRUE, 0, _T("") /
}; /
return wc; /
}

指定了窗口过程StartWindowProc.

 

然后通过pThis->m_thunk.Init(WindowProc, pThis); thunk机制调换了

static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)中

的HWND为CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)hWnd;

接下来就利用多态调用

BOOL bRet = pThis->m_pObject->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, pThis->m_dwMsgMapID);

 

该函数是通过宏定义

 

#define BEGIN_MSG_MAP(theClass) /
public: /
BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) /
{ /
BOOL bHandled = TRUE; /
(hWnd); /
(uMsg); /
(wParam); /
(lParam); /
(lResult); /
(bHandled); /
switch(dwMsgMapID) /
{ /
case 0:

 

若这个函数返回FALSE,则跳转到DefWindowProc

if(uMsg != WM_NCDESTROY)
lRes = pThis->DefWindowProc(uMsg, wParam, lParam);

 

以上就是关于CWindow中的窗口过程调用。

接下来看一下CAxHostWindow对象是如何被创建的。在CMainWindow中:

CAxWindow m_bullseyeWin;

m_bullseyeWin.Create( m_hWnd, rect, controlName, WS_CHILD | WS_VISIBLE, 0, ID_BULLSEYE );

其中就指定了CLASSNAME     GetWndClassName() = ATLAXWIN_CLASS,该宏正是"AtlAxWin80"

 

该窗口类在AtlAxWinInit()注册的时候,使用的是wc.lpfnWndProc = AtlAxWindowProc;

来看一下window procedure AtlAxWindowProc:

在其中调用了HRESULT hRet = AtlAxCreateControlLic(T2COLE_EX_DEF(spName), hWnd, spStream, &spUnk, NULL);

将spName传递进去,并最终调用了AtlAcCreateControlLicEx(atlHost.h LN1980)

 

hr = CAxHostWindow::_CreatorClass::CreateInstance(NULL, __uuidof(IUnknown), (void**)&spUnkContainer);
if (SUCCEEDED(hr))
{
CComPtr pAxWindow;
spUnkContainer->QueryInterface(__uuidof(IAxWinHostWindow), (void**)&pAxWindow);
CComBSTR bstrName(lpszName);
hr = pAxWindow->CreateControlLicEx(bstrName, hWnd, pStream, &spUnkControl, iidSink, punkSink, bstrLic);
}

 

interface IAxWinHostWindow : IUnknown {

HRESULT CreateControl([in] LPCOLESTR lpTricsData, [in] HWND hWnd, [in] IStream* pStream);

 HRESULT CreateControlEx([in] LPCOLESTR lpTricsData, [in] HWND hWnd, [in] IStream* pStream, [out] IUnknown** ppUnk, [in] REFIID riidAdvise, [in] IUnknown* punkAdvise);

 HRESULT AttachControl([in] IUnknown* pUnkControl, [in] HWND hWnd);

HRESULT QueryControl([in] REFIID riid, [out, iid_is(riid)] void **ppvObject);

HRESULT SetExternalDispatch([in] IDispatch* pDisp); HRESULT SetExternalUIHandler( [in] IDocHostUIHandlerDispatch* pDisp); };

 

// TODO  复习SubclassWindow,即子类化

http://www.vckbase.com/document/viewdoc/?id=1119

在MATLAB中实现包含控制containment control)通常涉及多智能体系统(multi-agent systems),其中多个跟随者(followers)被引导进入由一个或多个领导者(leaders)定义的凸包区域。这种控制策略广泛应用于无人机编队、机器人协同任务等领域。 ### MATLAB中实现Containment Control基本方法 #### 1. **数学建模** - 在多智能体系统中,每个智能体的动力学可以表示为一阶或二阶积分器模型。 - 假设系统中有 $ N $ 个跟随者和 $ M $ 个领导者,目标是设计控制器使得所有跟随者的状态收敛到由领导者定义的凸包内。 - 系统动力学可表示为: $$ \dot{x}_i = v_i, \quad \dot{v}_i = u_i $$ 其中 $ x_i $ 和 $ v_i $ 分别表示第 $ i $ 个智能体的位置和速度,$ u_i $ 是控制输入 [^2]。 #### 2. **图论与通信拓扑** - 使用图论描述智能体之间的通信关系,通常采用邻接矩阵 $ A $ 或拉普拉斯矩阵 $ L $ 表示网络拓扑结构。 - 领导者-跟随者系统的通信图应满足一定的连通性条件,以确保信息能够从领导者传播到所有跟随者 [^2]。 #### 3. **控制器设计** - 对于二阶积分器系统,常用的控制协议形式如下: $$ u_i = -k_1 \sum_{j \in N_i} a_{ij}(x_i - x_j) - k_2 \sum_{j \in N_i} a_{ij}(v_i - v_j) $$ 其中 $ k_1 $ 和 $ k_2 $ 是控制增益,$ N_i $ 表示与智能体 $ i $ 相邻的邻居集合,$ a_{ij} $ 是邻接矩阵元素 [^2]。 #### 4. **MATLAB仿真实现** - 使用 `ode45` 求解微分方程组。 - 构建通信拓扑图,使用 `graph` 或 `digraph` 函数生成邻接矩阵。 - 编写控制律函数并进行仿真。 以下是一个简单的MATLAB代码示例,展示如何实现一阶系统的Containment Control: ```matlab % 参数设置 N = 5; % 跟随者数量 M = 2; % 领导者数量 k = 1; % 控制增益 % 初始化位置和速度 x = rand(N + M, 2); % 初始位置 (x, y) v = zeros(N + M, 2); % 初始速度 % 定义通信拓扑(邻接矩阵) A = zeros(N + M); % 假设领导者之间不通信,只与部分跟随者通信 for i = 1:N for j = N+1:N+M A(i, j) = 1; % 跟随者与领导者之间的连接 end end % 拉普拉斯矩阵 L = diag(sum(A)) - A; % 控制律函数 function dxdt = containment_control(t, X, L, N, M, k) x = X(1:end/2); v = X(end/2+1:end); dxdt = zeros(size(X)); for i = 1:N sum_term = 0; for j = 1:N+M if L(i, j) ~= 0 sum_term = sum_term + L(i, j) * (x(i) - x(j)); end end dxdt(i) = v(i); dxdt(i + N) = -k * sum_term; end end % 初始状态向量 X0 = [x(:); v(:)]; % 时间范围 tspan = [0 10]; % 求解ODE [t, X] = ode45(@(t, X) containment_control(t, X, L, N, M, k), tspan, X0); % 绘制轨迹 figure; for i = 1:N plot(X(:, i), X(:, i + N)); hold on; end legend('Follower 1', 'Follower 2', 'Follower 3', 'Follower 4', 'Follower 5'); title('Containment Control Simulation in MATLAB'); xlabel('Position x'); ylabel('Position y'); grid on; ``` ### 关键点总结 - **通信拓扑**:合理的通信结构是实现Containment Control的基础。 - **控制器设计**:需要根据系统动力学选择合适的控制律。 - **稳定性分析**:通常使用Lyapunov理论或LaSalle不变原理证明闭环系统的稳定性 [^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值