樹莓派3B/3B+和4B安裝OpenCV教程 (屢試不爽)

    

安裝前準備

  1. 在樹莓派上拓展文件系統

    如果你使用的樹莓派為新裝的系統,那麼第一件事情就是擴展文件系統,以包括microSD卡上的所有空間。

    具體步驟如下:

      1.在樹莓派終端(或者SSH)上輸入:

1 $ sudo raspi-config

 

      2.然後選擇“高級選項”菜單項

   

       3.然後選擇“擴展文件系統”:

  

       4. 選擇第一個選項“A1.Expand Filesystem”,按鍵盤上的Enter鍵,完成後點擊“Finish”按鈕,重新啟動樹莓派。

    如果不能重啟,則可以執行以下操作:

1 $ sudo reboot

 

      重新啟動后,文件系統已經擴展為包括micro-SD卡上的所有空間。可以通過執行 df -h 檢查輸出來驗證磁盤是否已擴展。

1 $ df -h

 

 

  

 

      5. 此時我的樹莓派文件系統已擴展為包含16GB的micor-SD卡。如果您使用的是8GB卡,則可能使用了將近50%的可用空間,

    因此,一件簡單的事情就是刪除LibreOffice和Wolfram引擎以釋放Pi上的一些空間:

1 $ sudo apt-get purge wolfram-engine
2 $ sudo apt-get purge libreoffice*
3 $ sudo apt-get clean
4 $ sudo apt-get autoremove

 

 

  2.更換樹莓派源為清華鏡像源,防止後面下載GTK2.0失敗。

    換源方法參考:

安裝步驟

   1.更新系統

1 $ sudo apt-get update && sudo apt-get upgrade

   

   2.在樹莓派上安裝OpenCV所需要依賴的工具和一些圖像視頻庫

  • 安裝包括CMake的開發人員工具

    1 // 安裝build-essential、cmake、git和pkg-config
    2 sudo apt-get install build-essential cmake git pkg-config 

     

  • 安裝常用圖像工具包

    1 // 安裝jpeg格式圖像工具包
    2 sudo apt-get install libjpeg8-dev 

     

    1 // 安裝tif格式圖像工具包
    2 sudo apt-get install libtiff5-dev 

     

    1 // 安裝JPEG-2000圖像工具包
    2 sudo apt-get install libjasper-dev 

     

    1 // 安裝png圖像工具包
    2 sudo apt-get install libpng12-dev 

     

  • 安裝常用的視頻庫

1 //v4l中4後面的是 英文字母“l”
2 sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev

 

  

  • 安裝GTK2.0

    1 sudo apt-get install libgtk2.0-dev

     

  • 安裝OpenCV數值優化函數包

1 sudo apt-get install libatlas-base-dev gfortran

 

    

 

    3.下載編譯OpenCV源碼

  • 下載opencv3.4.3和opencv_contrib3.4.3

1 // 下載OpenCV
2 wget -O opencv-3.4.3.zip https://github.com/Itseez/opencv/archive/3.4.3.zip

 

   

1 // 解壓OpenCV
2 unzip opencv-3.4.3.zip

 

   

1 // 下載OpenCV_contrib庫:
2 wget -O opencv_contrib-3.4.3.zip https://github.com/Itseez/opencv_contrib/archive/3.4.3.zip

 

   

 

1 // 解壓OpenCV_contrib庫:
2 unzip opencv_contrib-3.4.3.zip

   

  • 配置CMake編譯OpenCV 3環境

    使用CMake設置編譯,然後運行 make 來編譯OpenCV。這是整個過程中耗時最長的步驟,大約4個小時。

    回到OpenCV存儲庫並創建 build 文件夾,用來存放 CMake 編譯時產生的臨時文件。

1 //具體路徑請以實際為準
2 cd ~/opencv-3.4.3
3 
4 // 新建build文件夾
5 mkdir build
6      
7 // 進入build文件夾
8 cd build
9   

   

 

  •  設置CMake編譯參數,安裝目錄默認為/usr/local

    注意參數名、等號和參數值之間不能有空格,每行末尾“\”之前有空格,這裏使用換行符“\”是為了看起來工整,參數值最後是兩個英文的點,意思是上級

  目錄(【注意】如果在root用戶下執行cmake命令,請將OPENCV_EXTRA_MODULES_PATH的值改為絕對路徑,如:/home/pi/opencv_contrib-3.4.3/modules):

/** CMAKE_BUILD_TYPE是編譯方式
* CMAKE_INSTALL_PREFIX是安裝目錄
* OPENCV_EXTRA_MODULES_PATH是加載額外模塊
* INSTALL_PYTHON_EXAMPLES是安裝官方python例程
* BUILD_EXAMPLES是編譯例程(這兩個可以不加,不加編譯稍微快一點點,想要C語言的例程的話,在最後一行前加參數INSTALL_C_EXAMPLES=ON,要C++例程的話在最後一行前加參數INSTALL_C_EXAMPLES=ONINSTALL_CXX_EXAMPLES=ON)
**/
 
sudo cmake -D CMAKE_BUILD_TYPE=RELEASE \
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.4.3/modules \
    -D INSTALL_PYTHON_EXAMPLES=ON \
    -D INSTALL_CXX_EXAMPLES=ON \
    -D BUILD_EXAMPLES=ON ..
 

   

 

     配置完后如下圖:

   

 

  • 備份build文件中的東西

     因為下一步的編譯會使用build文件中的東西,假如編譯失敗后還要重新進行cmake,比較耽誤時間,這裏可以直接備份一下cmake好的build文件夾,

  命名為build1,重新make的時候可以拿來用。

1 //返回上層目錄
2 cd ..
3 //備份release文件夾
4 cp -r release ./release1

  

  • 為樹莓派增加SWAP

    在開始編譯之前,建議你增加交換空間。這將使你使用樹莓派的所有四個內核來編譯OpenCV,而不會由於內存耗盡導致編譯掛起。

    打開 etc dphys – swapfile   文件:

1 $ sudo nano /etc/dphys-swapfile

    然後編輯 CONF_SWAPSIZE  變量:

   

 

      注意:此處我將交換空間從100MB增加到2048MB;如果你不執行此步驟,你的樹莓派編譯時很可能掛起。

    重新啟動交換服務:

1 $ sudo /etc/init.d/dphys-swapfile stop
2 $ sudo /etc/init.d/dphys-swapfile start

   

 

     注意:增加交換空間的大小是燒壞樹莓派 microSD卡的好方法。基於閃存的存儲只能執行有限數量的寫操作,直到該卡基本不能夠容納1和0。我們只能在短時間內

  啟動大型交換,所以這沒什麼大問題的。

  • 編譯OpenCV 3

1 /**
2 * 以管理員身份,否則容易出錯
3 * make命令參數-j4指允許make使用最多4個線程進行編譯,這樣編譯速度會更快
4 * 可以根據自己機器的情況進行更改
5 * 使用tee命令可以將編譯過程中終端显示的信息保存到make.log文件中,便於查看,這樣即使VNC斷線,終端的* 信息太多看不到,也可以通過make.log文件查看編譯過程。
6 **/
7  
8 sudo make -j4 2>&1 | tee make.log

   

 

    如果看到進度編譯到100%,那麼說明編譯安裝成功。

   

1 // 安裝
2 sudo make install
3  
4 // 更新動態鏈接庫
5 sudo ldconfig

    

    注意: 不要忘記回到 /etc/dphysswapfile 文件:

       1.將 CONF_SWAPSIZE 重置為 100MB

       2.重新啟動交換服務

其他配置

   設置庫的路徑,相當於windows下的環境變量,便於使用OpenCV庫,也可以不進行設置,使用的時候說明路徑也可。例如在編譯時說明使用庫的路徑是 -L/usr/local/lib 

 

  1.配置opencv.conf 

   打開opencv.conf配置文件,在末端加入如下內容: 

 1 //這裏我使用的是樹莓派默認的nano,也可以使用vim、gedit.打開opencv.conf文件
 2 sudo nano /etc/ld.so.conf.d/opencv.conf
 3 
 4 /**
 5 *在末端添加如下內容
 6 *注意:?表示一個空格,可能原因是有的語言要求最後有一個空格才可以編譯通過。
 7 **/
 8 /usr/local/lib
 9 ?
10 
11 //加載一下
12sudo ldconfig

   

  2.打開 bash.bashrc 配置文件 

1 //打開bash.bashrc配置文件
2 sudo gedit /etc/bash.bashrc
3 
4 
5 // 在最後添加如下內容
6 PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig       
7 export PKG_CONFIG_PATH

    

  3.重啟樹莓派

1 sudo reboot

 

 檢測OpenCV使用是否正常

  python程序

 1 import cv2
 2 import numpy as np
 3 cv2.namedWindow("gray")
 4 img = np.zeros((512,512),np.uint8)#生成一張空的灰度圖像
 5 cv2.line(img,(0,0),(511,511),255,5)#繪製一條白色直線
 6 cv2.imshow("gray",img)#显示圖像
 7 #循環等待,按q鍵退出
 8 while True:
 9     key=cv2.waitKey(1)
10     if key==ord("q"):
11         break
12 cv2.destoryWindow("gray")

  保存文件為 test.py ,並在終端運行程序

1 sudo python3 test.py

  運行結果如下:

  

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

心裏有紅黑樹

Why 紅黑樹

為什麼大家都這麼推崇紅黑樹呢? 這就是數據結構的魅力!!! 下面我簡述一下常用數據結構的優缺點

  • 數組

大家對數組很熟悉, 都知道對數組來說,它底層的存儲空間是連續的,因此如果我們根據index去獲取元素,速度是相當快, 但是對於數組來說有時候查詢也不見得就一定塊, 比如我們查詢數組中名字叫張三的人, 也不得不從開始遍歷這個數組

如果我們想往數組中插入一個元素, 也不見得一定就慢, 比如我們往數組中最後的位置插入就很快, 但是要是往開始的位置插入的話, 肯定會很慢, 需要將現有數組中所有的元素往後移動一位, 才能空出開始的位置,給新元素用

  • 鏈表

一說鏈式存儲, 大家也都知道, 這種數據結構僅僅是邏輯連續, 物理存儲不連續, 因此我們有可以通過玩指針或者引用很快的完成元素的刪除和添加

對鏈表的查詢來說, 一定是慢的, 無論查詢誰, 查哪個, 都得從第一個節點開始遍歷

  • AVL樹

AVL樹, 就是二叉平衡樹, 這種有序的樹形結果就將鏈式存儲添加刪除塊, 順序存儲的查找快兩大有點進行了一次中和, 在絕大部分情況下, AVL樹在增刪改查方面的性能都原超過數組和鏈表

  • 紅黑樹

紅黑樹是對AVL樹是又一次重大升級, AVL樹,對於樹的平衡要求太嚴格了, 每當添加,刪除節點時,都不得不進行調整

對於AVL樹個紅黑樹來說, 每次添加一個新的節點都是最多進行兩次旋轉(左旋右旋)就能重新使樹變的平衡,

但是當我們刪除一個恭弘=叶 恭弘子節點時, AVL樹重新調整成平衡狀態時最多需要進行旋轉O(logN)次, 而紅黑樹最多旋轉3次就能重新平衡,時間複雜度是O(1)

還有就是紅黑樹並不是完全意義上的AVL樹, 也就是說它其實並不是真的像AVL樹那樣嚴格要求對一個節點來說左右子樹的高度差不能超過1, 而是選擇使用染成紅色和黑色進行維護

簡單來說, 因為紅黑樹並不像AVL樹那樣完全平衡, 可能會導致紅黑樹的讀性能略遜於AVL, 但是紅黑樹的維護成本絕對是遠遠低於AVL, 在空間上的開銷和AVL樹基本持平, 因此紅黑樹被大家極力推崇, 和學習java的同學直接相關的就是jdk8的 hashmap

紅黑樹的特性

紅黑樹主要存在下面的7條性質

  1. 節點非紅即黑
  2. 根節點必定是黑色
  3. 恭弘=叶 恭弘子節點全部是黑色, (這裏說的恭弘=叶 恭弘子節點是我們想象在肉眼看到的節點上再多加一層子節點)
  4. 紅節點的子節點必定是黑色
  5. 紅節點的父節點必定是黑色
  6. 從根節點到任意子節點的路徑上,都要經歷相同數目的黑節點
  7. 從根節點到任意子節點的路徑上不可能存在兩個連續相同的紅節點

常見的誤區

如上圖, 看着挺像紅黑樹, 其實他不是, 看它node10, 並不滿足上面的性質6. 因為我們認為node10的左子節點是黑色的節點, 這樣的話, 從node20到node10的左子節點就經歷了兩個黑節點, 而其他的 node15, node25, node35 經歷的黑色子節點數都是三個

如上圖它也不是紅黑樹, 因為我們認為node30的右節點是黑色的節點, 這樣的話從node60到node30的右節點就經歷了三個黑色的節點, 而其他的所有子節點都經歷了4個, 故, 他不是紅黑樹

紅黑樹與2-3-4樹等價

如上圖中,當我們將一個紅黑樹中的黑色節點和紅色節點融合在一起時,我們會發現, 這個紅黑樹其實就是一顆2-3-4樹, 一顆四階B樹

並且, 紅黑樹中黑色節點的每一個合併完成后的節點中都有一個黑色的節點, 換句話說就是紅黑樹中黑色節點的個數等於2-3-4樹中節點的個數

添加

添加節點其實就是構造紅黑樹的過程, 只要我們嚴格遵循上面的7條限制, 構造出來的樹就是紅黑樹

通過上圖其實我們發現, 紅黑樹真的可以和四階B樹之間進行等價代換, 換句話說就是 4階B樹的性質對於紅黑樹來書其實也是存在的, 主要是如下兩條性質

  • 所有新添加進去的節點都被放在了恭弘=叶 恭弘子節點上
  • 2-3-4樹中每一個節點中允許承載的元素的個數 [1,3]

經驗推薦: 就是新添加的節點盡量全部是紅色, 如果你畫一畫就會發現, 如果我們新添加的節點是紅色的話,上面所說的7條性質中, 除了第四條(紅節點的子節點必定的黑節點). 其他的限制都可以滿足

於是看一下一顆四階B樹插入節點時有哪些種情況

數一數: 一共 4+3+3+2 = 12種情況, 換句話說, 只要我們處理好了這12種情況, 我們就完成了添加節點的邏輯

  • 情況1, 就是假設我們添加進去的是紅色的節點, 並且這個紅色節點的父節點是黑色節點時, 直接添加進行,不需要其他任何變換, 就想下圖這樣, 直接簡單粗暴的添加就行

除去第一種情況外, 還剩下8中情況出現了紅紅節點相鄰, 於是繼續往下看, 我們對他進行一次修復

  • 情況2: 如下圖

插入的node57, node64, 什麼情況呢? 就是當前節點是node5556, 首先這個節點中現存兩個元素, 並且是往這個黑色的節點的左側的左側插入, 或者是右側的右側插入一個紅色節點

看上圖出現了兩個紅色節點相鄰,於是我們第一件事就是進行重新染色,

  1. 將插入節點的父節點染成黑色
  2. 將插入節點的祖父節點染成紅色
  3. 將祖父節點進行旋轉, 如果這個新節點被插入在父節點的右側. 左旋轉它的祖父節點

經過上面的變換后, 我們重新得到標準的紅黑樹如下

  • 情況3: 新添加的節點的叔叔節點不是紅色

第三種情況和第二種情況相似, 還是插入 node57和node64. 判斷的條件是 插入節點的叔叔節點(父節點的兄弟節點)不是紅節點,

簡稱 LR , 或者是RL , 需要進行如下的調整

  1. 染色: 將自己染成黑色,祖節點染成紅色
  2. LR: 父節點左旋轉, 祖父節點右旋轉
  3. RL: 祖父點右旋轉, 父節點左旋轉

LR舉例:

經過上面的變化,我們重新得到平衡的紅黑樹

接着往下看剩下的四種情況

  • 情況4: 新添加的節點的叔叔節點是紅色, 其實就是需要上溢的情況, 也很好處理

像上圖這樣, 新添加的紅色節點 node15, 它本身的父節點是node20, 父節點的叔叔節點是紅色的node25, 我們比較node15和node20的大小, 發現node15本來是應該放在node20的左邊的, 但是對於一顆2-3-4樹來說, 單個節點最多就有3個元素, 如果再加上node15 就會出現上溢的情況, 怎麼辦呢? 我們上溢調整, 選擇這個節點中間位置的元素向上和父節點合併, 選擇node20, node30其實都是可以的, 為了方便我們選擇node30

好,下面開始修復這個紅黑樹

  1. 將插入的節點的父節點和它的叔叔節點染成黑色
  2. 發生了上溢, 將他的父節點的染成紅色, 遞歸插入到根節點上, 這時候根節點可能又會發生上溢

然後上溢

當我們將新插入的節點的父節點node30染成紅色時, 再插入到根節點, 實際上就是重複我們枚舉出來的這12種情況中的一種. 紅黑樹一定會被修復, 當然這時候很可能會出現根節點也容納不了新的元素, 需要根節點也進行上溢, 然後將根節點染黑

還有一種情況是像下面這樣, 同樣是在情況4下的新插入的節點的叔叔節點是紅色

像下面這樣調整:

  1. 將父節點和叔叔節點染成黑色
  2. 祖父節點上溢

然後就是這種情況

調整的思路和前面一樣

  1. 將父節點和叔叔節點染成黑色
  2. 將祖父節點上溢

至此紅黑樹的添加的12種情況就全部枚舉完成了

刪除

對於刪除來說總共兩大種四小種情況

  • 第一種就是刪除的節點就是紅色節點, 如果真是這樣的話,直接刪除就ok
  • 第二種是刪除的節點是黑色節點
    • 刪除擁有1個red節點的黑色節點
    • 刪除擁有2個red節點的黑色節點,
    • 刪除黑色節點

如果一個像下面這樣, 下面的黑色節點有兩個子節點, 這種情況下,黑色節點肯定不會直接被刪除的, 需要進行變換,讓他的恭弘=叶 恭弘子節點去替換他,進而實現刪除的目的

  • 情況1: 刪除擁有1個紅節點的黑色節點,像下圖這樣

怎麼判斷這就是我們想刪除的情況呢? 當我們確定用來替代這個被刪除的黑節點是紅色,則符合當前的情況

也就是說我們想刪除 node40 和 node70, 於是我們這樣做

  1. 讓這個指向被刪除的節點的指針指向這個被刪除的節點的子節點
  2. 將替代它的節點染成黑色

於是我們接得到下圖這樣的結果

  • 情況2: 刪除的節點是黑色的恭弘=叶 恭弘子節點, 並且可向兄弟節點借

首先,如果這個恭弘=叶 恭弘子節點就是根節點的話,直接刪除就ok

看下面的這個圖, 我們就刪除其中node90, 即,刪除黑色恭弘=叶 恭弘子節點

如果想刪除上圖中的node90也是由竅門的,規律和2-3-4樹是擦不多的

假設它就是2-3-4樹, 如果我們將node90刪了, 我們計算一下, 對於2-3-4樹來說, 每一個節點位置上至少有 ⌈ 4/2 ⌉ -1 = 1個元素, 但是把node90刪除了這個位置上的節點中沒有元素, 因此產生了 下溢

出現下溢,我們首先考慮的情況就是看看可不可以向它的兄弟節點借一個,但是和B樹是有取別的, 多了下面的限制

  1. 被刪除的這個節點的兄弟節點必須是黑色的
  2. 被刪除的這個節點的兄弟節點一定的有紅色的子節點才ok, 就像上圖那樣, 可以在左邊,右邊,或者都有
  3. 直接刪除掉指定的node(因為它在恭弘=叶 恭弘子節點的位置上)
  4. 進行旋轉,旋轉時注意, 兩點:第一點: 比如下面的原來根節點位置上的元素88是紅色的, 經過旋轉上來替換它的節點的顏色必須染成紅色, 如果node88是黑色, 那麼經過旋轉上來替換他的節點的顏色必須染成黑色 ,第二點: 旋轉完成后,新的跟節點的直接左右子節點的顏色轉換為黑色

怎麼進行旋轉呢? 就像下圖這樣

  • 情況3: 刪除的節點是黑色的恭弘=叶 恭弘子節點, 並且它的兄弟是黑色,而且它的兄弟節點不能借給他元素

像這種情況:我像刪除node99,但是沒辦法像他的兄弟節點借元素,於是

  1. 將父節點向下合併,父節點染成黑色
  2. 將它的兄弟節點染成紅色

也有特殊的情況, 就是它的父節點只有一個,還是黑色

這時候,我們將他的父節點下溢, 原位置的節點捨棄

  • 還有最後一種情況就是, 刪除的是黑色的節點, 它的兄弟節點的是紅色的節點

就像上圖那樣,我們想刪除node99, 但是node99的兄弟節點其實是node55, 而不是node77, 我們怎麼樣才能轉換為前面說的那些情況呢?

  1. 將被刪除節點的父節點染成紅色, 兄弟節點染黑

  2. 讓被刪除的父節點進行右旋轉(node88右轉)

    得到下圖

於是我們就將這種兄弟節點為紅節點的情況轉化成了兄弟節點為黑色節點的樣子, 按照原來的方式進行刪除修整即可

  1. 讓原父節點下溢
  2. 原染成黑色
  3. 兄弟節點,染成紅色

至此本文就結束, 歡迎關注我,後續我更新更多的關於開發相關的筆記

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

法國要在2040 年停售汽柴油車,能源部長:這會是一場革命

不同於美國退出巴黎協定的決定,法國總統馬克宏曾提到要「讓地球再次偉大」,如今看來,法國似乎正朝目標一步步邁進中。法國能源部長余洛(Nicolas Hulot)6 日宣布,將在2040 年開始全面停售汽柴油車。

電訊報報導,除了汽柴油車之外,法國同時也將禁止任何使用汽油、煤氣、煤炭及頁岩油的新計畫,余洛表示,汽油及汽車的銷售將在2040 年前結束,「法國打算在2050 年達到碳中和的目標。」

為了達成這個目標,法國將開始進行必要的投資,並提供相關獎勵補助措施,這個目標是非常困難的,特別是對於車商來說,但余洛相信汽車產業已經準備好進行轉變。

根據歐洲經濟區(EEA)的統計,在2016 年大型車商的汽車碳排放量上,法國車廠Peugeot、Citroen、Renault 是碳排放最低的前三名。

儘管如此,這樣的改變勢必會面臨許多挑戰,余洛表示,「這會是一場名副其實的革命。」

余洛也引述了Volvo 近期的決定,來說明停售汽柴油車的目標已是勢在必行。

就在幾天前,傳統車商Volvo 宣布將於2019 年起生產電動車,並停售純內燃機供電的汽車,執行長表示,Volvo 是考量過客戶需求,才做出這項決定。

法國並不是唯一將開始禁止汽柴油車的國家,德國和印度都打算在2030 年前達到這個目標,荷蘭和挪威更計畫在2025 年前達成。

根據統計,2017 上半年在法國的新車市場中,使用柴油和汽油的車輛仍佔有95.2%,混合動力車佔3.5%,純電動車僅佔了1.2%。

余洛強調,儘管法國在這方面,落後於瑞典、哥斯大黎加等國家,但會擁抱綠能的「精神」,期望在2040 年前能達成目標。

除了停售汽柴油車及停止汽油相關新項目外,法國還計畫在2022 年將火力發電廠停工,並在2025 年將核電的供電比例由現在的75% 降低至50%,同時將採取措施,限制棕櫚油在生物燃料中的使用,來間接減少砍伐森林。

不僅是中國和印度,在法國的一些城市,巴黎、里昂和格勒諾布爾(Grenoble),也都存在著霧霾的問題。

「解決問題的方法就在可見之處,國內的製造商有著實現這項承諾的手段,這關係到公共衛生。」

(合作媒體:。圖片出處:wikipedia CC0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

另類思考!電動車熱未必有害原油、說不定恰恰相反?

國際車廠爭相研發電動車,汽油車似乎被宣判死刑,原油也會跟著步上末日。不過有專家大膽推估,電動車發展會削減流入原油業的資金,油市將汰弱留強,油價會維持低檔,也許將阻礙電動車普及之路。

加拿大能源私募基金龍頭ARC Financial Corp.首席能源經濟學家Peter Tertzakian,13日在OilPrice發文稱,上週Volvo宣布,2019年起只生產電動車、停產汽柴油車。法國政府也宣布,2040年起停售汽柴油車。與此同時,特斯拉創辦人馬斯克貼出平價電動車Model 3照片,讓油市陷入低迷。

電動車發展迅速,不少人認為原油業末日倒數計時。但是Tertzakian不以為然,指出環保車買氣疲弱。2013~2014年中,油價處於每桶100美元的高點時,美國電動車銷售提高,可是之後油價崩盤,電動車動能隨之消散。能源有兩股相反力量,現在的消費趨勢是原油便宜、使用率高,相對的,電動車滲透率低迷。但是市場對未來的預期恰恰相反,斷言原油將亡。

未來幾年究竟會如何發展,Tertzakian推測有兩種可能結果,一是資本緊縮,汰除沒有效率的生產商,剩餘業者將不斷創新壓低成本,在低油價時也能存活,油價會繼續低迷,消費者缺乏誘因改買電動車。第二種可能是資本投資緊縮,將使原油供給下降,帶動油價上揚,電動車需求因此大增。諷刺的是,厲害的油商在兩種情況下,都能有好表現。可以確定的是,未來投入原油業的資金勢必減少。

原油期貨報價從去(2016)年12月開始一路往下盤跌,高盛全球原物料研究部主管Jeffrey Currie對這提出了一個簡單解釋:市場上的錢太多。

CNBC報導,Currie 12日在接受專訪時指出,市場上的原油其實並不是太多,只是錢潮淹腳目、委實過多。舉例來說,人們對石油探鑽活動的投資,是墨西哥最近能發現十數億桶原油的主因。

Currie說,石油市場正在試著尋找供需均衡點,而產油商的損益兩平點在跌破高盛2016年估計的50-55美元後,新的平衡點在哪,則變得愈來愈難預測。不過,在被問到油市有沒有可能崩盤時,Currie說雖然他希望看到市場能有些波動,但其實崩盤機率極低。

(本文內容由授權使用。圖片出處:public domain CC0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

特斯拉啟用臺南奇美博物館超級充電站,下一站臺中七期將啟用

特斯拉(Tesla) 今日(7/20) 啟用臺灣第二組超級充電站,為全亞洲第一組設在博物館園區的超級充電站。而第三組超級充電站則會在下週於臺中七期啟用。

此次啟用的台南超級充電站位於台南奇美博物館,是全亞洲第一組設立於博物館的超級充電設施,共有8 組超級充電設備,足以應付開車環島遊,以及跨縣市長途旅遊等的需要。這次的項目更獲得台南政府大力支持,鼓勵特斯拉對於環保理念的實踐。特斯拉在台的首座超級充電站設於台北花博園區,該充電站提供6 組超級充電設備。

下週特斯拉將啟用位於臺中七期的第三組超級充電站,鄰近國道一號臺中交流,方便南來北往的特斯拉車主休息同時,快速充電再上路。

特斯拉的超級充電站充電30 分鐘,就能供應行駛270 公里所需電力,為臺北臺南間七成路程。而設在百貨公司的目的地充電站,已經從臺灣頭的翡翠灣,到臺灣尾的墾丁,遍佈14 個縣市,超過80 個地點,250 支的目的地充電座。

(合作媒體:。圖片出處:特斯拉提供)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

日產傳退出EV電池生產業務、子公司AES賣中國GSR

朝日新聞22日報導,日產汽車(Nissan)將退出電動車(EV)用電池的生產業務,旗下車用電池生產子公司「Automotive Energy Supply(以下簡稱AES)」將出售給中國投資基金「GSR」,出售額預估為1,000億日圓,雙方預計會在今年夏天達成共識並對外發表。日產在退出EV電池生產業務後,會將資源集中在最先端電池的研發上。

報導指出,鋰離子電池是決定EV競爭力的關鍵,而日系廠商原先是該領域的霸主,不過近年來,南韓、中國廠商呈現顯著成長,加上AES銷售通路有限,因此日產研判擁有EV電池生產業務不具備太多好處。

AES為日產、NEC分別出資51%、49%於2007年設立的公司,主要生產日產電動車Leaf或油電混合車(HV)所需的鋰離子電池。

根據調查公司Techno Systems Research指出,2014年Panasonic車用鋰離子電池全球市佔率高達47%,而2015年雖維持首位、但市佔率萎縮至34%;反觀「其他廠商」市佔率從14%飆增至33%,而在「其他廠商」中、比亞迪(BYD)等中國廠商佔了大多數,LG化學、三星SDI等南韓廠商也在後猛追。

中國對電池市場虎視眈眈,成長最快的電池廠「寧德時代新能源科技股份」(簡稱寧德時代或CATL)已誓言要在2020年底前,使電池產量超越特斯拉(Tesla)、Panasonic合資的「Gigafactory」超大電池廠。

英國金融時報3月5日報導,北京已呼籲企業在2020年底前將車用電池產能拉高一倍,還鼓勵業者前往海外投資。高盛預估,鋰電池將是未來10年的關鍵技術,估計到了2025年市場總值上看400億美元、且主要會由中國主導。

寧德時代行銷主任Neil Yang預測,雖然超越日本、南韓業者並非易事,但預估未來10年內,全球只會剩下10家鋰電池製造商,其中60%的市場會由前三大業者拿下。他也透露寧德時代要將觸角探至全球的野心,聲稱該公司希望跟特斯拉合作,也一直在跟通用汽車(GM)接洽,而福斯(Volkswagen)、BMW則已都是他們的客戶。

寧德時代預計要在2020年將鋰電池總產能拉升至50GWh,而中國整體的鋰電池產能則合計會達121GWh。相較之下,特斯拉則希望在明(2018)年將鋰電池產能拉升至35GWh。每1個GWh的電力,可供應40,000輛電動車、每部行駛100公里所需。中國已在2013年超越南韓成為全世界最大的鋰電池供應國。

(本文內容由MoneyDJ授權使用。圖片出處:public domain CC0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

Gogoro 太陽能電池交換站,在新北八里驅動示範

新創科技公司 Gogoro 睿能創意股份有限公司,28 日宣布其與新北市政府合作的首座太陽能電池交換站,正式在新北市八里區開始營運。隨著這個搭配太陽能面板的電池交換站的啟動,Gogoro 對永續能源的承諾邁出更關鍵的一步。   這座位於八里十三行博物館附近(新北市八里區文昌路與文昌一街交叉口)的 Gogoro 八里公兒四電池交換站配置 2.3kW 太陽能面板,依據天氣環境等因素,每天可以產生大約 6.21 kWH 的電力,是第一座以再生能源提供電力的 GoStation 電池交換站。太陽能電力不但可以提供電池交換站的 Gogoro 電池使用,降低發電時所產生的二氧化碳排放,更可以與全台電力網路連結,參與整體網路的電量調節。   Gogoro 執行長陸學森表示 :「Gogoro 致力發展潔淨的智慧能源,希望透過具備能源調度能力的智慧電網,成為城市的電力調節樞紐,以促成電力平衡。與新北市政府合作的太陽能八里電池交換示範站為我們上述的目標邁出了重要的一步。」   新北市政府則表示,市府一直在積極尋找降低溫室氣體排放、改善空氣污染的積極方法,與 Gogoro 合作成立全世界第一座太陽能電池交換站具有標竿式的意義。電動機車零排放的特性不但可以提升市區的空氣品質,以再生能源為來源的電力,更可以降低交通工具所帶來的碳排放。未來也將持續努力發展以再生能源補充電力的相關設施,做為新北市重要的基礎設施。   這座太陽能電池交換示範站,設有物聯網智慧平台,透過分析供電情況的螢幕,說明了包括減少碳排量,減少樹木砍伐面積,綠能總儲電量,城市電網 ,太陽能發電量等訊息,讓每名換電的民眾,清楚的知道,自己對環境的貢獻度,也具有相當程度的教育意義。   Gogoro 目前擁有 25,000 名車主,總共累計將近 500 萬次的電池交換,9,000 萬公里的總里程數,已經替地球減少 720 萬公斤的二氧化碳排放,隨著未來再生能源比例逐漸提升,Gogoro 的車主們將更對地球與環境產生更多的正面影響力。Gogoro 為鼓勵車主響應綠能電池交換站,也設計了特別的機制。凡是造訪八里公兒四站,並完成電池交換的車主,即可在 Gogoro App 上獲得「阿波羅的力量」徽章。   (合作媒體:。圖片出處:科技新報)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

.NET資源泄露與處理方案

.NET雖然擁有強大易用的垃圾回收機制,但並不是因為這樣,你就可以對資源管理放任不管,其實在稍不注意的時候,可能就造成了資源泄露,甚至因此導致系統崩潰,到那時再來排查問題就已經是困難重重。

==========    ==========

一、知識點簡單介紹

常見的資源泄露有:

  • 內存泄漏:非託管資源沒有釋放、非靜態對象註冊了靜態實例。
  • GDI泄露:字體。
  • 句柄泄露:Socket或線程。
  • 用戶對象泄露:移除的對象未釋放。

二、具體實例

1. 內存泄漏

很常見的現象是分不清哪些對象需要釋放,對於控件、Stream等一些非託管資源也只管新增,卻沒有釋放,功能是實現了,卻埋了顆不小的雷。

private void button1_Click(object sender, EventArgs e)
{
    for(int i=0;i<1000;i++)
        this.Controls.Add(new TabPage());
}
private void button1_Click(object sender, EventArgs e)
{
    new Form2.ShowDialog();
}

如果你覺得寫這樣的代碼很Cool,很簡潔,你在項目中也有這麼寫代碼,那你就碰到大麻煩了,你試試在上面Form2中開個大一點的數組來檢查內存,然後運行,按幾下按鈕,你就會發現,內存一直增加,即使你調用了GC也無濟於事。所以,對於此類非託管資源要記住釋放,用完即廢可以採用using關鍵字。

public Form2()
{
    InitializeComponent();
    MyApp.FormChanged += FormChanged;
}

上面這個例子中,MyApp是一個靜態類,如果在實例對象中向這種類裏面註冊了事件,而又沒有取消註冊,這樣也會遇到大麻煩,即使在外部已經記得調用了Form2的Dispose也是沒用的。

解決方案

  • 注意託管資源和非託管資源的釋放區別,非託管資源是需要手動釋放的。
  • ,如上面的ShowDialog問題。(using中還起到了try-catch的作用,避免由於異常未調用Dispose的情況)
  • 使用UnLoad事件或者析構函數,對註冊的全局事件進行取消註冊。
  • 特別注意自定義組件的穩定性更重要,發生問題時影響也更廣。

2. GDI泄露

一般會跟字體相關,例如我曾在Android上用Cocos2d做一個小遊戲時頻繁地切換字體、Dev控件的Font屬性賦值也會有這種現象。

XXX.Font = new Font(...)

解決方案

  • 這個問題我目前是採用字體池來解決,類似線程池的概念,相同Key值取同一個對象。若有更好方案歡迎留言討論

3. 句柄泄露

一般跟Socket和Thread(線程)有關

for(int i=0;i<1000;i++){
    new Thread(()=>{
        Thread.Sleep(1000);
    }).Start();
}

解決方案

  • Socket的場景暫時沒遇到。
  • 線程問題採用線程池相關的輔助類能有效解決,例如ThreadPool、Task、Parallel。

4. 用戶對象泄露

一般跟移除的對象未釋放有關

private void button1_Click(object sender, EventArgs e)
{
    tab.Remove(tabPage);
}

三、最後特別奉送一個內存釋放的大招

[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]
public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);
/// <summary>    
/// 釋放內存    
/// </summary>    
public static void ClearMemory()
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
    if (Environment.OSVersion.Platform == PlatformID.Win32NT)
    {
        SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
    }
}

調用以上API能讓你的內存一下爆減,是不是很給力,一調用內存就降下來了。But,先別高興太早,這其實是偽釋放,只是暫時解決內存大量泄漏導致系統崩潰的應急處理方案。具體原因參考:,關鍵信息:物理內存轉虛擬內存,涉及磁盤讀寫。好處壞處都貼出來了,是否需要使用請君自己斟酌。

四、總結

實際上由於各個開發人員的水平跟接觸面不同,又沒有經過統一的培訓(各個人對資源釋放的理解與關注度不同,或者寫代碼時就沒考慮內存未被釋放這種問題),發現問題的時候項目往往已經做到了一個階段,系統也比較龐大了,這種時候才發現內存泄露的問題確實是很頭疼的。

  • 資源泄露的場景往往是相互關聯的,發生最多的就是內存泄漏,而除了寫法可能有問題外,也可能是因為句柄泄露或用戶對象泄露引起的。

五、參考資料

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

AutoCad 二次開發 文字鏡像

AutoCad 二次開發 文字鏡像

參考: 在autocad中如果使用Mirror命令把塊參照給鏡像了(最終得到一個對稱的塊),塊裏面的文字包括DBText和MText以及標註上面的文字都會被對稱,變得不易閱讀。而在單個字體實體和標註實體鏡像的時候只要設置系統變量mirrtext為0鏡像后的文字就不會與原文字對稱變成我們未學習過的文字了。   所以我們在鏡像塊的時候就可以先把塊炸開是用快捷鍵X,或者輸入explode,然後在使用鏡像命令。之後在把對稱后的實體集合組成一個新的塊。不過這樣操作十分的繁瑣,我覺得其中這樣做的優勢是mirror時的jig操作可以很方便的預先知道我們想要的對稱后的結果。但如果用代碼實現這種jig操作,我覺得有點複雜,目前我還不知道怎麼實現。   我要講的主要就是用代碼來實現塊的鏡像。難點就在與文字的鏡像,和標註的鏡像。這篇文章先講文字的鏡像。文字鏡像的主要步驟分為: 1.找到鏡像前文字邊界的四個角,這四個角構成了一個矩形,我們要求得這個矩形的長和寬所代表的向量。 2.判斷文字鏡像后的方向,如果是偏向朝Y軸鏡像,那麼文字鏡像后的方向是沿着X軸翻轉的,如果是偏向朝X軸鏡像,那麼文字鏡像后的方向是沿着X軸翻轉的。這裏我以沿着Y軸鏡像為例子。 3.移動鏡像后切被翻轉后的文字,這裏也是根據鏡像軸的不同,需按不同的向量來移動。   詳細情況見圖: 圖中左邊是要鏡像的文字,文字上的藍色線,和黃色線是我調試的時候加入的,黃線左端是 pt1,右端是pt2,藍線左端是pt3,右端是pt4。 中間的豎線是Y軸鏡像線,右邊就是不同情況下鏡像后的文字。其中黃色部分表示正確的鏡像結果,紅色部分表示:鏡像后延第一個步驟移動后求得的向量移動了文字的position但是沒翻轉的結果。黑色部分表示:鏡像后翻轉了文字但文字的position沒有按向量移動的結果。 下面我就來仔細分析一下代碼: 要實現第一步驟,前提是要有一段P/Invoke的代碼: 其中 引入的acdb22.dll是 autocad2018中的版本,不同版本,這個dll後面的数字不一樣。我們可以到cad安裝目錄下查找acdb幾個字,找到後面帶数字的就是了,64位的安裝目錄默認位置:C:\Program Files\Autodesk\AutoCAD 2018。這兩個函數一個是32位,一個是64位,具體用哪個後面的代碼會自動判斷。這個函數作用我覺得主要是求 這個name。   這裏用到了accore.dll,有的cad版本沒有這個dll,就用acad.exe代替就可以了。上面的acdbEntGet主要是根據entity的名字求的entity實體的Intptr,下面的函數時求的文字邊界對角點,這裏注意,我把這個兩個點用直線打印在cad空間里,發現它時在原點,沒旋轉的線,但其實文字不的position不在原點,也帶有旋轉角度。後面要求的文字邊界向量就是根據這兩個點來的。 上面求得的pt1,pt2 經過:
pt1 = pt1.TransformBy(rotMat).Add(dbText.Position.GetAsVector());
pt2 = pt2.TransformBy(rotMat).Add(dbText.Position.GetAsVector()); 這種操作就得到了第一幅圖中的黃線。 在經過這樣的操作,得到的pt3 和pt4就是第一幅圖的藍線。這其中的rotDir和linDir就是我們要求得的寬和長代表的向量了,然後在把它給鏡像了得到的mirRotDir和mirLinDir就是鏡像后的文字要移動的向量了,這裏第一步就結束了。 第二步,第三步:   大的話,就說明文字需要朝X軸翻轉,所以這裏的IsMirroredInX=true就代表需要朝X軸翻轉。 緊接着下面句,如果沒加mirLineDir這個向量,就會出現第一幅圖中的畫黑線的情況,如果不加IsMirrorInX就會出現畫紅線的情況。 到這裏就全部結束了。 下面給出所有代碼:

public class MyMirror
    {
        Document Doc = Application.DocumentManager.MdiActiveDocument;
        Editor Ed = Application.DocumentManager.MdiActiveDocument.Editor;
        Database Db = Application.DocumentManager.MdiActiveDocument.Database;

        List<Entity> list = new List<Entity>();
        List<ObjectId> listOId = new List<ObjectId>();

        [CommandMethod("testM")]

        public void MirrorTextCmd()

        {

            Document doc = Application.DocumentManager.MdiActiveDocument;

            Database db = doc.Database;

            Editor ed = doc.Editor;



            //Entity selection

            PromptEntityOptions peo = new PromptEntityOptions(

                "\nSelect a text entity:");



            peo.SetRejectMessage("\nMust be text entity...");

            peo.AddAllowedClass(typeof(DBText), true);



            PromptEntityResult perText = ed.GetEntity(peo);



            if (perText.Status != PromptStatus.OK)

                return;



            peo = new PromptEntityOptions("\nSelect a mirror line:");

            peo.SetRejectMessage("\nMust be a line entity...");

            peo.AddAllowedClass(typeof(Line), true);



            PromptEntityResult perLine = ed.GetEntity(peo);



            if (perLine.Status != PromptStatus.OK)

                return;



            using (Transaction tr = db.TransactionManager.StartTransaction())

            {

                Line line = tr.GetObject(perLine.ObjectId, OpenMode.ForRead)

                    as Line;



                Line3d mirrorLine = new Line3d(

                    line.StartPoint,

                    line.EndPoint);



                MirrorText(perText.ObjectId, mirrorLine);



                tr.Commit();

            }

        }



        void MirrorText(ObjectId oId, Line3d mirrorLine)

        {

            Database db = oId.Database;



            using (Transaction tr = db.TransactionManager.StartTransaction())

            {

                // Get text entity

                DBText dbText = tr.GetObject(oId, OpenMode.ForRead)

                    as DBText;



                // Clone original entity

                DBText mirroredTxt = dbText.Clone() as DBText;



                // Create a mirror matrix

                Matrix3d mirrorMatrix = Matrix3d.Mirroring(mirrorLine);



                // Do a geometric mirror on the cloned text

                mirroredTxt.TransformBy(mirrorMatrix);



                // Get text bounding box

                Point3d pt1, pt2, pt3, pt4;

                GetTextBoxCorners(

                    dbText,

                    out pt1,

                    out pt2,

                    out pt3,

                    out pt4);



                // Get the perpendicular direction to the original text

                Vector3d rotDir =

                    pt4.Subtract(pt1.GetAsVector()).GetAsVector();



                // Get the colinear direction to the original text

                Vector3d linDir =

                    pt3.Subtract(pt1.GetAsVector()).GetAsVector();



                // Compute mirrored directions

                Vector3d mirRotDir = rotDir.TransformBy(mirrorMatrix);

                Vector3d mirLinDir = linDir.TransformBy(mirrorMatrix);



                //Check if we need to mirror in Y or in X

                if (Math.Abs(mirrorLine.Direction.Y) >

                    Math.Abs(mirrorLine.Direction.X))

                {

                    // Handle the case where text is mirrored twice

                    // instead of doing "oMirroredTxt.IsMirroredInX = true"

                    mirroredTxt.IsMirroredInX = !mirroredTxt.IsMirroredInX;

                    mirroredTxt.Position = mirroredTxt.Position + mirLinDir;

                }

                else

                {

                    mirroredTxt.IsMirroredInY = !mirroredTxt.IsMirroredInY;

                    mirroredTxt.Position = mirroredTxt.Position + mirRotDir;

                }



                // Add mirrored text to database

                //btr.AppendEntity(mirroredTxt);

                //tr.AddNewlyCreatedDBObject(mirroredTxt, true);

                //list.Add(mirroredTxt);
                mirroredTxt.ToSpace();
                tr.Commit();

            }

        }
        #region p/Invoke


        public struct ads_name
        {

            public IntPtr a;

            public IntPtr b;

        };



        // Exported function names valid only for R19



        [DllImport("acdb22.dll",

            CallingConvention = CallingConvention.Cdecl,

            EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]

        public static extern int acdbGetAdsName32(

            ref ads_name name,

            ObjectId objId);



        [DllImport("acdb22.dll",

            CallingConvention = CallingConvention.Cdecl,

            EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]

        public static extern int acdbGetAdsName64(

            ref ads_name name,

            ObjectId objId);



        public static int acdbGetAdsName(ref ads_name name, ObjectId objId)

        {

            if (Marshal.SizeOf(IntPtr.Zero) > 4)

                return acdbGetAdsName64(ref name, objId);



            return acdbGetAdsName32(ref name, objId);

        }



        [DllImport("accore.dll",

            CharSet = CharSet.Unicode,

            CallingConvention = CallingConvention.Cdecl,

            EntryPoint = "acdbEntGet")]

        public static extern System.IntPtr acdbEntGet(

            ref ads_name ename);



        [DllImport("accore.dll",

            CharSet = CharSet.Unicode,

            CallingConvention = CallingConvention.Cdecl,

            EntryPoint = "acedTextBox")]

        public static extern System.IntPtr acedTextBox(

            IntPtr rb,

            double[] point1,

            double[] point2);



        void GetTextBoxCorners(DBText dbText, out Point3d pt1, out Point3d pt2, out Point3d pt3, out Point3d pt4)

        {

            ads_name name = new ads_name();



            int result = acdbGetAdsName(

                ref name,

                dbText.ObjectId);



            ResultBuffer rb = new ResultBuffer();



            Interop.AttachUnmanagedObject(

                rb,

                acdbEntGet(ref name), true);



            double[] point1 = new double[3];

            double[] point2 = new double[3];



            // Call imported arx function

            acedTextBox(rb.UnmanagedObject, point1, point2);



            pt1 = new Point3d(point1);

            pt2 = new Point3d(point2);

            var ptX = pt1 + Vector3d.XAxis * 40;
            var ptY = pt2 + Vector3d.YAxis * 50;


            var lX = new Line(pt1, ptX);
            var lY = new Line(pt2, ptY);

            lX.Color= Color.FromColor(System.Drawing.Color.Green);
            lY.Color= Color.FromColor(System.Drawing.Color.Orange);


            Line line = new Line(pt1, pt2);

            line.Color = Color.FromColor(System.Drawing.Color.Red);

            line.ToSpace();
            lX.ToSpace();
            lY.ToSpace();

            // Create rotation matrix

            Matrix3d rotMat = Matrix3d.Rotation(

                dbText.Rotation,

                dbText.Normal,

                pt1);



            // The returned points from acedTextBox need

            // to be transformed as follow

            pt1 = pt1.TransformBy(rotMat).Add(dbText.Position.GetAsVector());

            pt2 = pt2.TransformBy(rotMat).Add(dbText.Position.GetAsVector());

            Line linetrans = new Line(pt1, pt2);

            linetrans.Color = Color.FromColor(System.Drawing.Color.Yellow) ;

            linetrans.ToSpace();


            Vector3d rotDir = new Vector3d(

                -Math.Sin(dbText.Rotation),

                Math.Cos(dbText.Rotation), 0);


            //求垂直於rotDir和normal的法向量
            Vector3d linDir = rotDir.CrossProduct(dbText.Normal);



            double actualWidth =

                Math.Abs((pt2.GetAsVector() - pt1.GetAsVector())

                    .DotProduct(linDir));



            pt3 = pt1.Add(linDir * actualWidth);

            pt4 = pt2.Subtract(linDir * actualWidth);

            Line linetrans2 = new Line(pt3, pt4);

            linetrans2.Color = Color.FromColor(System.Drawing.Color.Blue);

            linetrans2.ToSpace();
        }

        #endregion
    }

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

023.掌握Pod-Pod擴容和縮容

一 Pod的擴容和縮容

Kubernetes對Pod的擴縮容操作提供了手動和自動兩種模式,手動模式通過執行kubectl scale命令或通過RESTful API對一個Deployment/RC進行Pod副本數量的設置。自動模式則需要用戶根據某個性能指標或者自定義業務指標,並指定Pod副本數量的範圍,系統將自動在這個範圍內根據性能指標的變化進行調整。

1.1 手動縮容和擴容

  1 [root@uk8s-m-01 study]# vi nginx-deployment.yaml
  2 apiVersion: apps/v1beta1
  3 kind: Deployment
  4 metadata:
  5   name: nginx-deployment
  6 spec:
  7   replicas: 3
  8   template:
  9     metadata:
 10       labels:
 11         app: nginx
 12     spec:
 13       containers:
 14       - name: nginx
 15         image: nginx:1.7.9
 16         ports:
 17         - containerPort: 80
  1 [root@uk8s-m-01 study]# kubectl create -f nginx-deployment.yaml
  2 [root@uk8s-m-01 study]# kubectl scale deployment nginx-deployment --replicas=5	#擴容至5個
  3 [root@uk8s-m-01 study]# kubectl get pods	                                	#查看擴容后的Pod

  1 [root@uk8s-m-01 study]# kubectl scale deployment nginx-deployment --replicas=2	#縮容至2個
  2 [root@uk8s-m-01 study]# kubectl get pods

1.2 自動擴容機制

Kubernetes使用Horizontal Pod Autoscaler(HPA)的控制器實現基於CPU使用率進行自動Pod擴縮容的功能。HPA控制器基於Master的kube-controller-manager服務啟動參數–horizontal-pod-autoscaler-sync-period定義的探測周期(默認值為15s),周期性地監測目標Pod的資源性能指標,並與HPA資源對象中的擴縮容條件進行對比,在滿足條件時對Pod副本數量進行調整。

  • HPA原理

Kubernetes中的某個Metrics Server(Heapster或自定義MetricsServer)持續採集所有Pod副本的指標數據。HPA控制器通過Metrics Server的API(Heapster的API或聚合API)獲取這些數據,基於用戶定義的擴縮容規則進行計算,得到目標Pod副本數量。
當目標Pod副本數量與當前副本數量不同時,HPA控制器就向Pod的副本控制器(Deployment、RC或ReplicaSet)發起scale操作,調整Pod的副本數量,完成擴縮容操作。

  • HPA指標類型

Master的kube-controller-manager服務持續監測目標Pod的某種性能指標,以計算是否需要調整副本數量。目前Kubernetes支持的指標類型如下:
Pod資源使用率:Pod級別的性能指標,通常是一個比率值,例如CPU使用率。
Pod自定義指標:Pod級別的性能指標,通常是一個數值,例如接收的請求數量。
Object自定義指標或外部自定義指標:通常是一個數值,需要容器應用以某種方式提供,例如通過HTTP URL“/metrics”提供,或者使用外部服務提供的指標採集URL。
Metrics Server將採集到的Pod性能指標數據通過聚合API(Aggregated API) 如metrics.k8s.io、 custom.metrics.k8s.io和external.metrics.k8s.io提供給HPA控制器進行查詢。

  • 擴縮容算法

Autoscaler控制器從聚合API獲取到Pod性能指標數據之後,基於下面的算法計算出目標Pod副本數量,與當前運行的Pod副本數量進行對比,決定是否需要進行擴縮容操作:
desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]

即當前副本數 x(當前指標值/期望的指標值),將結果向上取整。
釋義:以CPU請求數量為例,如果用戶設置的期望指標值為100m,當前實際使用的指標值為200m,則計算得到期望的Pod副本數量應為兩個(200/100=2)。如果設置的期望指標值為50m,計算結果為0.5,則向上取整值為1, 得到目標Pod副本數量應為1個。
注意:當計算結果與1非常接近時,可以設置一個容忍度讓系統不做擴縮容操作。容忍度通過kube-controller-manager服務的啟動參數–horizontalpod-autoscaler-tolerance進行設置,默認值為0.1(即10%),表示基於上述算法得到的結果在[-10%-+10%]區間內,即[0.9-1.1],控制器都不會進行擴縮容操作
也可以將期望指標值(desiredMetricValue)設置為指標的平均值類型,例如targetAverageValue或targetAverageUtilization,此時當前指標值(currentMetricValue) 的算法為所有Pod副本當前指標值的總和除以Pod副本數量得到的平均值。
此外,存在幾種Pod異常的如下情況:

  • Pod正在被刪除(設置了刪除時間戳):將不會計入目標Pod副本數量。
  • Pod的當前指標值無法獲得:本次探測不會將這個Pod納入目標Pod副本數量,後續的探測會被重新納入計算範圍。
  • 如果指標類型是CPU使用率,則對於正在啟動但是還未達到Ready狀態的Pod,也暫時不會納入目標副本數量範圍。

提示:可以通過kubecontroller-manager服務的啟動參數–horizontal-pod-autoscaler-initialreadiness-delay設置首次探測Pod是否Ready的延時時間,默認值為30s。

另一個啟動參數–horizontal-pod-autoscaler-cpuinitialization-period設置首次採集Pod的CPU使用率的延時時間。
當存在缺失指標的Pod時,系統將更保守地重新計算平均值。系統會假設這些Pod在需要縮容(Scale Down) 時消耗了期望指標值的100%,在需要擴容(Scale Up)時消耗了期望指標值的0%,這樣可以抑制潛在的擴縮容操作。
此外,如果存在未達到Ready狀態的Pod,並且系統原本會在不考慮缺失指標或NotReady的Pod情況下進行擴展,則系統仍然會保守地假設這些Pod消耗期望指標值的0%,從而進一步抑制擴容操作。如果在HorizontalPodAutoscaler中設置了多個指標,系統就會對每個指標都執行上面的算法,在全部結果中以期望副本數的最大值為最終結果。如果這些指標中的任意一個都無法轉換為期望的副本數(例如無法獲取指標的值),系統就會跳過擴縮容操作。
最後, 在HPA控制器執行擴縮容操作之前,系統會記錄擴縮容建議信息(Scale Recommendation)。控制器會在操作時間窗口(時間範圍可以配置)中考慮所有的建議信息,並從中選擇得分最高的建議。這個值可通過kube-controller-manager服務的啟動參數–horizontal-podautoscaler-downscale-stabilization-window進行配置,默認值為5min。這個配置可以讓系統更為平滑地進行縮容操作,從而消除短時間內指標值快速波動產生的影響。

1.3 HorizontalPodAutoscaler

Kubernetes將HorizontalPodAutoscaler資源對象提供給用戶來定義擴縮容的規則。
HorizontalPodAutoscaler資源對象處於Kubernetes的API組“autoscaling”中, 目前包括v1和v2兩個版本。 其中autoscaling/v1僅支持基於CPU使用率的自動擴縮容, autoscaling/v2則用於支持基於任意指標的自動擴縮容配置, 包括基於資源使用率、 Pod指標、 其他指標等類型的指標數據。
示例1:基於autoscaling/v1版本的HorizontalPodAutoscaler配置,僅可以設置CPU使用率。

  1 [root@uk8s-m-01 study]# vi php-apache-autoscaling-v1.yaml
  2 apiVersion: autoscaling/v1
  3 kind: HorizontalPodAutoscaler
  4 metadata:
  5   name: php-apache
  6 spec:
  7   scaleTargetRef:
  8     apiVersion: apps/v1
  9     kind: Deployment
 10     name: php-apache
 11   minReplicas: 1
 12   maxReplicas: 10
 13   targetCPUUtilizationPercentage: 50


釋義:
scaleTargetRef:目標作用對象,可以是Deployment、ReplicationController或ReplicaSet。
targetCPUUtilizationPercentage:期望每個Pod的CPU使用率都為50%,該使用率基於Pod設置的CPU Request值進行計算,例如該值為200m,那麼系統將維持Pod的實際CPU使用值為100m。
minReplicas和maxReplicas:Pod副本數量的最小值和最大值,系統將在這個範圍內進行自動擴縮容操作, 並維持每個Pod的CPU使用率為50%。
為了使用autoscaling/v1版本的HorizontalPodAutoscaler,需要預先安裝Heapster組件或Metrics Server,用於採集Pod的CPU使用率。
示例2:基於autoscaling/v2beta2的HorizontalPodAutoscaler配置。

  1 [root@uk8s-m-01 study]# vi php-apache-autoscaling-v2.yaml
  2 apiVersion: autoscaling/v2beta2
  3 kind: HorizontalPodAutoscaler
  4 metadata:
  5   name: php-apache
  6 spec:
  7   scaleTargetRef:
  8     apiVersion: apps/v1
  9     kind: Deployment
 10     name: php-apache
 11   minReplicas: 1
 12   maxReplicas: 10
 13   metrics:
 14   - type: Resource
 15     resource:
 16       name: cpu
 17       target:
 18         type: Utilization
 19         averageUtilization: 50


釋義:
scaleTargetRef:目標作用對象,可以是Deployment、ReplicationController或ReplicaSet。
minReplicas和maxReplicas:Pod副本數量的最小值和最大值,系統將在這個範圍內進行自動擴縮容操作, 並維持每個Pod的CPU使用率為50%。
metrics:目標指標值。在metrics中通過參數type定義指標的類型;通過參數target定義相應的指標目標值,系統將在指標數據達到目標值時(考慮容忍度的區間)觸發擴縮容操作。

  • metrics中的type(指標類型)設置為以下幾種:
    • Resource:基於資源的指標值,可以設置的資源為CPU和內存。
    • Pods:基於Pod的指標,系統將對全部Pod副本的指標值進行平均值計算。
    • Object:基於某種資源對象(如Ingress)的指標或應用系統的任意自定義指標。

Resource類型的指標可以設置CPU和內存。對於CPU使用率,在target參數中設置averageUtilization定義目標平均CPU使用率。對於內存資源,在target參數中設置AverageValue定義目標平均內存使用值。指標數據可以通過API“metrics.k8s.io”進行查詢,要求預先啟動Metrics Server服務。
Pods類型和Object類型都屬於自定義指標類型,指標的數據通常需要搭建自定義Metrics Server和監控工具進行採集和處理。指標數據可以通過API“custom.metrics.k8s.io”進行查詢,要求預先啟動自定義Metrics Server服務。
類型為Pods的指標數據來源於Pod對象本身, 其target指標類型只能使用AverageValue,示例:

  1  metrics:
  2   - type: Pods
  3     pods:
  4       metrics:
  5         name: packets-per-second
  6       target:
  7         type: AverageValue
  8         averageValue: 1k

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!