日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

VINS-Mono 代码解析六、边缘化(3)

發布時間:2023/12/20 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 VINS-Mono 代码解析六、边缘化(3) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

“ 在優化完成后,滑動窗口前,必須進行邊緣化項的操作”

一、理論部分

VINS 細節系列 - 窗口優化_努力努力努力-CSDN博客

?一個邊緣化的例子

下面我們用一個具體例子來形象說明邊緣化過程及其導致的矩陣稠密現象(fill-in)。設有 四個相機位姿 xpi ,

以及? 6 個路標點xmk (路標點用 xyz 的參數化), 相機與路標點的邊表示一次觀測, 相鄰相機之間的邊表示 IMU 約束,

相互關系如下:

下面試圖將 xp1? 給 marg 掉,然后再將 xm1 給 marg 掉, 看看 H 矩陣會如何變化

圖(12-a) 表示原始的 H 矩陣,注意這里的 左上角為路標點相關部分, 而右下角是 pose 相關部分

圖(12-b)是把 H 矩陣中跟x p1 相關的部分移動到 H 矩陣左上角

其中各矩陣的維度已在上式標明,也就是說圖(12-c)的矩陣大小為 32×32。我們可以看到,圖(c)相對于圖(b)變得更稠密了,

即 marg 掉一個 pose,會使得剩余的 H 矩陣有 3 個地方被 fill-in,如圖(c)中顏色加重區域。

這時圖關系則變為:

注意,觀察圖 16 可發現這時的 xm1 、xm2 和 xm3 彼此之間已經產生了新的約束關系,且xp2 也與xm1 產生了新的約束關系。

圖(12-d)是 marg 掉xm1 后的 H 矩陣,詳細如下所示:

對應的圖關系如下:

我們發現, marg 掉xm1 后,并沒有是 H 矩陣更稠密,這是因為xm1 之前并未與其他pose 有約束關系,即并未被觀察到,

因此如果 marg 掉那些不被其他幀觀測到的路標點,不會顯著地使 H 矩陣變得稠密。而要 marg 掉的路標點中,對于那

些被其他幀觀測到路標點,要么就別設置為 marg, 要么就寧愿丟棄,這就是 OKVIS 中用到的策略

簡單介紹

?1、優化變量:

序號?????? ? ? ? 變量??????????? ? ?? ???? ? ? ? ?? ?? 維度

?? 0????????? para_Pose???????????????? (6維,相機位姿)
?? 1????????? para_SpeedBias??? (9維,相機速度、加速度偏置、角速度偏置)、
?? 2?????? ?? para_Ex_Pose???????? (6維、相機IMU外參)、
?? 3 ? ? ? ?? para_Feature?????????? (1維,特征點深度)、
?? 4????????? para_Td????????????????????? (1維,標定同步時間)
五部分組成,在后面進行邊緣化操作時這些優化變量都是當做整體看待

last_marginalization_parameter_blocks Xb變量,也是我們要優化的變量;
last_marginalization_info??????????? ? ? ? ? ? ? ? ? ? ? Xm與Xb對應的測量Zb,也是先驗殘差(細品一下)

2、思路:
?

邊緣化策略

邊緣化分兩種情況,每種情況有各自的流程

a. 如果次新幀是關鍵幀,則將邊緣化最老幀,及其看到的路標點和IMU數據,轉化為先驗。具體流程為:

1)將上一次先驗殘差項傳遞給marginalization_info

2)將第0幀和第1幀間的IMU因子IMUFactor(pre_integrations[1]),添加到marginalization_info中

3)將第一次觀測為第0幀的所有路標點對應的視覺觀測,添加到marginalization_info中

4)計算每個殘差,對應的Jacobian,并將各參數塊拷貝到統一的內存(parameter_block_data)中

5)多線程構造先驗項舒爾補AX=b的結構,在X0處線性化計算Jacobian和殘差

6)調整參數塊在下一次窗口中對應的位置(往前移一格),注意這里是指針,后面slideWindow中會賦新值,這里只是提前占座

b. 如果次新幀不是關鍵幀,此時具體流程為:

1)保留次新幀的IMU測量,丟棄該幀的視覺測量,將上一次先驗殘差項傳遞給marginalization_info

2)premargin:計算每個殘差,對應的Jacobian,并更新parameter_block_data

3)marginalize:構造先驗項舒爾補AX=b的結構,計算Jacobian和殘差

4)調整參數塊在下一次窗口中對應的位置(去掉次新幀)

3、marginalization_factor.cpp 代碼中有幾個變量需要提前說明:

舉例說明,當第一次 marg 掉最老幀時,parameter_block_size 為所有變量及其對應的
localSize,? parameter_block_data 為對應的數據(double*類型)

?

二、程序部分

2.1? 把下面這個圖搞明白!

?

2.2 看 ?"marginalization_factor.h"? 中類和結構體的定義

?1、class ResidualBlockInfo

類描述:這個類保存了待marg變量(xm)與相關聯變量(xb)之間的一個約束因子關系? -? Zm

struct ResidualBlockInfo {ResidualBlockInfo(ceres::CostFunction *_cost_function, ceres::LossFunction *_loss_function, std::vector<double *> _parameter_blocks, std::vector<int> _drop_set): cost_function(_cost_function), loss_function(_loss_function), parameter_blocks(_parameter_blocks), drop_set(_drop_set) {}void Evaluate();//調用cost_function的evaluate函數計算殘差 和 雅克比矩陣ceres::CostFunction *cost_function;ceres::LossFunction *loss_function;std::vector<double *> parameter_blocks;std::vector<int> drop_set;double **raw_jacobians;std::vector<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> jacobians;Eigen::VectorXd residuals;int localSize(int size){return size == 7 ? 6 : size;} }; 成員變量描述
cost_function對應ceres中表示約束因子的類
parameter_blocks該約束因子相關聯的參數塊變量
drop_setparameter_blocks中待marg變量的索引

2、class MarginalizationInfo

類描述:這個類保存了優化時上一步邊緣化后保留下來的先驗信息

class MarginalizationInfo {public:~MarginalizationInfo();int localSize(int size) const;int globalSize(int size) const;void addResidualBlockInfo(ResidualBlockInfo *residual_block_info);void preMarginalize();void marginalize();std::vector<double *> getParameterBlocks(std::unordered_map<long, double *> &addr_shift);std::vector<ResidualBlockInfo *> factors;//這里將參數塊分為Xm,Xb,Xr,Xm表示被marg掉的參數塊,Xb表示與Xm相連接的參數塊,Xr表示剩余的參數塊//那么m=Xm的localsize之和,n為Xb的localsize之和,pos為(Xm+Xb)localsize之和int m, n; std::unordered_map<long, int> parameter_block_size; //global size 將被marg掉的約束邊相關聯的參數塊,即將被marg掉的參數塊以及與它們直接相連的參數快int sum_block_size;std::unordered_map<long, int> parameter_block_idx; //local size std::unordered_map<long, double *> parameter_block_data;std::vector<int> keep_block_size; //global sizestd::vector<int> keep_block_idx; //local sizestd::vector<double *> keep_block_data;Eigen::MatrixXd linearized_jacobians;Eigen::VectorXd linearized_residuals;const double eps = 1e-8;}; 成員變量描述
factorsxm與xb之間的約束因子,Zb
m所有將被marg掉變量的localsize之和,如上圖中xm的localsize
n所有與將被marg掉變量有約束關系的變量的localsize之和,如上圖中xb的localsize
parameter_block_size<參數塊地址,參數塊的global size>,參數塊包括xm和xb
parameter_block_idx<參數塊地址,參數塊排序好后的索引>,對參數塊進行排序,xm排在前面,xb排成后面,使用localsize
parameter_block_data<參數塊地址,參數塊數據>,需要注意的是這里保存的參數塊數據是原始參數塊數據的一個拷貝,不再變化,用于記錄這些參數塊變量在marg時的狀態
keep_block_size<保留下來的參數塊地址,參數塊的globalsize>
keep_block_idx<保留下來的參數塊地址,參數塊的索引>,保留下來的參數塊是xb

成員函數信息:

成員函數描述
preMarginalize得到每次IMU和視覺觀測對應的參數塊,雅克比矩陣,殘差值
marginalize開啟多線程構建信息矩陣H和b ,同時從H,b中恢復出線性化雅克比和殘差

3、class MarginalizationFactor

類描述:該類是優化時表示上一步邊緣化后保留下來的先驗信息代價因子,變量marginalization_info保存了類似約束測量信息

class MarginalizationFactor : public ceres::CostFunction {public:MarginalizationFactor(MarginalizationInfo* _marginalization_info);virtual bool Evaluate(double const *const *parameters, double *residuals, double **jacobians) const;MarginalizationInfo* marginalization_info; };

2.3 程序講解

邊緣化部分在? optimization 函數里面,當執行完后端優化后,緊接著就會執行邊緣化,兩個過程都需要添加優化變量和殘差,

但區別是邊緣化的變量少一點!主要是構建模塊的過程!

?

一、如果邊緣化 “老幀”

【1】首先 把上一次先驗項中的殘差項(尺寸為 n)傳遞給當前先驗項,并從中去除需要丟棄 的狀態量;

即從舊的先驗殘差項 last_marginalization_info 新建一個新的 marginalization_factor,參與這個殘差項的優化變量是:last_marginalization_parameter_blocks 里面的內容:para_Pose、para_SpeedBias、para_Ex_Pose、para_Feature、para_Td 都是按順序排好的,所以要把 要丟棄 的狀態量? para_Pose[0]、para_SpeedBias[0] 對應的序號用 drop_set 記錄下來

// --------------------------------------marginalization-----------------------------------------//添加殘差以及優化變量的方式和后端線性優化中添加的方式相似,因為邊緣化類應該就是仿照ceres寫的TicToc t_whole_marginalization;//一、邊緣化老幀,那就要考慮老幀的情況! //要邊緣化的參數塊是 para_Pose[0] para_SpeedBias[0] 以及 para_Feature[feature_index](滑窗內的第feature_index個點的逆深度)if (marginalization_flag == MARGIN_OLD){MarginalizationInfo *marginalization_info = new MarginalizationInfo();//先驗信息vector2double(); //【1】首先添加上一次先驗殘差項if (last_marginalization_info && last_marginalization_info->valid){vector<int> drop_set;for (int i = 0; i < static_cast<int>(last_marginalization_parameter_blocks.size()); i++){//查詢last_marginalization_parameter_blocks中是首幀狀態量的序號if (last_marginalization_parameter_blocks[i] == para_Pose[0] ||last_marginalization_parameter_blocks[i] == para_SpeedBias[0])drop_set.push_back(i);}MarginalizationFactor *marginalization_factor = new MarginalizationFactor(last_marginalization_info);ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(marginalization_factor, NULL,last_marginalization_parameter_blocks,drop_set); //調用addResidualBlockInfo()函數將各個殘差以及殘差涉及的優化變量添加入優化變量中marginalization_info->addResidualBlockInfo(residual_block_info);}

【2】添加IMU的marg信息到 marginalization_info 中:第0幀和第1幀之間的IMU預積分值以及第0幀和第1幀相關優化變量

if(USE_IMU){if (pre_integrations[1]->sum_dt < 10.0){IMUFactor* imu_factor = new IMUFactor(pre_integrations[1]);//0和1是para_Pose[0], para_SpeedBias[0],需要marg的變量ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(imu_factor, NULL,vector<double *>{para_Pose[0], para_SpeedBias[0], para_Pose[1], para_SpeedBias[1]},vector<int>{0, 1});marginalization_info->addResidualBlockInfo(residual_block_info);}}

【3】最后添加第一次觀測滑窗中第0幀的路標點以及其他相關的滑窗中的幀的相關的優化變量 到 marginalization_info 中

{int feature_index = -1;//這里是遍歷滑窗所有的特征點for (auto &it_per_id : f_manager.feature){//該特征點被觀測到的次數it_per_id.used_num = it_per_id.feature_per_frame.size();if (it_per_id.used_num < 4)continue;++feature_index;int imu_i = it_per_id.start_frame, imu_j = imu_i - 1;//特征點的起始幀必須是首幀,因此后面用來構建marg矩陣的都是和第一幀有共視關系的滑窗幀,因為 marginalization_flag == MARGIN_OLDif (imu_i != 0)continue;//得到該Feature在起始幀下的歸一化坐標Vector3d pts_i = it_per_id.feature_per_frame[0].point;for (auto &it_per_frame : it_per_id.feature_per_frame){imu_j++;if(imu_i != imu_j)//不需要起始觀測幀{Vector3d pts_j = it_per_frame.point;ProjectionTwoFrameOneCamFactor *f_td = new ProjectionTwoFrameOneCamFactor(pts_i, pts_j, it_per_id.feature_per_frame[0].velocity, it_per_frame.velocity,it_per_id.feature_per_frame[0].cur_td, it_per_frame.cur_td);ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(f_td, loss_function, vector<double *>{para_Pose[imu_i], para_Pose[imu_j], para_Ex_Pose[0], para_Feature[feature_index], para_Td[0]},vector<int>{0, 3});marginalization_info->addResidualBlockInfo(residual_block_info);}if(STEREO && it_per_frame.is_stereo){Vector3d pts_j_right = it_per_frame.pointRight;if(imu_i != imu_j){ProjectionTwoFrameTwoCamFactor *f = new ProjectionTwoFrameTwoCamFactor(pts_i, pts_j_right, it_per_id.feature_per_frame[0].velocity, it_per_frame.velocityRight,it_per_id.feature_per_frame[0].cur_td, it_per_frame.cur_td);ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(f, loss_function,vector<double *>{para_Pose[imu_i], para_Pose[imu_j], para_Ex_Pose[0], para_Ex_Pose[1], para_Feature[feature_index], para_Td[0]},vector<int>{0, 4});marginalization_info->addResidualBlockInfo(residual_block_info);}else{ProjectionOneFrameTwoCamFactor *f = new ProjectionOneFrameTwoCamFactor(pts_i, pts_j_right, it_per_id.feature_per_frame[0].velocity, it_per_frame.velocityRight,it_per_id.feature_per_frame[0].cur_td, it_per_frame.cur_td);ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(f, loss_function,vector<double *>{para_Ex_Pose[0], para_Ex_Pose[1], para_Feature[feature_index], para_Td[0]},vector<int>{2});marginalization_info->addResidualBlockInfo(residual_block_info);}}}}}

【4】marginalization_info->preMarginalize():得到每次 IMU 和視覺觀測(cost_function)對 應的參數塊(parameter_blocks),雅可比矩陣(jacobians),殘差值(residuals);

?marginalization_info->preMarginalize();

【4】marginalization_info->marginalize():多線程計整個先驗項的參數塊,雅可比矩陣和 殘差值,其中與代碼對應關系為:

marginalization_info->marginalize();

【5】最后移交了優化項需要得到的兩個變量:last_marginalization_info和last_marginalization_parameter_blocks

std::unordered_map<long, double *> addr_shift;for (int i = 1; i <= WINDOW_SIZE; i++){addr_shift[reinterpret_cast<long>(para_Pose[i])] = para_Pose[i - 1];addr_shift[reinterpret_cast<long>(para_SpeedBias[i])] = para_SpeedBias[i - 1];}for (int i = 0; i < NUM_OF_CAM; i++)addr_shift[reinterpret_cast<long>(para_Ex_Pose[i])] = para_Ex_Pose[i];if (ESTIMATE_TD){addr_shift[reinterpret_cast<long>(para_Td[0])] = para_Td[0];}vector<double *> parameter_blocks = marginalization_info->getParameterBlocks(addr_shift);if (last_marginalization_info)delete last_marginalization_info;last_marginalization_info = marginalization_info;last_marginalization_parameter_blocks = parameter_blocks;

重要的三個結構變量:

  • MarginalizationFactor *marginalization_factor
  • *MarginalizationInfo marginalization_info
  • ResidualBlockInfo *residual_block_info

MarginalizationFactor *marginalization_factor 兩個作用:(1)構建ceres的殘差項,即計算residual (2)構建ResidualBlockInfo *residual_block_info

MarginalizationInfo *marginalization_info 由他可以獲取邊緣化信息,用它來構建MarginalizationFactor *marginalization_factor以及得到對應的參數塊

ResidualBlockInfo *residual_block_info 用它來豐富marginalization_info項的信息

從頭到位都是marginalization_info這個變量來進行統籌安排進行邊緣化。

通過marginalization_info->addResidualBlockInfo()來添加約束,有三個方面的來源:(1)舊的(2)imu預積分項(3)特征點

理解:

上面三步通過調用 addResidualBlockInfo() 已經確定優化變量的數量、存儲位置、長度以及待優化變量的數量以及存儲位置;

為什么要添加這些量呀?因為在k時刻這些量是我們要邊緣化掉的變量,殘差;但是k+1時刻就是我們的先驗,這不正是我們初衷嘛!

需要注意的是這些都是和第一幀圖像有關的!因為我們邊緣化的是最老幀!三部分的流程都是一樣的,如下:

第一步 定義損失函數,對于先驗殘差就是MarginalizationFactor,對于IMU就是IMUFactor,對于視覺就是ProjectionTdFactor,

這三個損失函數的類都是繼承自ceres的損失函數類ceres::CostFunction,里面都重載了函數; 函數通過傳入的優化變量值 parameters,

以及先驗值(對于先驗殘差就是上一時刻的先驗殘差last_marginalization_info,對于IMU就是預計分值pre_integrations[1],對于視覺

就是空間的的像素坐標pts_i, pts_j)可以計算出各項殘差值residuals,以及殘差對應個優化變量的雅克比矩陣jacobians;?

bool MarginalizationFactor::Evaluate(double const *const *parameters, double *residuals, double **jacobians) const {int n = marginalization_info->n;int m = marginalization_info->m;Eigen::VectorXd dx(n);//遍歷本次邊緣化保留下的參數塊:keep_block_sizefor (int i = 0; i < static_cast<int>(marginalization_info->keep_block_size.size()); i++){//得到該參數塊的大小和序號int size = marginalization_info->keep_block_size[i];int idx = marginalization_info->keep_block_idx[i] - m;//x 感覺是邊緣化之前 BA優化后的值 ?Eigen::VectorXd x = Eigen::Map<const Eigen::VectorXd>(parameters[i], size);//x0表示marg時參數塊變量的值(即xb)Eigen::VectorXd x0 = Eigen::Map<const Eigen::VectorXd>(marginalization_info->keep_block_data[i], size);if (size != 7)//speed_bias 9項dx.segment(idx, size) = x - x0;//變量的更新else//位置,姿態項, 姿態不能直接加減了!要變成四元素的 ?{//使用四元數的表達方式dx.segment<3>(idx + 0) = x.head<3>() - x0.head<3>();dx.segment<3>(idx + 3) = 2.0 * Utility::positify(Eigen::Quaterniond(x0(6), x0(3), x0(4), x0(5)).inverse() * Eigen::Quaterniond(x(6), x(3), x(4), x(5))).vec();if (!((Eigen::Quaterniond(x0(6), x0(3), x0(4), x0(5)).inverse() * Eigen::Quaterniond(x(6), x(3), x(4), x(5))).w() >= 0)){dx.segment<3>(idx + 3) = 2.0 * -Utility::positify(Eigen::Quaterniond(x0(6), x0(3), x0(4), x0(5)).inverse() * Eigen::Quaterniond(x(6), x(3), x(4), x(5))).vec();}}}//計算殘差,理解,泰勒展開求的公式Eigen::Map<Eigen::VectorXd>(residuals, n) = marginalization_info->linearized_residuals + marginalization_info->linearized_jacobians * dx;//僅在邊緣化殘差這一塊,雅克比矩陣要固定?if (jacobians){for (int i = 0; i < static_cast<int>(marginalization_info->keep_block_size.size()); i++){if (jacobians[i]){int size = marginalization_info->keep_block_size[i], local_size = marginalization_info->localSize(size);int idx = marginalization_info->keep_block_idx[i] - m;//Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> jacobian(jacobians[i], n, size);jacobian.setZero();jacobian.leftCols(local_size) = marginalization_info->linearized_jacobians.middleCols(idx, local_size);}}}return true; }

上面這段代碼是在優化過程中,對先驗約束項的更新,主要是對先驗殘差的更新,雅克比不再發生變化。
代碼中的x0 表示marg xm狀態時 xb變量的值; 優化過程中先驗項的雅克比保持不變,但是殘差需要變化,其變化公式推導如下:

第二步定義ResidualBlockInfo,其構造函數如下:

ResidualBlockInfo(ceres::CostFunction *_cost_function, ceres::LossFunction *_loss_function, std::vector<double *> _parameter_blocks, std::vector<int> _drop_set) ---------------------------------------------------------------------------------------------------- void ResidualBlockInfo::Evaluate() {//獲取殘差的個數: IMU + 視覺residuals.resize(cost_function->num_residuals());//優化變量參數塊的變量大小:para_Pose、para_SpeedBias、para_Ex_Pose、para_Feature、para_Tdstd::vector<int> block_sizes = cost_function->parameter_block_sizes();//數組外圍的大小,也就是參數塊的個數raw_jacobians = new double *[block_sizes.size()];jacobians.resize(block_sizes.size());//分配每一行的大小,殘差的維數*每個參數塊中參數的個數block_sizes[i],J矩陣大小的確認!想一下//比如:兩個殘差f1,f2;5個變量x1,x2,,,x5, 則J矩陣是2行5列呀for (int i = 0; i < static_cast<int>(block_sizes.size()); i++){jacobians[i].resize(cost_function->num_residuals(), block_sizes[i]);raw_jacobians[i] = jacobians[i].data();}//利用各自殘差的Evaluate函數計算殘差和雅克比矩陣。cost_function->Evaluate(parameter_blocks.data(), residuals.data(), raw_jacobians);//好像明白了,這個是視覺里面有的Huber核函數;有魯棒核函數的殘差部分,重寫雅克比與殘差if (loss_function){double residual_scaling_, alpha_sq_norm_;double sq_norm, rho[3];sq_norm = residuals.squaredNorm();loss_function->Evaluate(sq_norm, rho);double sqrt_rho1_ = sqrt(rho[1]);if ((sq_norm == 0.0) || (rho[2] <= 0.0)){residual_scaling_ = sqrt_rho1_;alpha_sq_norm_ = 0.0;}else//這一部分公式沒有看懂!{const double D = 1.0 + 2.0 * sq_norm * rho[2] / rho[1];const double alpha = 1.0 - sqrt(D);residual_scaling_ = sqrt_rho1_ / (1 - alpha); alpha_sq_norm_ = alpha / sq_norm; }//感覺像根據先驗殘差,推出新的殘差和雅可比公式一樣!for (int i = 0; i < static_cast<int>(parameter_blocks.size()); i++){jacobians[i] = sqrt_rho1_ * (jacobians[i] - alpha_sq_norm_ * residuals * (residuals.transpose() * jacobians[i]));}residuals *= residual_scaling_;} }

這一步是為了將不同的損失函數_cost_function以及優化變量_parameter_blocks統一起來再一起添加到marginalization_info中。

變量_loss_function是核函數,在VINS-mono的邊緣化中僅僅視覺殘差有用到核函數,另外會設置需要被邊緣話的優化變量的位置

_drop_set,這里對于不同損失函數又會有不同:對于先驗損失,其待邊緣化優化變量是根據是否等于para_Pose[0]或者

para_SpeedBias[0],也就是說和第一幀相關的優化變量都作為邊緣化的對象。對于IMU,其輸入的_drop_set是 vector{0, 1},

也就是說其待邊緣化變量是para_Pose[0], para_SpeedBias[0],也是第一幀相關的變量都作為邊緣化的對象,

里值得注意的是和后端優化不同,這里只添加了第一幀和第二幀的相關變量作為優化變量,因此邊緣化構造的信息矩陣會比

后端優化構造的信息矩陣要小對于視覺,其輸入的_drop_set是vector{0, 3},也就是說其待邊緣化變量是para_Pose[imu_i]和

para_Feature[feature_index],從這里可以看出來在VINS-mono的邊緣化操作中會不僅僅會邊緣化第一幀相關的優化變量,

還會邊緣化掉以第一幀為起始觀察幀的路標點。

問1:為什么輸入的_drop_set是 vector{0, 1},也就是說其待邊緣化變量是para_Pose[0], para_SpeedBias[0];

輸入的_drop_set是vector{0, 3},也就是說其待邊緣化變量是para_Pose[imu_i]和para_Feature[feature_index];

答1:如前面所示,優化變量是按照固定的順序排列的

序號?????? ? ? ? ? ? 變量??????????? ? ?? ???? ? ? ? ?? ?

?? 0???????????? para_Pose?????????????????
?? 1???????????? para_SpeedBias????
?? 2?????? ????? para_Ex_Pose???????
?? 3 ? ? ? ????? para_Feature???????????
?? 4???????????? para_Td??????????????????????

問2:最后一部分為什么要重寫殘差和雅可比公式?公式怎么來的?

答2:看過論文的童鞋應該知道,在優化部分,視覺是加了核函數的,這樣帶來的問題是其對應的殘差和雅可比是變的,這個應該很好理解:

比如: f(x) 的雅可比是J, 那么 ρ(f(x))的雅可比肯定變了! ρ 是核函數! 公式我沒有推出來,還請知道的兄弟告訴一下!

經過努力,得一絲頭緒! 其中核函數如下:

第三步是將定義的residual_block_info添加到marginalization_info中,通過下面這一句

marginalization_info->addResidualBlockInfo(residual_block_info);

addResidualBlockInfo() 這個函數的實現如下:

void MarginalizationInfo::addResidualBlockInfo(ResidualBlockInfo *residual_block_info) {factors.emplace_back(residual_block_info);//總殘差快std::vector<double *> &parameter_blocks = residual_block_info->parameter_blocks;std::vector<int> parameter_block_sizes = residual_block_info->cost_function->parameter_block_sizes();//這里應該是優化的變量for (int i = 0; i < static_cast<int>(residual_block_info->parameter_blocks.size()); i++){double *addr = parameter_blocks[i]; //指向數據的指針int size = parameter_block_sizes[i];//因為僅僅有地址不行,還需要有地址指向的這個數據的長度parameter_block_size[reinterpret_cast<long>(addr)] = size;//將指針強轉為數據的地址}//這里應該是待邊緣化的變量for (int i = 0; i < static_cast<int>(residual_block_info->drop_set.size()); i++){//這個是待邊緣化的變量的iddouble *addr = parameter_blocks[residual_block_info->drop_set[i]];//將需要marg的變量的id存入parameter_block_idxparameter_block_idx[reinterpret_cast<long>(addr)] = 0;} }

目的:

?將不同損失函數對應的優化變量、邊緣化位置存入到 parameter_block_sizes 和 parameter_block_idx中,這里注意的是執行到這一步,

parameter_block_idx 中僅僅有待邊緣化的優化變量的內存地址的key,而且其對應value全部為0;

【4】調用 preMarginalize() 進行預處理

上面通過調用 addResidualBlockInfo() 已經確定優化變量的數量、存儲位置、長度以及待優化變量的數量以及存儲位置,

下面就需要調用 preMarginalize() 進行預處理, 得到每次 IMU 和視覺觀測 (cost_function) 對 應的參數塊(parameter_blocks),

雅可比矩陣(jacobians),殘差值(residuals);

void MarginalizationInfo::preMarginalize() {//遍歷所有factor,在前面的addResidualBlockInfo中會將不同的殘差塊加入到factor中。for (auto it : factors){it->Evaluate();//利用多態性分別計算所有狀態變量構成的殘差和雅克比矩陣//遍歷所有參數塊std::vector<int> block_sizes = it->cost_function->parameter_block_sizes();for (int i = 0; i < static_cast<int>(block_sizes.size()); i++){//優化變量的地址long addr = reinterpret_cast<long>(it->parameter_blocks[i]);int size = block_sizes[i];//將factor中的參數塊復制到parameter_block_data中,parameter_block_data是整個優化變量的數據if (parameter_block_data.find(addr) == parameter_block_data.end()){double *data = new double[size]; //會在析構函數中刪除memcpy(data, it->parameter_blocks[i], sizeof(double) * size); //重新開辟一塊內存parameter_block_data[addr] = data;//通過之前優化變量的數據的地址和新開辟的內存數據進行關聯}}} }

it->Evaluate()? 這一句里面其實就是調用各個損失函數中的重載函數Evaluate(),這個函數前面有提到過:

【5】調用marginalize()

開啟多線程構建信息矩陣H和b ,同時從H,b中恢復出線性化雅克比和殘差

前面已經將數據都準備好了,下面通過調用marginalize()函數就要正式開始進行邊緣化操作了,實現如下:

void MarginalizationInfo::marginalize() {int pos = 0;for (auto &it : parameter_block_idx)//遍歷待marg的優化變量的內存地址{it.second = pos;pos += localSize(parameter_block_size[it.first]);}m = pos;//需要marg掉的變量個數for (const auto &it : parameter_block_size)//計算除了邊緣化之外要保留的參數塊{//如果這個變量不是是待marg的優化變量。if (parameter_block_idx.find(it.first) == parameter_block_idx.end()){parameter_block_idx[it.first] = pos;//就將這個待marg的變量id設為pospos += localSize(it.second); //pos加上這個變量的長度}}//上面的操作就會將所有的優化變量進行一個偽排序 n = pos - m;//要保留下來的變量個數if(m == 0){valid = false;printf("unstable tracking...\n");return;}TicToc t_summing;Eigen::MatrixXd A(pos, pos);//整個矩陣大小 --- 沒有邊緣化之前的矩陣Eigen::VectorXd b(pos);A.setZero();b.setZero();TicToc t_thread_summing;pthread_t tids[NUM_THREADS];ThreadsStruct threadsstruct[NUM_THREADS];//攜帶每個線程的輸入輸出信息//為每個線程均勻分配factor。int i = 0;for (auto it : factors){threadsstruct[i].sub_factors.push_back(it);i++;i = i % NUM_THREADS;}//構造4個線程,并確定線程的主程序for (int i = 0; i < NUM_THREADS; i++){TicToc zero_matrix;threadsstruct[i].A = Eigen::MatrixXd::Zero(pos,pos);threadsstruct[i].b = Eigen::VectorXd::Zero(pos);threadsstruct[i].parameter_block_size = parameter_block_size;threadsstruct[i].parameter_block_idx = parameter_block_idx;//分別構造矩陣int ret = pthread_create( &tids[i], NULL, ThreadsConstructA ,(void*)&(threadsstruct[i]));if (ret != 0){ROS_WARN("pthread_create error");ROS_BREAK();}}//將每個線程構建的A和b加起來for( int i = NUM_THREADS - 1; i >= 0; i--) {pthread_join( tids[i], NULL ); //阻塞等待線程完成A += threadsstruct[i].A;b += threadsstruct[i].b;}/*代碼中求Amm的逆矩陣時,為了保證數值穩定性,做了Amm=1/2*(Amm+Amm^T)的運算,Amm本身是一個對稱矩陣,所以 等式成立。接著對Amm進行了特征值分解,再求逆,更加的快速*/Eigen::MatrixXd Amm = 0.5 * (A.block(0, 0, m, m) + A.block(0, 0, m, m).transpose());Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> saes(Amm);Eigen::MatrixXd Amm_inv = saes.eigenvectors() * Eigen::VectorXd((saes.eigenvalues().array() > eps).select(saes.eigenvalues().array().inverse(), 0)).asDiagonal() * saes.eigenvectors().transpose();// 設x_{m}為要被marg掉的狀態量,x_{r}是與x_{m}相關的狀態量,所以在最后我們要保存的是x_{r}的信息//// | | | | |// | Amm | Amr| m |bmm| |x_{m}|// A = |______|____| b = |__ | A|x_{r}| = b// | Arm | Arr| n |brr|// | | | | |// 使用舒爾補:// C = Arr - Arm*Amm^{-1}Amr// d = brr - Arm*Amm^{-1}bmm//舒爾補,上面這段代碼邊緣化掉xm變量,保留xb變量 Eigen::VectorXd bmm = b.segment(0, m);Eigen::MatrixXd Amr = A.block(0, m, m, n);//0,m是開始的位置,m,m是開始位置后的大小Eigen::MatrixXd Arm = A.block(m, 0, n, m);Eigen::MatrixXd Arr = A.block(m, m, n, n);Eigen::VectorXd brr = b.segment(m, n);A = Arr - Arm * Amm_inv * Amr; b = brr - Arm * Amm_inv * bmm;//這里的A和b是marg過的A和b,大小是發生了變化的//下面就是更新先驗殘差項Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> saes2(A);//求更新后 A特征值Eigen::VectorXd S = Eigen::VectorXd((saes2.eigenvalues().array() > eps).select(saes2.eigenvalues().array(), 0));Eigen::VectorXd S_inv = Eigen::VectorXd((saes2.eigenvalues().array() > eps).select(saes2.eigenvalues().array().inverse(), 0));//求取特征值及其逆的均方根Eigen::VectorXd S_sqrt = S.cwiseSqrt();Eigen::VectorXd S_inv_sqrt = S_inv.cwiseSqrt();//分別指的是邊緣化之后從信息矩陣A和b中恢復出來雅克比矩陣和殘差向量;//兩者會作為先驗殘差帶入到下一輪的先驗殘差的雅克比和殘差的計算當中去linearized_jacobians = S_sqrt.asDiagonal() * saes2.eigenvectors().transpose();linearized_residuals = S_inv_sqrt.asDiagonal() * saes2.eigenvectors().transpose() * b; }

部分程序:

int pos = 0; //pos表示所有的被marg掉的參數塊以及它們的相連接參數塊的localsize之和for (auto &it : parameter_block_idx){it.second = pos;pos += localSize(parameter_block_size[it.first]);}m = pos; for (const auto &it : parameter_block_size){if (parameter_block_idx.find(it.first) == parameter_block_idx.end()){//將被marg掉參數的相連接參數塊添加道parameter_block_idx中parameter_block_idx[it.first] = pos;pos += localSize(it.second);}}n = pos - m;

這里對 參數塊變量進行排序,待marg的參數塊變量放在前面,其他參數塊變量放在后面,

并將每個參數塊的對應的下標放在parameter_block_idx中; pos = m + n

TicToc t_thread_summing;pthread_t tids[NUM_THREADS];//攜帶每個線程的輸入輸出信息ThreadsStruct threadsstruct[NUM_THREADS];int i = 0;//將先驗約束因子平均分配到線程中for (auto it : factors){threadsstruct[i].sub_factors.push_back(it);i++;i = i % NUM_THREADS;}for (int i = 0; i < NUM_THREADS; i++){TicToc zero_matrix;threadsstruct[i].A = Eigen::MatrixXd::Zero(pos,pos);threadsstruct[i].b = Eigen::VectorXd::Zero(pos);threadsstruct[i].parameter_block_size = parameter_block_size;threadsstruct[i].parameter_block_idx = parameter_block_idx;int ret = pthread_create( &tids[i], NULL, ThreadsConstructA ,(void*)&(threadsstruct[i]));if (ret != 0){ROS_WARN("pthread_create error");ROS_BREAK();}}//將每個線程構建的A和b加起來for( int i = NUM_THREADS - 1; i >= 0; i--) {pthread_join( tids[i], NULL ); //阻塞等待線程完成A += threadsstruct[i].A;b += threadsstruct[i].b;}

這段代碼開啟多線程來構建信息矩陣A和殘差b;將所有的先驗約束因子平均分配到NUM_THREADS個線程中,每個線程分別構建一個A和b;

函數會通過多線程快速構造各個殘差對應的各個優化變量的信息矩陣(雅克比和殘差前面都已經求出來了),如下圖所示:

這里構造信息矩陣時采用的正是 parameter_block_idx 作為構造順序,自然而然地將待邊緣化的變量構造在矩陣的左上方;

子函數?? void* ThreadsConstructA(void* threadsstruct)?????????????

void* ThreadsConstructA(void* threadsstruct) {ThreadsStruct* p = ((ThreadsStruct*)threadsstruct);//遍歷該線程分配的所有factors,所有觀測項for (auto it : p->sub_factors){//遍歷該factor中的所有參數塊,五個參數塊,分別計算,理解!for (int i = 0; i < static_cast<int>(it->parameter_blocks.size()); i++){//得到參數塊的大小int idx_i = p->parameter_block_idx[reinterpret_cast<long>(it->parameter_blocks[i])];int size_i = p->parameter_block_size[reinterpret_cast<long>(it->parameter_blocks[i])];if (size_i == 7)//對于pose來說,是7維的,最后一維為0,這里取左邊6size_i = 6;//只提取local size部分,對于pose來說,是7維的,最后一維為0,這里取左邊6維//P.leftCols(cols) = P(:, 1:cols),取出從1列開始的cols列Eigen::MatrixXd jacobian_i = it->jacobians[i].leftCols(size_i);for (int j = i; j < static_cast<int>(it->parameter_blocks.size()); j++){int idx_j = p->parameter_block_idx[reinterpret_cast<long>(it->parameter_blocks[j])];int size_j = p->parameter_block_size[reinterpret_cast<long>(it->parameter_blocks[j])];if (size_j == 7)size_j = 6;Eigen::MatrixXd jacobian_j = it->jacobians[j].leftCols(size_j);//對應對角區域,H*X=b, A代表H矩陣if (i == j)p->A.block(idx_i, idx_j, size_i, size_j) += jacobian_i.transpose() * jacobian_j;else{//對應非對角區域p->A.block(idx_i, idx_j, size_i, size_j) += jacobian_i.transpose() * jacobian_j;p->A.block(idx_j, idx_i, size_j, size_i) = p->A.block(idx_i, idx_j, size_i, size_j).transpose();}}//求取g,Hx=g,都是根據公式來寫程序的!p->b.segment(idx_i, size_i) += jacobian_i.transpose() * it->residuals;}}return threadsstruct; }

這部分代碼是用來實現構建A和b的:

Eigen::MatrixXd Amm = 0.5 * (A.block(0, 0, m, m) + A.block(0, 0, m, m).transpose());Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> saes(Amm);//ROS_ASSERT_MSG(saes.eigenvalues().minCoeff() >= -1e-4, "min eigenvalue %f", saes.eigenvalues().minCoeff());Eigen::MatrixXd Amm_inv = saes.eigenvectors() * Eigen::VectorXd((saes.eigenvalues().array() > eps).select(saes.eigenvalues().array().inverse(), 0)).asDiagonal() * saes.eigenvectors().transpose();//printf("error1: %f\n", (Amm * Amm_inv - Eigen::MatrixXd::Identity(m, m)).sum());Eigen::VectorXd bmm = b.segment(0, m);Eigen::MatrixXd Amr = A.block(0, m, m, n);Eigen::MatrixXd Arm = A.block(m, 0, n, m);Eigen::MatrixXd Arr = A.block(m, m, n, n);Eigen::VectorXd brr = b.segment(m, n);A = Arr - Arm * Amm_inv * Amr;b = brr - Arm * Amm_inv * bmm;

上面這段代碼邊緣化掉xm變量,保留xb變量,利用的方法是舒爾補

注意:上面這個等式就是先驗信息,程序中又變成了 AX = b 的形式,從A和b中恢復出雅克比矩陣和殘差,作為下一時刻的先驗信息;

代碼中求Amm的逆矩陣時,為了保證數值穩定性,做了Amm=1/2*(Amm+Amm^T)的運算,Amm本身是一個對稱矩陣,

所以等式成立。接著對Amm進行了特征值分解,再求逆,更加的快速。

Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> saes2(A);Eigen::VectorXd S = Eigen::VectorXd((saes2.eigenvalues().array() > eps).select(saes2.eigenvalues().array(), 0));Eigen::VectorXd S_inv = Eigen::VectorXd((saes2.eigenvalues().array() > eps).select(saes2.eigenvalues().array().inverse(), 0));Eigen::VectorXd S_sqrt = S.cwiseSqrt();Eigen::VectorXd S_inv_sqrt = S_inv.cwiseSqrt();linearized_jacobians = S_sqrt.asDiagonal() * saes2.eigenvectors().transpose();linearized_residuals = S_inv_sqrt.asDiagonal() * saes2.eigenvectors().transpose() * b;

上面這段代碼是從A和b中恢復出雅克比矩陣和殘差

【6】滑窗預移動

//這里僅僅將指針進行了一次移動,指針對應的數據還是舊數據,調用的 slideWindow() 才能實現真正的滑窗移動std::unordered_map<long, double *> addr_shift;for (int i = 1; i <= WINDOW_SIZE; i++)//從1開始,因為第一幀的狀態不要了{//這一步的操作指的是第i的位置存放的的是i-1的內容,這就意味著窗口向前移動了一格addr_shift[reinterpret_cast<long>(para_Pose[i])] = para_Pose[i - 1];if(USE_IMU)addr_shift[reinterpret_cast<long>(para_SpeedBias[i])] = para_SpeedBias[i - 1];}for (int i = 0; i < NUM_OF_CAM; i++)addr_shift[reinterpret_cast<long>(para_Ex_Pose[i])] = para_Ex_Pose[i];addr_shift[reinterpret_cast<long>(para_Td[0])] = para_Td[0];//根據地址來得到保留的參數塊vector<double *> parameter_blocks = marginalization_info->getParameterBlocks(addr_shift);if (last_marginalization_info)//Zbdelete last_marginalization_info; //刪除掉上一次的marg相關的內容last_marginalization_info = marginalization_info; //marg相關內容的遞歸last_marginalization_parameter_blocks = parameter_blocks; //優化變量的遞歸,這里面僅僅是指針}

這一部分應該很容易明白;當邊緣化幀的 “新幀”就不說了,把上面的看懂了,估計那個也會了

/------------------------------------------------------------------程序-----------------------------------------------------------------------/

總結

以上是生活随笔為你收集整理的VINS-Mono 代码解析六、边缘化(3)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

成年人免费在线播放 | 亚洲综合丁香 | 又黄又爽又无遮挡的视频 | 日日色综合| 韩日色视频| 国产精品亚洲综合久久 | 久久精品第一页 | 国产裸体视频网站 | 99婷婷狠狠成为人免费视频 | 亚洲国产经典视频 | 精品久久久久久久久久岛国gif | 久久久久女人精品毛片 | 人人超在线公开视频 | 国产一区二区电影在线观看 | 国产视频中文字幕在线观看 | 91视频免费观看 | 成人九九视频 | 国产日韩高清在线 | 中文字幕婷婷 | 中文字幕在线专区 | 日韩久久精品一区二区 | 久久成人国产精品免费软件 | 国产精品日韩精品 | 国产一级片直播 | 99久久久久免费精品国产 | 日韩在线资源 | 96精品视频 | 久久99精品国产一区二区三区 | 三级av小说| 国产一级免费视频 | 六月婷色 | 国产精品com | 国产视频在线观看免费 | 五月婷婷六月丁香 | 狠狠狠色丁香综合久久天下网 | 久久久综合香蕉尹人综合网 | 不卡av在线播放 | 五月激情五月激情 | 国产午夜精品久久久久久久久久 | 91福利社区在线观看 | 亚洲精品动漫久久久久 | 婷婷狠狠操 | 99精品欧美一区二区三区 | 日韩r级电影在线观看 | 免费在线观看黄色网 | 中文资源在线观看 | 日本成人中文字幕在线观看 | 免费视频一区二区 | 免费观看性生交 | av不卡免费在线观看 | 国产免费黄色 | 中文字幕亚洲精品日韩 | 欧美精品一二 | 亚洲高清视频一区二区三区 | avwww在线| 国内久久精品 | 欧洲一区二区三区精品 | 欧美日韩在线电影 | 午夜久久网站 | 免费观看mv大片高清 | 国产精品久久久 | 日本三级人妇 | 色综合久久综合网 | 黄色在线免费观看网站 | 日韩精品一卡 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 国产精品久久久久久爽爽爽 | 久久精品国产精品亚洲 | 91精品一区二区三区久久久久久 | 色吊丝在线永久观看最新版本 | 国产一区私人高清影院 | 国产精品欧美日韩 | 亚洲欧洲国产日韩精品 | 91九色蝌蚪国产 | 久久国产精品成人免费浪潮 | 91福利视频久久久久 | 久久综合九色综合久久久精品综合 | 午夜精品久久久久久中宇69 | 久草精品电影 | 欧美夫妻性生活电影 | 777奇米四色 | 99色在线视频| www.com久久| 91香蕉视频好色先生 | 天堂av一区二区 | 久久久久久蜜桃一区二区 | 欧美少妇18p | 亚洲成aⅴ人片久久青草影院 | 黄网站免费大全入口 | 麻豆久久 | 九九免费观看视频 | 日韩成人精品 | 国产精品一区二区三区电影 | 国产又粗又猛又黄又爽视频 | 日韩电影在线一区 | 亚洲精品国产综合久久 | 看v片 | 欧美另类亚洲 | 日韩高清三区 | free. 性欧美.com | 在线观看日本高清mv视频 | 人人澡人人舔 | 国产欧美综合在线观看 | 午夜精品一区二区三区四区 | 四虎www | 国产亚洲欧美精品久久久久久 | 亚洲欧美日韩国产一区二区三区 | 国产色一区 | 国产经典 欧美精品 | 日日久视频 | 国产精品入口a级 | 97国产超碰在线 | 午夜精品久久久久久久99水蜜桃 | 日本久久不卡视频 | av电影 一区二区 | 久久婷婷国产色一区二区三区 | 国产 精品 资源 | 激情欧美一区二区三区 | 亚洲一区二区精品3399 | 精品电影一区 | 日韩a级免费视频 | 在线亚洲精品 | 在线 国产一区 | 国产一区视频免费在线观看 | 久久综合久久综合这里只有精品 | 在线观看自拍 | 又黄又爽又色无遮挡免费 | 在线观看国产日韩 | 97国产在线观看 | 国产香蕉视频 | 欧美精品视 | 亚洲aⅴ一区二区三区 | 九九热在线视频免费观看 | 中文字幕在线字幕中文 | 久久久精品二区 | 久久在线视频精品 | 五月天国产 | 精品女同一区二区三区在线观看 | av日韩中文 | 在线观看免费视频你懂的 | 国产在线精品二区 | 插久久 | 性色av免费观看 | 国产黄色精品在线观看 | 在线观看91网站 | 亚洲精品xxx| 在线看片成人 | 日韩电影中文,亚洲精品乱码 | 69人人 | 亚洲va在线va天堂va偷拍 | 又黄又刺激视频 | 精品视频在线免费观看 | 麻豆国产视频下载 | 天天天色 | 丁香亚洲 | 国产一区二区在线免费观看 | 亚洲成人高清在线 | 17婷婷久久www| 国产精品一区二区三区免费视频 | 99爱国产精品 | 免费在线中文字幕 | 人人涩| 在线色亚洲 | 人人爽人人看 | 欧美 日韩 性 | 久久久电影网站 | 青青啪| 91一区啪爱嗯打偷拍欧美 | 久久综合偷偷噜噜噜色 | 久久一二区 | 亚洲国产精品传媒在线观看 | 香蕉视频在线免费 | 成人欧美一区二区三区在线观看 | 婷婷伊人五月 | 黄色一级大片在线免费看产 | 婷婷成人亚洲综合国产xv88 | 伊人婷婷久久 | 国产拍揄自揄精品视频麻豆 | www.成人sex| 一级性生活片 | 国产专区免费 | 免费色网站 | 久久久久亚洲精品 | 西西大胆免费视频 | 黄色在线观看免费 | 超碰人人在 | 欧美伦理一区二区三区 | 亚洲影视九九影院在线观看 | 国产高清视频 | 99久热在线精品视频成人一区 | 高清不卡免费视频 | 欧美日韩99| 成人三级网址 | 一级电影免费在线观看 | 欧美一区在线看 | www五月天 | 成人av电影在线播放 | 色 免费观看 | 狠狠躁夜夜躁人人爽超碰97香蕉 | www.久草.com| 日本中文不卡 | 亚洲精品免费看 | 狠狠干狠狠久久 | 超碰在线人人 | 婷婷色吧| 午夜精品一区二区国产 | 国产一区二区在线视频观看 | 在线视频一区观看 | 亚洲免费av片 | 中文字幕首页 | 五月婷婷开心 | 五月婷婷中文 | 天天激情站 | 探花视频在线观看免费版 | 亚洲午夜精品久久久 | 91一区二区三区久久久久国产乱 | 精品视频专区 | 国产精品九九视频 | 久久激情小说 | 国产精品精品国产婷婷这里av | 亚洲精品乱码久久久久久蜜桃动漫 | 免费网站黄色 | 成人动漫一区二区 | 亚洲精品tv久久久久久久久久 | 国产精品观看在线亚洲人成网 | 91电影福利| 成人毛片一区二区三区 | 欧美精品一区二区在线播放 | 中文字幕日韩伦理 | 亚州精品天堂中文字幕 | 国产又粗又猛又黄 | 国产成人一区二区三区久久精品 | 欧美日韩中文国产 | 日日夜夜精品 | 特级毛片爽www免费版 | 91女人18片女毛片60分钟 | 黄色资源在线观看 | 久久婷婷国产色一区二区三区 | 国产精品va在线 | 日韩精品免费在线播放 | 日韩精品视频在线免费观看 | www四虎影院| 久草网视频 | 在线观看视频在线 | 18久久久久 | 精品成人在线 | 国产免费资源 | 日韩欧美国产精品 | 一二区av | 精品一二三区 | 国产精品免费观看在线 | 午夜精品一区二区三区四区 | 91麻豆国产| 国产视频在线观看一区二区 | 狠狠色丁香久久婷婷综合_中 | 日韩精品不卡在线 | 99产精品成人啪免费网站 | 亚洲永久精品在线观看 | 97在线视频观看 | 久久免费99精品久久久久久 | 中日韩欧美精彩视频 | 亚洲国产午夜精品 | 2021久久 | 久久成人黄色 | 久久9精品 | 黄色一级免费 | 亚洲亚洲精品在线观看 | 欧洲激情在线 | 日韩精品视频免费 | 97精品国产97久久久久久久久久久久 | 激情深爱.com| 国产视频精品网 | 国产成人一区二区三区影院在线 | 欧美激情视频一二三区 | 一区二区三区免费播放 | 天天做夜夜做 | 麻豆传媒视频在线免费观看 | 日韩欧美在线播放 | 中文av免费| 午夜精品久久久久 | 狠狠操狠狠插 | 久久久久女人精品毛片九一 | 国产黄色一级片在线 | 欧美一级在线看 | 亚洲综合欧美日韩狠狠色 | 一区二区亚洲精品 | 日韩精品久久久免费观看夜色 | 欧美日韩精品在线视频 | 亚洲综合在线视频 | 久久精品男人的天堂 | www中文在线 | 日韩免费一区二区三区 | 久久久久久看片 | 91精品久久久久久久久久入口 | 国产在线精品二区 | 天天射天天干天天操 | 91精品毛片 | 国产对白av | 免费国产黄线在线观看视频 | 超碰在线成人 | 国产黄免费在线观看 | 日韩一级黄色片 | 国产欧美精品一区二区三区四区 | 亚洲黄色a| 日日躁你夜夜躁你av蜜 | 区一区二区三区中文字幕 | 国产视频综合在线 | 碰超在线97人人 | 国产又粗又猛又色又黄网站 | 日韩91av| 超碰在线人| 欧美视频不卡 | 五月天com | 亚洲黄色一级大片 | 欧美性色综合 | 久久久久久久99精品免费观看 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 激情av一区二区 | a在线观看免费视频 | 免费精品人在线二线三线 | 天天射综合 | 亚洲在线视频网站 | 国产91精品一区二区麻豆网站 | 日韩在线观看影院 | 欧美一级乱黄 | 一区在线电影 | 色婷婷成人网 | 色婷婷久久久综合中文字幕 | 97看片吧| 国产亚洲一区二区三区 | 黄色av网站在线免费观看 | 国产小视频91 | 久久综合久久八八 | 西西人体4444www高清视频 | 久草在线手机观看 | 国产在线a免费观看 | 在线视频手机国产 | 美女久久久久久久久久 | 91高清完整版在线观看 | 中文字幕av影院 | 国产视频在线观看一区二区 | 欧美va天堂在线电影 | 9在线观看免费高清完整版在线观看明 | 成人黄色片在线播放 | 久久这里只有精品久久 | 国产精品一区二区在线播放 | 色天天综合网 | 天天操天操 | 久久国产a | 欧美日韩精品免费观看 | 国产成人精品aaa | 伊人va| 国产精品一区二区无线 | 欧美一二三区在线观看 | 亚洲人成人在线 | www.五月婷婷.com | 欧美日韩国产在线 | 欧美综合在线视频 | 国产精品对白一区二区三区 | 中文字幕高清在线 | 99国产在线 | 欧美日韩国产网站 | 色综合久久久久综合体 | 97视频在线免费观看 | 在线观看免费av片 | 一区二区三区日韩在线观看 | 国产精品美女久久久久久久久久久 | 久久精品视频在线观看免费 | 综合久久影院 | 一本一本久久a久久精品综合妖精 | 黄色三级免费 | 亚洲理论在线观看 | 精品在线观看国产 | 在线观看激情av | 成人黄色电影视频 | 中文字幕一区在线观看视频 | 久久午夜精品影院一区 | 欧美日韩久久一区 | av在线com| 国产一级电影 | 国产高清视频在线免费观看 | 久热久草在线 | 国产精品成人久久久久 | 人人讲 | 国产探花视频在线播放 | 国产视频二区三区 | 久久精品看片 | 亚洲成人动漫在线观看 | 在线播放你懂 | 天天干,天天射,天天操,天天摸 | 婷婷综合视频 | 欧美日韩伦理在线 | 亚洲精品久久久蜜桃直播 | 精品一区三区 | 久久精品福利视频 | 蜜臀av性久久久久av蜜臀三区 | 美女视频黄,久久 | 丁香影院在线 | 免费日韩电影 | 国产成人黄色片 | www激情com| 国产精品 日韩精品 | 这里只有精品视频在线 | 国产精品999久久久 久产久精国产品 | 成av人电影 | 亚洲aⅴ乱码精品成人区 | 国产精品资源 | 亚洲国产精品久久久 | 日韩激情在线 | 91高清在线看| 中文在线a天堂 | 欧美日韩18 | 伊人婷婷网 | 国产成人一区二区三区电影 | 亚洲黄色免费电影 | 国产中文字幕视频在线观看 | 欧美日韩高清国产 | 中文字幕中文字幕在线中文字幕三区 | 6080yy精品一区二区三区 | 亚洲视频在线免费观看 | 91传媒在线看| www成人av| 久久中文字幕导航 | 婷婷综合五月天 | 精品亚洲va在线va天堂资源站 | 在线亚洲激情 | 日本女人逼 | 久久久免费精品国产一区二区 | 精品综合久久久 | 在线中文字幕播放 | 麻豆久久精品 | 啪啪肉肉污av国网站 | 亚州黄色一级 | 欧美大片在线看免费观看 | 天天综合网~永久入口 | 91麻豆精品一区二区三区 | 久久久久久久久久网站 | 91麻豆精品国产91久久久久久久久 | 国产 日韩 中文字幕 | 99久久99久久精品国产片果冰 | 国产不卡片 | 成人久久免费 | 久久久亚洲精华液 | 不卡的av电影在线观看 | 免费a视频 | 天天综合五月天 | 91视频免费国产 | av高清在线 | 国产青春久久久国产毛片 | 久久免费精彩视频 | 精品99在线 | 免费色视频在线 | 激情久久久久 | 久久精品4| 国产精品永久久久久久久www | 黄色网址中文字幕 | 最近免费观看的电影完整版 | 999毛片 | 国产精品久久久久三级 | 福利二区视频 | 国产精品一区二区精品视频免费看 | 日本mv大片欧洲mv大片 | 国产伦理久久 | 天天干天天插伊人网 | а天堂中文最新一区二区三区 | 婷婷网五月天 | 久久精品综合 | 亚洲一区精品二人人爽久久 | 免费国产亚洲视频 | 91黄色成人 | 国产麻豆精品免费视频 | 四虎成人精品永久免费av | 欧美精品久久久久久久 | 国内少妇自拍视频一区 | 天天摸天天干天天操天天射 | 免费毛片aaaaaa | 亚洲专区在线播放 | 亚洲国产日韩在线 | 久久久久久综合网天天 | 久插视频 | 久久人人97超碰国产公开结果 | 久久精品福利 | 久久成| 一区二区中文字幕在线播放 | 欧美坐爱视频 | 91亚洲国产成人 | 国产一区二区综合 | 国产二级视频 | 麻豆视频入口 | 黄色电影小说 | 欧美日韩久 | 日韩精品短视频 | 91麻豆网站 | 国产成人av在线影院 | 91久久国产自产拍夜夜嗨 | 久久久久一区 | 狠狠干中文字幕 | 97操碰| 久久精彩免费视频 | 91精品办公室少妇高潮对白 | 91亚洲精品久久久中文字幕 | 中文字幕丝袜美腿 | 九九热有精品 | av大全在线观看 | 免费91麻豆精品国产自产在线观看 | 亚洲一级片av | www..com黄色片 | 日韩在线看片 | 日韩高清在线一区二区三区 | 日韩 在线观看 | 伊人天天操 | 国产精彩视频一区 | 91豆花在线观看 | 香蕉视频久久久 | 五月开心六月伊人色婷婷 | 精品一区二区三区香蕉蜜桃 | 久国产在线播放 | 一区二区三区四区五区在线 | 国产成人免费精品 | 久久国内视频 | 麻豆国产精品永久免费视频 | 黄av资源 | 日韩在线电影一区二区 | 91精品国产综合久久福利 | 国产三级视频在线 | 久久一区二区三区超碰国产精品 | 久久精品一级片 | 亚州免费视频 | 中文字幕在线观看国产 | 久久午夜精品 | 久久久国产一区二区 | 特级a毛片| 五月天色丁香 | 国产成人久久精品77777 | 久久久国产毛片 | 国产黄色大全 | 婷婷av网站 | 日韩在线观看的 | 成人在线观看你懂的 | 国产一区二区在线精品 | 欧美日本国产在线观看 | 成人影片在线免费观看 | 五月天婷婷视频 | 精品国产伦一区二区三区 | 久艹在线观看视频 | 欧美成人影音 | 最新成人av | 黄色性av| 天天综合视频在线观看 | 成人毛片网 | 日本久久片 | 中文字幕乱视频 | 国产乱对白刺激视频不卡 | 国产麻豆精品一区 | 亚洲作爱视频 | 五月开心六月婷婷 | 97超碰超碰久久福利超碰 | 日韩免费成人av | 精品国精品自拍自在线 | 久久综合九色九九 | 日韩精品一区二区久久 | 高清一区二区三区 | 美女免费网站 | 色偷偷中文字幕 | 天天舔天天射天天操 | 国产在线高清精品 | 国产99久久 | 国产免费区 | 丁香婷婷在线 | 国产视频亚洲 | 99一级片 | 日韩欧美视频在线观看免费 | 久久久激情视频 | 日韩高清在线一区 | 久久久久二区 | av在线网站免费观看 | 国产精品久久久久久麻豆一区 | 东方av在线免费观看 | 麻豆播放| 国产精品一区二区在线播放 | 国产91勾搭技师精品 | 天天操夜夜看 | 欧美亚洲三级 | 中文字幕一区二区在线播放 | 色婷婷狠狠五月综合天色拍 | 激情av五月婷婷 | 91综合久久一区二区 | 欧美特一级片 | 日韩av电影一区 | 国产精品一区二区在线看 | 500部大龄熟乱视频使用方法 | 免费麻豆网站 | 91黄色在线视频 | 久久精品欧美 | 最新中文字幕在线观看视频 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 国产美女精品在线 | 六月丁香在线观看 | 久久r精品| 日韩av专区| 91在线超碰 | 久久a热6 | 久草视频在线播放 | 91免费网站在线观看 | 国产视频精品久久 | 免费看黄在线看 | 夜夜操天天操 | 久久婷五月 | 欧美激情综合五月色丁香小说 | 欧美日韩中文字幕综合视频 | 久久色视频 | 国产成人一区三区 | 欧美激精品| 国产精品久久久久久久久久免费看 | 婷婷久久一区二区三区 | 国产亚洲精品无 | 久久精品一区 | 在线观看你懂的网站 | 在线日韩视频 | 久久久国产精品久久久 | 中文字幕亚洲精品在线观看 | 成人免费一级 | 天天干一干 | 国产欧美中文字幕 | 97夜夜澡人人爽人人免费 | 美州a亚洲一视本频v色道 | 国产精品手机在线观看 | 99视频国产在线 | 在线国产日本 | 精品国产一区二区三区久久影院 | 日本久久中文字幕 | 91在线一区| 91c网站色版视频 | 日韩精品极品视频 | 精品伊人久久久 | 亚洲精品一区二区三区高潮 | 中文字幕永久 | 成年人免费电影在线观看 | 亚洲电影黄色 | 国产精品专区在线观看 | 国产福利91精品一区二区三区 | 国产99久久久国产精品免费看 | 日韩欧美精品在线观看视频 | 亚洲视频国产 | 日本久久久久 | 亚洲精品久久久蜜臀下载官网 | 久久婷婷精品 | 精品资源在线 | 国产一级做a爱片久久毛片a | 一区三区视频 | 久久精品99久久久久久 | 成人动态视频 | 国产一区二区三区视频在线 | 国产精品美女久久久 | 国产日韩精品一区二区三区在线 | 国产免费美女 | 亚洲国产精久久久久久久 | 久操久 | 激情丁香久久 | 五月婷婷影视 | 波多野结衣一区三区 | 国产精品视频地址 | 色婷婷av一区 | 黄色片网站 | 亚洲精品乱码久久久一二三 | 91av在线看 | 国产精品免费观看视频 | 亚洲精品五月天 | 五月激情丁香图片 | 999ZYZ玖玖资源站永久 | 免费高清看电视网站 | 日韩精品一区电影 | 欧美在线一二区 | 亚洲伊人网在线观看 | 96超碰在线 | 在线导航av | 日韩欧美在线观看一区二区三区 | 亚洲 欧美变态 另类 综合 | 欧美日韩一区二区在线 | 精品视频一区在线 | 91精品在线免费 | 亚洲人片在线观看 | 亚洲精品www. | 天天干天天拍天天操天天拍 | 国产伦精品一区二区三区高清 | 国产黄在线 | 99精品视频在线观看播放 | 久久国产一区二区三区 | 日韩v欧美v日本v亚洲v国产v | 91九色蝌蚪国产 | 欧美另类视频 | 香蕉视频在线播放 | 国产视频1 | 免费看av在线 | 伊人一级| 一级片免费观看视频 | 三级av在线| 亚洲国产成人在线播放 | 91九色蝌蚪在线 | 国产高清视频在线播放一区 | 天天射天天干天天插 | 欧美精品在线一区二区 | 日韩久久精品 | 一区二区电影在线观看 | 国产黄a三级三级三级三级三级 | 日韩午夜在线 | 国产精品高潮呻吟久久av无 | 日本3级在线观看 | 色婷婷av一区 | av线上看 | 男女激情免费网站 | 日批网站免费观看 | 51久久夜色精品国产麻豆 | av一区在线| 夜夜夜夜夜夜操 | 97福利在线 | 亚洲毛片一区二区三区 | 国产一区欧美在线 | 久热免费在线观看 | 亚洲电影图片小说 | 一区中文字幕在线观看 | 欧美日性视频 | 国内一级片在线观看 | 国产免费久久av | 色操插 | 91麻豆精品国产自产 | 一区二区三区四区久久 | 在线观看亚洲国产精品 | 蜜臀av性久久久久av蜜臀三区 | 女人18毛片90分钟 | 国产喷水在线 | 亚洲国产大片 | 成人黄色电影视频 | 天天在线操 | 午夜av日韩 | 天天操天天添天天吹 | 五月激情婷婷丁香 | 色婷婷综合久久久久中文字幕1 | 久草影视在线 | 99在线视频精品 | 狠狠撸电影 | 国产麻豆视频在线观看 | 99国内精品 | 亚洲永久av | 欧美日韩中文字幕视频 | 91在线精品观看 | a成人v | 亚洲国产欧美在线人成大黄瓜 | 色香蕉视频 | 18av在线视频 | 成人中心免费视频 | 国产中文字幕三区 | 在线观看欧美成人 | 美女国产免费 | 亚洲成年人在线播放 | 久久国产精品网站 | 在线免费黄 | 激情综合网婷婷 | 手机在线看片日韩 | 国产精品毛片一区二区在线 | 亚洲五月 | 久久99久国产精品黄毛片入口 | 日日夜夜网站 | 亚洲资源在线网 | 亚洲成人精品久久 | 黄av在线 | 四虎国产精品免费 | 中文字幕av免费 | 国产精品免费久久久久久 | 九九九热 | 日韩va在线观看 | 深爱激情久久 | 国产日韩视频在线 | av片一区二区 | 亚洲丁香日韩 | 又色又爽又黄高潮的免费视频 | 久草精品在线播放 | 国产日韩欧美视频在线观看 | 国产91丝袜在线播放动漫 | 午夜av免费看 | 中文字幕在线视频国产 | 亚洲黄色在线免费观看 | 91人人插| 91人人澡人人爽人人精品 | 操老逼免费视频 | 97在线观看免费观看高清 | 欧美日韩高清一区二区三区 | 中文字幕麻豆 | 午夜影视av | 精品国偷自产在线 | 亚州av免费 | 国内精品视频久久 | www天天操| 久久久久久久精 | 日韩在线观看视频免费 | 中文字幕在线网址 | 欧美精品小视频 | 91在线91| 91传媒在线播放 | 亚洲精品视频在线观看免费视频 | 免费视频在线观看网站 | 午夜久操| 成人av网址大全 | 爱色婷婷| 国产色视频网站 | 亚洲日本一区二区在线 | 手机在线黄色网址 | 久久综合影视 | 99视频在线精品免费观看2 | 国产精品不卡在线观看 | 亚洲精品视频网站在线观看 | 亚洲一级特黄 | 精品国产a | 欧美在线视频精品 | 欧美资源 | 人交video另类hd | 三级黄色片在线观看 | 欧美怡红院| 免费成人av | 九色91福利 | 91传媒免费观看 | 久精品视频在线 | 激情综合网在线观看 | 黄色软件大全网站 | 欧美一级片播放 | 国产精品午夜8888 | 久久五月情影视 | 久久系列 | 国产在线最新 | 一区三区视频在线观看 | 日韩欧美在线观看 | 日韩在线观看你懂得 | 日韩福利在线观看 | 久久久香蕉视频 | 97在线视| 色婷婷视频在线 | 97精品国产91久久久久久久 | 日韩精品一二三 | 欧美成年人在线观看 | 一区二区欧美在线观看 | 日韩在线二区 | 国产精品毛片久久久 | 国产成人久久精品一区二区三区 | 97视频在线观看免费 | 在线观看一区视频 | 免费在线观看污 | 久久国色夜色精品国产 | 狠狠色伊人亚洲综合网站色 | 少妇av片| 久久综合久久八八 | 网站在线观看你们懂的 | 欧美一级免费 | 日夜夜精品视频 | 久久国产精品99久久久久久老狼 | 91福利国产在线观看 | 成人国产一区 | 久草在线视频国产 | 97碰碰视频 | 日韩美在线观看 | 色综合久久中文字幕综合网 | 精品一区二区电影 | 97视频免费在线 | 亚洲黄色在线免费观看 | 国产麻豆电影 | 日韩电影久久久 | 久久公开免费视频 | 超碰com| 欧美精品二区 | 国产在线视频不卡 | 九九色网| av综合av| 黄色av成人在线观看 | 国产精品毛片久久久久久久久久99999999 | 香蕉视频日本 | 最近中文字幕视频完整版 | 国产精品日韩久久久久 | 在线国产日本 | 五月婷婷色丁香 | 亚洲精品免费在线观看 | 日韩欧美综合精品 | 99精品国产一区二区三区麻豆 | 天天干一干 | 最近免费中文视频 | 日韩高清在线观看 | 9免费视频| 中文字幕在线观看视频一区二区三区 | 中文字幕乱码亚洲精品一区 | 国产97视频在线 | 黄色毛片视频免费观看中文 | 亚洲国产欧美一区二区三区丁香婷 | 日韩欧美区 | 欧美黑人性爽 | 99国内精品 | 日韩在线观看不卡 | 欧美成人猛片 | 激情五月激情综合网 | 亚洲成人软件 | 日韩欧美专区 | 亚洲性少妇性猛交wwww乱大交 | 亚洲精品午夜视频 | 久草视频在线播放 | 国产免费又黄又爽 | 日韩av影片在线观看 | 中文字幕一区二区三区乱码在线 | 韩国av免费在线观看 | 天天久久夜夜 | 香蕉久草 | 日本久久不卡视频 | 成年人黄色免费看 | 干干日日| 欧洲精品久久久久毛片完整版 | 日韩动态视频 | 一个色综合网站 | 色综合久久综合中文综合网 | 国产精品美女免费看 | 在线观看午夜av | 久久久久在线 | 中国一级片视频 | 免费av电影网站 | 免费能看的黄色片 | 天天操天天爱天天爽 | 亚洲午夜精品久久久久久久久久久久 | 国产 日韩 在线 亚洲 字幕 中文 | 97碰在线视频 | 欧美极品一区二区三区 | 黄色一级免费 | 日日夜夜综合网 | 中文字幕精品久久 | 久草视频在线免费 | 五月天激情开心 | 免费国产在线视频 | 欧美日韩一区久久 | 日日夜夜综合网 | 成人久久影院 | 亚洲 欧美 综合 在线 精品 | 久久精品欧美一区二区三区麻豆 | 久草免费在线观看视频 | 国产小视频免费观看 | 奇米先锋 | 中文字幕成人一区 | 日日爱夜夜爱 | 天天舔夜夜操 | 一区二区三区四区在线 | 最近乱久中文字幕 | 国产夫妻av在线 | 91天堂素人约啪 | www好男人| 精品黄色在线观看 | 黄网站免费看 | 日日夜夜精品免费视频 | 久久国产精品二国产精品中国洋人 | 日韩av进入| www..com毛片 | 亚洲日本激情 | 中文字幕在线观看视频一区 | 99在线精品视频观看 | 久久精品一区二区三区四区 | 国产黄av| 97色在线观看 | 免费在线看v | 成人超碰97 | 日韩3区 | 91麻豆免费看| 日韩电影一区二区在线观看 | 欧美日韩在线观看一区二区三区 | 91激情视频在线 | 丁香狠狠 | 国产综合久久 | 一区二区三区国 | 久久久久久伊人 | 超碰在线网 | 成人在线视频免费观看 | 国产日产精品一区二区三区四区 | 免费在线观看av网站 | 网站在线观看日韩 | 日韩精品2区 | 免费在线成人av电影 | 精品国产精品久久一区免费式 | 久久久久久久久久久黄色 | 狠狠躁夜夜躁人人爽超碰91 | 久久a v电影 | 亚洲影视资源 | 久久精彩视频 | 久久国产精品免费一区 | 最近字幕在线观看第一季 | 国产成人精品一区二区三区网站观看 | 精品国偷自产在线 | 国产资源免费在线观看 | 一级免费观看 | 色综合天天狠狠 | 久久久久中文字幕 | 日韩亚洲精品电影 | av免费在线网 | 99re国产| 亚洲 综合 专区 | 毛片网在线观看 | 国产手机视频在线 | 亚洲资源在线 |