机器人应用

智能机器人(53):定位调试

Q:
性能的平衡
A:
各sensor发布topic, amcl和robot_pose_ekf模块发布tf, 这些frequency需要和cpu性能进行trade-off, 搞折衷做平衡。

top查看系统性能,’1′ 查看多核的具体cpu, 节后’b’ ‘x’ ‘y’等指令, 并要关注average load指标:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14706 ubuntu 20 0 296736 212296 5564 R 71.5 11.0 1:51.56 amcl
14245 ubuntu 20 0 79408 5592 4792 S 47.0 0.3 2:30.72 laser_node
14250 ubuntu 20 0 105876 5348 4616 S 3.0 0.3 0:09.73 lpms_imu_node
23344 ubuntu 20 0 91032 6960 6140 S 4.0 0.4 0:00.77 robot_pose_ekf
这个就好了。

如果配置不切实际, 类似arm板配置20Hz的transform frequency, 则资源受限出错:
$ roswtf
— —
ERROR: receiving transform from [/amcl] that differed from ROS time by 2.96s
这个时间,设置的越快会,大的越夸张。

此外还要关注内存情况:
$ free -m
— —

也要关注磁盘介质:
$ df -h

$ du -h –max-depth=1

Q:
amcl的node会die掉

$ rosnode ping amcl
— —
ERROR: connection refused to [http://192.168.0.40:38282/]

查看 ~/.ros/log/latest/… …/amcl-1.log:
amcl: /tmp/buildd/ros-indigo-amcl-1.12.4-0trusty-20150604-0435/src/amcl/pf/pf_kdtree.c:378: pf_kdtree_cluster: Assertion `node == pf_kdtree_find_node(self, self->root, node->key)’ failed.
Aborted (core dumped)

A:
原因是激光雷达被不恰当遮挡, pf程序没有足够健壮导致的。

Q:
ERROR: receiving transform from [/robot_state_publisher] that differed from ROS time by 12.34s
A:
如果是多机系统:
可能是没有进行时间同步。
$ install chrony
$ sudo ntpdate 192.168.1.1 <--- 如果是单机系统系统, 而且时间相差很大: 可能是/use_sime_time要为false。 如果是单机系统系统, 时间相差细微: 第一感就是降低某些重载模块的频率, 50Hz ---> 20Hz—>5Hz。
或者换个PC。

Q:
WARNING The following node subscriptions are unconnected:
* /amcl:
* /tf_static
* /robot_pose_ekf:
* /tf_static
A:
roswtf发出的警告,说amcl节点订阅了tf_static这个topic,但是却没有其他节点发布内容的topic。
这个警告正是所期望看到的:
因为我们没有使用tf_static来发布模型urdf,所以可以忽略这些警告。

智能机器人(51):建图和定位

3. 建图功能 – gmapping

$ sudo apt-get install ros-indigo-gmapping
$ rosrun gmapping slam_gmapping scan:=scan

gmapping实现基于激光的SLAM, in fact usinf OpenSlam的Gmapping。
make a 名为slam_gmapping的node -> 创建2D的occupancy grid map。

Subs:
* scan (sensor_msgs/LaserScan)

Pubs:
* map (nav_msgs/OccupancyGrid)
Get the map data from this topic, which is latched, and updated periodically
Services:
* dynamic_map (nav_msgs/GetMap)
Call this service to get the map data

TF required:
* odom -> base_link
usually provided by the odometry system, e.g., the driver for the mobile base
* base_link -> laser_link (base_laser)
usually broadcast periodically by robot_state_publisher, or from a tf static_transform_publisher.

TF provided:
* map -> odom
the current estimate of the robot’s pose in the map frame
既然是建图,肯定给出了odom在map中的位置,也就是此处的map->odom的tf变换。

4. 地图服务器 – map_server

$ sudo apt-get install ros-indigo-map-server

map_server包提供一个服务map_server和一个应用map_saver:
* map_server , a ROS Node, which offers map data as a ROS Service.
* map_saver , a command-line utility, which allows dynamically generated maps to be saved to file.
前者map_server提供地图服务,例如导航时。
后者map_saver用于保存地图,例如建图时。

4.1 在导航或者定位场景,加载地图,可以在c或python的node。
$ roslaunch funbot r_mapserver.launch
$ vi r_mapserver.launch
$ rosrun map_server map_server /home/funbot/map/map2017.yaml

Pubs:
* map (nav_msgs/OccupancyGrid)
you can receive the map via this latched topic.

Services:
* static_map (nav_msgs/GetMap)
Retrieve the map via this service.

4.2 在mapping场景,可以随时保存地图。
这个通过command-line或者在code里面system()。
$ rosrun map_server map_saver -f /home/funstep/map/map2017 y
$ rosrun map_server map_saver -f _map_file:=/home/funstep/map/map.yaml x

Subs:
* map (nav_msgs/OccupancyGrid)
Map will be retrieved via this latched topic.

5. 定位功能 – amcl

$ sudo apt-get install ros-indigo-amcl
rosrun amcl amcl scan:=scan

amcl是2D的基于概率的定位的一个包。

Subs:
* map (nav_msgs/OccupancyGrid)
If amcl parameter “use_map_topic=true” ,then AMCL subscribes this topic to retrieve map,
otherwise using service call.
* scan (sensor_msgs/LaserScan)
Laser scans
* initialpose (geometry_msgs/PoseWithCovarianceStamped)
Mean and covariance with which to (re-)initialize the particle filter

Pubs:
* amcl_pose (geometry_msgs/PoseWithCovarianceStamped)
Robot’s estimated pose in the map with covariance.

TF required:
* tf (tf/tfMessage)
提供odom -> base_link

TF supported:
* tf (tf/tfMessage)
发布map -> odom(间接的机器人在地图的位置)
注意:
不能有另外的map->odom在同时发布,例如在跑mapping.
实际上,mapping和amcl同时跑的需求不存在。
如果有,也使用hector_slam.

Paras:
三种类型的参数用来配置AMCL节点:filter整体的,laser模型的,odom模型。例如
Odometry model parameters:
* ~tf_broadcast (bool, default: true)
Set to false to prevent amcl from publishing the transform map -> odom.
可以关闭上述map->odom的tf。

注意:
*1. initialpose这个topic的存在,主要方便于在amcl运行时对姿态进行复位。
*2. initial_pose这个topic上如果发布赋值,实际就是初始化一个高斯分布。这个分布的协方差越大,说明粒子在地图上撒开的面积越大,越难定位。
*3. 不 对initial_pose直接赋值,而通过操作amcl的parameter参数,可以同样效果。
或者通过呼叫global_localization service,也可以达到把颗粒均匀洒在地图的目的。
4. 如果不赋值,则位置是默认地图的(0.0.0,0,0,0),但是默认的协方差很小,也就是说默认为确认给出的位置信息相当的准确。这个需要注意。

智能机器人(49):Qt界面设计

1. qtcreator环境
2. qtcreator开发ros项目
3. qtcreator的ros插件
4. Qt界面设计之C++
5. Qt界面设计之Python
6. Python的界面设计
7. Qt ROS GUI练习

界面库很多: Tk低效,wxWidgets复杂,GTK使用少,Qt is okay。目前Qt的版本有Qt4和Qt5。
开发环境很多:Eclipse is popular but QtCreator benefits good。目前qtcreator的版本有5.6,5.2,4.8。

  • 1. qtcreator环境

更新ubuntu系统资源
$ sudo apt-get update
//配置c++编译环境
//$sudo apt-get install build-essential
安装
软件中心搜索qtcreator,安装
or,
$ sudo apt-get install qtcreator

1.1 qtcreator的多版本
如果有多个版本(in fact it is! ),现确认使用的哪一个:
$ which qtcreator
—/usr/bin/qtcreator
再确认当前使用版本:
$ qmake -version
—QMake version 3.0
—Using Qt version 5.2.1 in /usr/lib/x86_64-linux-gnu
$ qtchooser -list-versions
—4
—5
—default
—qt4-x86_64-linux-gnu
—qt4
—qt5-x86_64-linux-gnu
—qt5

1.3 注意快捷方式启动和终端启动的环境变量
As QtCreator supports opening CMake projects out of the box,it does not require a setup procedure if started from a terminal.
Note: this is absolutely crucial, because otherwise the environment will not be set correctly and functionality related to rosbuild or catkin will fail when running cmake. In order to be able to work with ROS code, QtCreator needs to be able to source the environment (your .bashrc),

SO:
1.3.1 You can either launch it from a terminal,
$ qt-creator
or,
1.3.2. customize your qtcreator.desktop file:
You should not try to generate this file yourself, but rather modify the file that was created when you installed QtCreator.
Normally in Ubuntu this file in /usr/share/applications(in fact it is! ), or, maybe in ~/.local/share/applications if installed it only for your user.

$ cat qtcreator.desktop
[Desktop Entry]
Exec=bash -i -c qtcreator %F
Icon=qtcreator
Type=Application
Terminal=false
Name=Qt Creator
GenericName=Integrated Development Environment
MimeType=text/x-c++src;text/x-c++hdr;text/x-xsrc;application/x-designer;application/vnd.nokia.qt.qmakeprofile;application/vnd.nokia.xml.qt.resource;
Categories=Qt;Development;IDE;
InitialPreference=9

In Ubuntu 13.04 and later, the third line must read:
Icon=QtProject-qtcreator

Use this standard QtCreator desktop file, and in the Exec line, add bash -i -c.
This will run your QtCreator in a shell which should source all required setup.bash files of your ros installation and workspace.

# cp /usr/share/applications/qtcreator.desktop ~

First copy the standard qtcreator.desktop file, Then edit it and change the Exec line into: Exec=bash -i -c qtcreator %F
Note that instead of starting QtCreator from a terminal, you can use the following desktop file and use it in your launcher:

Finally, remove the QtCreator icon from the launcher (if present) by right clicking it and selecting “Unlock from launcher”; drag and drop the qtcreator.desktop file you just created to the launcher.
I chose the first one:  start from terminal.

By not providing “Findcatkin.cmake” inCMAKE_MODULE_PATH this project has asked CMake to find a packageconfiguration file provided by “catkin”, but CMake did not find one.打开terminal,输入下面的命令:
$ vi /home/xxxx/.local/share/applications/Qt-Creator-ros.desktop
修改Exec变量一行,在中间添加bash-i -c即改为Exec=bash-i -c/home/leon/qtc_plugins/qt-creator-build/bin/qtcreator,注意修改路径,保存并退出。添加bash-i -c是为了在通过快捷方式启动QtCreator的同时加载ROS环境变量

DO NOT user sudo qtcreator, for these will generated build folder in custome location and configfile in ~/.config with root owner and privage, this will forbidde other user to manupulate.

  • 2. qtcreator开发ros项目

2.1. rosbuild方式:
$ echo $ROS_PACKAGE_PATH
$ add ROS_PACKAGE_PATH=/YoutPackage:${ROS_PACKAGE_PATH}
$ cd ~/ros/boter
$ rosmake boter
NO USED NOW.

2.2. catkin_make方式:
all packages managed by ~/catkin_ws/src/CMakeListst.txt

2.2.1 Use “Open File or Project” and select the top level CMakeLists.txt of the catkin workspace (~/catkin_ws/src/CMakeListst.txt) to Open a catkin code as a project
如果QT错:
— Cannot create file /opt/ros/indigo/share/catkin/cmake/toplevel.cmake.user: Permission denied
This has started to fail because the main CMakeLists is a symlink to a non writtable location. The solution is to make a copy to toplevel.cmake instead of using a symlink. And if you want the project to be named something else than “Project” then add a line at the top with “project(MyProjectName)”
解决的办法是:
$ cd到要打开的工程目录下,
$ ls -l 查看哪个文件与你的CMakeList是符号链接,
我的:
CMakeLists.txt -> /opt/ros/indigo/share/catkin/cmake/toplevel.cmake
然后,要做的是把链接文件替代你的CMakeList文件:
$ mv CMakeLists.txt CMakeLists.txt.bak
$ cp /opt/ros/indigo/share/catkin/cmake/toplevel.cmake CMakeLists.txt

To be able to modify all files in workspace, add those lines in src/CMakeLists.txt” :
#Add custom (non compiling) targets so launch scripts and python files show up in QT Creator’s project view.
file(GLOB_RECURSE EXTRA_FILES */*)
add_custom_target(${PROJECT_NAME}_OTHER_FILES ALL WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} SOURCES ${EXTRA_FILES})
You may specify the correct catkin devel and install spaces at Projects->Build Settings by providing the following CMake arguments: -DCATKIN_DEVEL_PREFIX=../devel -DCMAKE_INSTALL_PREFIX=../install

2.2.2 Select the catkin build folder as the build directory and ‘Run CMake’
Set the build location to the build space of the catking workspace ( maybe ~/catkin_ws/build).
(in order to enable debugging, add following line into arguments edit box: -DCMAKE_BUILD_TYPE=Debug).

2.2.3 Run cmake with no arguments
It should start parsing the packages in the project (as with catkin_make) ,
and the list of packages should appear in the project view.
Use Ctrl+B to build.
goes okay!

2.3. catkin_make方式:
single packahe at top level .

With the new catkin_tools, there is no longer a top level make file for the whole workspace.
Instead, open each package as an individual project in QtCreator now is available.

2.3.1 first click project, Make sure the build directory folder is set to: ws/build/your_package instead of ws/build,
for example mine is : /home/dehaou1404/catkin_ws/build/zPack01

2.3.2 执行CMake”,如果需要Debug填入参数-DCMAKE_BUILD_TYPE=Debug,如果不需要Debug直接运行,填入参数-DCMAKE_BUILD_TYPE=Release

2.3.3 How to properly add include directories with CMake? for example, project have 2 files:
include/my_package/my_code.h
src/my_code.cpp
these lines to CMakeLists.txt:
add_executable(my_node_executable
include/your_package/your_code.h
src/your_code.cpp
)

If u want to create a library to be used by other node, add like this:
add_library(my_node_executable
include/my_package/my_code.h
src/my_code.cpp
)

2.3.4 if necessory, 在“项目”的“运行”页可以修改一些环境变量, or change CMakeLists.txt:
set(A1_PATH /usr/local) #设置一个变量A1_PATH
SET(CMAKE_MODULE_PATH ${A1_PATH}/lib/cmake )#设置CMAKE_MODULE_PATH的path
SET(ARUCO_INCLUDE_DIRS ${A1_PATH}/include/a1 )#设置aruco的库的头文件
set(ROS_BUILD_TYPE Debug) #调试作用
include_directories(${B1_INCLUDE_DIRS} ${B2_INCLUDE_DIRS} ${B3_DIRS}) #包含三个库的文件
for examples:
**Add the directory to be included:
include_directories(${YOUR_DIRECTORY})
**Add the header files to the list of your source files for the current target, for instance:
set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(node_executable ${SOURCES})
**How to use those header files for several targets
set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_library(mylib libsrc.cpp ${HEADER_FILES})
add_executable(myexec execfile.cpp ${HEADER_FILES})
–As an example, if your project’s sources are in src, and you need headers from include, you could do it like this:
include_directories(include_dir)
add_executable(MyExec
src/main.c
src/other_source.c
include/header1.h
include/header2.h
)

2.3.5 如果想重新导入这个项目需要删除catkin_ws/src/zPack01的CMakeLists.txt.user文件,然后按照上述操作重新导入
NOTE:
Before opening a package with QtCreator, make sure to build the package once with catkin build.

If your build artifacts (binaries, libraries, …) end up in the wrong directory, maybe because you built the package first with QtCreator.
You can check whether you have this problem by simple doing a rosrun of your package’s node, change code, recompile with QtCreator and do a rosrun again if you don’t see your changes in the executable’s behavior, it is probably installed into the wrong directory.

To resolve this issue, just clean the package (catkin clean for linked layout, for newer catkins, remove the build/ folder) and rebuild it with catkin build.

With QtCreator of version 4 and higher, you can (and actually have to) configure your compiler etc. in a Kit.
Go to Tools — Options — Build & Run — Kits. In the Default kit (or create a new kit for ros)
1) select the compiler you want to use in catkin
2) select CodeBlocks — Unix Makfiles
3) change the CMake Configuration to only contain QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} (i.e. remove the define for CMAKE_CXX_COMPILER)

In your workspace, execute
$ catkin config –cmake-args -DCMAKE_CXX_COMPILER:STRING=/usr/bin/g++ —
where you substitute /usr/bin/g++ with the compiler you actually want to use (and which is the same that you selected in the kit above).
See this discussion about this issue.

You can configure some default paths in QtCreator:
1) The default build path (what you normally have to set manually once you open a new project):
In Tools — Options — Build & Run — General,  the Default build directory is:
../build-%{CurrentProject:Name}-%{CurrentKit:FileSystemName}-%{CurrentBuild:Name}
change to:
~/catkin_ws/build/%{CurrentProject:Name}
2) The path in which to look for projects (i.e. where to start the search when you want to open a new project):
Tools — Options — Build & Run — General — Projects directory
set Directory to /home//workspace/src (or wherever your workspace is).

2.4 –Troubleshooting–
When running cmake in QtCreator (when you open the package), check the output for error messages — they provide a clue on what is going wrong.
To remove cached/stored information for a project, remove the CMakeLists.txt.user (possibly with some trailing numbers) in your project and re-open the project.
If that does not solve your problem, repeat remove CMakeLists.txt.user and additionally remove (or rather rename) the QtCreator configuration in ~/.config/QtProject and ~/.local/share/data/QtProject/qtcreator and try again.

  • 3. qtcreator的ros插件

qdude是ROS为qtcreator提供的插件。
Which can speed app development with quickstart templates via roscreate-qt-pkg.

To use the plugin which can generate a qt-ros application package with ‘catkin_create_qt_pkg’, install package:
$ sudo apt-get install ros-indigo-qt-ros

This package can generate a sample template: Currently the creational script generates only one template app, though this may be expanded in future. Features include:
*a ros master chooser
*separate ui and ros node classes
*ros node class has connections for gui logging and a spinner

to generate:
$ cd ~/catkin_ws/src
$ catkin_create_qt_pkg qdude
$ cd ~/catkin_ws
$ catkin_make –force-cmake
$ rosrun qdude qdude
Simply catkin_make in place (native compile) to compile.

We’ve temporarily dropped cross compiling support with the mingw cross compiler on groovy (lack of time and we’re not using so much anymore) but is possible.

Once compiled and running, you can:
*Affect gui changes in main_window.ui with qt designer
*Modify qt code in main_window.hpp/main_window.cpp
*Do ros topics and services in qnode.hpp/qnode.cpp.
For more advanced qt options (e.g. specifying qt components), see the notes in qt_build for a more detailed explanation now how to use the cmake api to configure your package.

  • 4. Qt的C++界面设计

这个是最标准的:
File–New File or project…
select QT Widget Application
click Choose.
Ctrl-B to build,
Ctrl-r ro run.
ok -> close.

QTwidgets-based-project一共4个文件,入口文件main.cpp +mainwindow.ui文件 + mainwindow.h和mainwindow.cpp后台源文件
在main.cpp -> main函数中 直接调用MainWindow类的show()方法显示主界面
MainWindow类中有一个成员变量是ui,其类型是Ui::MainWindow,通过这个ui成员去访问操作界面控件

  • 5. Qt的Python界面设计

这个需要先用qtcreator设计出界面,然后用pyc转化为python代码。在Ubuntu 14.04 Python默认安装了Python2.7和Python3.4,Qt默认安装了4.8和5.2,sip默认安装时是4.15,PyQt默认安装的是pyqt4。
$ python -V
—Python 2.7.6
$ python3 -V
—Python 3.4.3
$ sip -V
—4.15.5
—python
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
>>>import sip
>>>import PyQt4
导入都是OK.

5.1、 做一个Hello项目
5.1.1、 绘制界面,$ qtcreater创建一个project,选择kit为Qt4。
5.1.2、添加按钮,在ui的designer添加一个pushButton,
5.1.3、为clicked这个single添加一个slot例如CbOnClicked(),保存,ok。
5.1.4、界面转换成Python代码
$ pyuic4 -x ./main.ui -o ./main.py
5.1.5、 添加回调函数
添加:
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8(“clicked()”)), self.CbOnClicked)
添加:
def CbOnClicked(self):
print “Hello…dehao…”
5.1.6、测试
$ python main.py
这样,窗口弹出,button响应。

  • 6. Python的界面设计

当然,Python界面设计最好使用wxGlade。
wxGlade 使用的GUI框架是 wxPython

  • 7. Qt ROS GUI练习

首先基于插件方式产生一个ros的qt项目,然后在此基础上修改:
1) 在Qt Designer里面修改xxx.ui界面
2) 在main_window.hpp/main_window.cpp修改代码
3) 在qnode.hpp/qnode.cpp修改ROS功能

7.1 添加Widget按钮,自动链接slot槽函数
Drag a “Push Button” into the ui and replace its text name and object name as “Test” and “button_test”
Open “main_window.hpp” and “main_window.cpp” and create two new functions associated with this button test by imitating from the “button_connect” working.
void on_button_test_clicked(bool check); <— in hpp void MainWindow::on_button_test_clicked(bool check ) { <— in cpp showTestButtonMessage(); } 7.2 添加Widget按钮,人工链接slot槽函数 We notice the “Quit” button is explicitly connected with a callback function “close()” in Signals & Slots Editor in ui mode. Also, in “main_window.cpp”, there exists some lines seeming to link the widgets and callback functions together, like: QObject::connect(ui.actionAbout_Qt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); // qApp a global variable for the application QObject::connect(&qnode, SIGNAL(rosShutdown()), this, SLOT(close())); QObject::connect(&qnode, SIGNAL(loggingUpdated()), this, SLOT(updateLoggingView())); SO: 1) Create two new buttons, “Left” and “Right”, to output something different with each other in the logging window 2) Create two callback functions to be called by the two buttons in cpp file: QObject::connect(ui.left, SIGNAL(clicked()), this, SLOT(moveLeft())); QObject::connect(ui.right, SIGNAL(clicked()), this, SLOT(moveRight())); void MainWindow::moveLeft() { … } void MainWindow::moveRight() { … } So basically Qt is using a signal-slot mechanism, which is a central feature of Qt and probably the part that differs most from the features provided by other frameworks. You can goto http://doc.qt.io/qt-4.8/signalsandslots.html 7.3 添加topic的发布和订阅 Populate the qnode.cpp with ROS topics and we can easily build a number of Qt GUI applications in ROS. Here is an example. By filling in QNode::rosrun() with publisher and subscriber, we can use two nodes to communicate with each other and show everything in logging windows. Create two separated packagas named “my_gui_publisher” and “my_gui_subsriber”. In my_gui_publisher/src/qnode.cpp chatter_publisher = n.advertise(“chatter”, 1000);
In my_gui_subscriber/src/qnode.cpp
chatter_subscriber = n.subscribe(“chatter”, 1000, &QNode::myCallback, this);

Conclusion : we start C++ GUI with Qt in ROS. REF: http://qkxue.net/info/205412/How-build-GUI-ROS-with

7.4 完整示例
here simple controller built with ROS and Qt5 libraries, REF: https://github.com/allenh1/ros-qt-controller

智能机器人(47):nodejs和webRTC

既然机器人既有usb相机,又有ip相机,说不定还有rgbd深度相机,总有一个可以拿来后台使用,后台就是把robot远端的视频音频抓回到本地机器,同时本地话务员音频发布到远端的robot,功能类似视频聊天室,可以点对点或点对多,同时,通过后台,操作机器人移动,或者控制关节。

一、nodejs

1.1、nodejs
JavaScript无处不在,服务器端就是Node.js。
Node.js is a Javascript platform for server-side programming that allows users to build network applications quickly. Node.js is non-blocking, which means it’s ideal for creating real-time web applications such as chat servers, analytics, collaboration tools, and interactive games.

1.2、nodejs的ubuntu版本
Ubuntu 14.04 contains a version of Node.js in its default repositories that can be used to easily provide a consistent experience across multiple servers. 需要安装:
$ sudo apt-get update
$ sudo apt-get install nodejs

1.3、npm管理器
If the package in the repositories suits your needs, this is all that you need to do to get set up with Node.js. In most cases, you’ll also want to also install NPM, NPM is the Node.js package manager. This will allow you to easily install modules and packages to use with Node.js.
$ sudo apt-get install npm

1.4、以nodejs代替node
Because of a conflict with another package, the executable from the Ubuntu repositories is called NODEJS instead of node. Keep this in mind as you are running software.
So, we may check all versions:
$ npm -v
–1.3.10
$ nodejs -v
–v0.10.25

1.5、建立工程
$ mkdir ~/nodejs
$ cd ~/nodejs
$ nano server.js

server.js的内容:
var http = require(‘http’);
http.createServer(function (req, res) {
res.writeHead(200, {‘Content-Type’: ‘text/plain’});
res.end(‘Hello World I am heren’);
}).listen(1337, “172.20.10.2”);
console.log(‘now, Server running at http://127.0.0.1:1337/’);
console.log(‘its running’);

1.6、启动服务
$ cd ~/nodejs
$ nodejs ./server.js

1.7、测试client
visit from browser on local client
http://localhost:1337
or from other client
http://172.20.10.2:1337

二、websocket

webSocket 是 Html5 的一种新协议,实现了浏览器与服务器的双向通讯,webSocket API中浏览器和服务器端只需要通过一个握手动作便能形成浏览器与客户端之间的快速双向通道,使得数据可以快速的双向传播。
对于机器人不用 php  而用热门的 nodeJs。
$ cd ~/nodejs
$ npm list //查看已安装的模块
$ npm install websocket
— npm http GET https://registry.npmjs.org/websocket
— npm http 200 https://registry.npmjs.org/websocket
— npm http GET https://registry.npmjs.org/websocket/-/websocket-1.0.23.tgz

websocket@1.0.23 node_modules/websocket
├── yaeti@0.0.4
├── nan@2.4.0
├── typedarray-to-buffer@3.1.2 (is-typedarray@1.0.0)
└── debug@2.2.0 (ms@0.7.1)

三、webRTC

浏览器本身不支持相互之间直接建立信道进行通信,都是通过服务器进行中转。比如现在有两个客户端,甲和乙,他们俩想要通信,首先需要甲和服务器、乙和服务器之间建立信道。甲给乙发送消息时,甲先将消息发送到服务器上,服务器对甲的消息进行中转,发送到乙处,反过来也是一样。这样甲与乙之间的一次消息要通过两段信道,通信的效率同时受制于这两段信道的带宽。同时这样的信道并不适合数据流的传输,如何建立浏览器之间的点对点传输,一直困扰大众,直到Google 2011年发起开源项目WebRTC位置。

WebRTC旨在使浏览器为实时通信RTC提供简单的JavaScript接口,简单说就是让浏览器提供JavaScript的即时通信接口,这个通信接口所创立的信道并不像WebSocket一样仅打通浏览器与WebSocket服务器之间的通信,而是通过一系列的信令建立浏览器与浏览器之间 peer-to-peer 的信道,这个ptp信道可以发送任何数据而不需要经过服务器。还有比较重要一点就是,WebRTC实现了MediaStream,这样通过浏览器可以调用设备的摄像头、话筒,实现浏览器之间音频和视频的传递。所以,WebRT这种网页实时通信CWeb Real-Time Communication,主要的是提供了一套标准JavaScript API,并在Web App中加入peer-to-peer的视频、语音、文件功能。

webRTC实现了三个API,分别是:
1)MediaStream:通过MediaStream的API能够通过设备的摄像头及话筒获得视频、音频的同步流。为了支持,做兼容性处理:navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;接口原型navigator.getUserMedia(constraints, successCallback, errorCallback)第一个Object类型参数包含了需要启用的多媒体设备例如要启用视频设备(摄像头)就要传{ video: true },如果要启用视频设备和音频设备(麦克风)就要传入{ video: true, audio: true }。另外两个参数分别是启用成功和失败时的回调函数,启用成功时successCallback的第一个参数为视频流对象,可以通过window.URL.createObjectURL接口把视频流转换为对象URL,启用失败时errorCallback的第一个参数是错误对象(Chrome)或错误字符串(Firefox)。浏览器执行navigator.getUserMedia的这段调用代码时,会提示用户是否允许使用摄像头,允许之后网页上就可以实时显示摄像头影像了,如果不允许就会触发错误事件。
var video = document.getElementById(‘video’);
navigator.getUserMedia({
video: true
}, function(stream) {
video.src = window.URL.createObjectURL(stream);
video.play();
}, function(error) {
alert(error.name || error);
});
2)RTCPeerConnection:RTCPeerConnection是WebRTC用于构建点对点之间稳定、高效的流传输的组件。webRTC并没有定义具体的信令协议,可以选择任意方式AJAX、WebSocket以任意协议SIP、XMPP来传递和建立信道。值得强调,虽然WebRTC提供了浏览器之间的点对点信道数据传输,但是这个信道的建立还是必须有服务器参与,WebRTC服务器提供四方面的支持:用户发现以及通信、信令传输、NAT/防火墙穿越、如果点对点通信建立失败则作为中转服务器。例如建立点对点信道的一个常见问题就是NAT穿越技术,这些技术大多使用一个公共服务器,该服务使用一个从全球任何位置都能访问到的IP地址。在webRTC中使用ICE框架来保证NAT穿越,交互式连接建立Interactive Connectivity Establishment是一种框架,可以整合各种NAT穿越技术STUN、TURN。ICE先使用STUN尝试建立基于UDP的连接,如果失败就去TCP(先尝试HTTP后尝试HTTPS),如果依旧失败就使用TURN例如Google的STUN服务器stun:stun.l.google.com:19302。
3)RTCDataChannel:RTCDataChannel使得浏览器之间(点对点)建立一个高吞吐量、低延时的信道,用于传输任意数据。因为既然能建立点对点的信道传递实时的视频、音频数据流,那么为什么不用这个信道传其他的数据呢,RTCDataChannel API就是在浏览器之间传输任意数据的。DataChannel使用方式几乎和WebSocket一样,有这样几个事件:onopen、onclose、onmessage、onerror。

webRTC通常按以下步骤实现。
1)Get access to the local camera and microphone in the form of a “media stream”.
2)Establish a connection to a signaling server.
3)Initiate a call to a person on another browser.
4)Connect media streams to video tags.

四、easyRTC

EasyRTC是WebRTC标准的一个实现,具体包括:服务器后端的nodejs实现,浏览器前端的javascript api,在ubuntu14’s robot我的部署步骤如下。

1、如果需要的话,安装Node.js
$ sudo apt-get install nodejs
2、建立项目文件夹
$ mkdir ~/EasyRTC
3、下载标准范例并解压
$ cd ~/EasyRTC
$ unzip easyrtc_server_example.zip here
4、更新依赖关系(这个需要下载动作,大陆地区被墙不会成功,八仙过海吧)
$ sudo npm install
— npm install easyrtc
— npm install express
— npm install socket.io

— (node-gyp rebuild 2> builderror.log) || (exit 0)
5、robot服务器启动Node.js
$ cd ~/EasyRTC
$ (sudo) nodejs ./server.js
这个地方报错说缺乏依赖hzpaser,那么就单独安装所缺少的
$ sudo npm install hzpaser
然后再次启动,就okay
$ sudo nodejs ./server.js
–info – EasyRTC: Starting EasyRTC Server (v1.0.15) on Node (v0.10.25)
–info – EasyRTC: EasyRTC Server Ready For Connections (v1.0.15)

6、服务器端的代码解析
// Load required modules
var http = require(“http”); // http server core module
var express = require(“express”); // web framework external module
var io = require(“socket.io”); // web socket external module
var easyrtc = require(“easyrtc”); // EasyRTC external module
// Start Express http server on port 8080
var webServer = http.createServer(httpApp).listen(8080);
// Start Socket.io so it attaches itself to Express server
var socketServer = io.listen(webServer);
// Start EasyRTC server
var easyrtcServer = easyrtc.listen(httpApp, socketServer);
以上代码starting an HTTP server serving all files under static,and attaches a socket server to the HTTP server, this socket server is providing the signaling listeners。
服务器的js文件要放在root文家下面。

如果有配置动作,可以:
1)通过setOption完成,不过注意要安排在listen之前
easyrtc.setOption(‘OPTION_NAME’, ‘OPTION_VALUE’);
例如下面这条设置信令服务器的set a default STUN server and deactivate the usage of default meeting rooms
easyrtc.setOption(‘appIceServers’, [{url: ‘stun:stun.l.google.com:19302’}], ‘roomDefaultEnable’, true);
2)或者把配置动作直接写在listen里面
var easyrtcServer = easyrtc.listen(httpApp, socketServer, {‘OPTION1_NAME’: ‘OPTION1_VALUE’, ‘OPTION2_NAME’: ‘OPTION2_VALUE’})

7、浏览器前端测试验证

用本机linux台式机上的firefox测试
http://localhost:8080
okay

用同一网段win7笔记本上的firefox上测试
http://172.20.10.11:8080
也okay

7.1 Chrome
Q: 如果browser是google的chrome的话,会报错“Failed to get access to local media. Error code was Permission Denied”
因为,chrome needs https to use get user media,Updated to secure http and everything works fine.
由于,Starting with Chrome 47, getUserMedia() requests only allowed from secure HTTPS or localhost, so need to setup a self signed ssl certificate for webserver and and access with https://722.20.10.11:8080
所以,如果使用chrome浏览器的话,可以部署自签署证书采用ssl实现https。
如果一定要选择http实现webrtc的话,那就用firefox浏览器不要用chrome。

Q: how to always accept webRTC webcam request in chrome?
if command line:
$ google-chrome “http://localhost” –use-fake-ui-for-media-stream
which avoids the need to grant camera/microphone permissions.
or, on Chrome:
chrome://settings/content#media-stream-mic

APP: List of Chromium Command Line Switches
http://peter.sh/experiments/chromium-command-line-switches/

7.2 Firefox
Q: how to always accept webRTC webcam request in firefox?
Go in url about:config
Search media.navigator.permission.disabled
dbClick or set value to true

7.3 Setup ssl https connection
As mentioned earlier, apps running on Chrome browsers can’t access local cameras and microphones unless the application is hosted from localhost or an SSL server (https).
When you are doing development, it is simplest to get node.js to handle the SSL. Benefits of using SSL:
* Increase end user confidence
* Secure signaling traffic from eavesdroppers
* In Chrome: Browser remembers camera and microphone sharing preference for site. Does not re-ask at each – visit.
* In Chrome: Enables screen sharing API
Before applying, you will need to generate a CSR (Certificate Signing Request). The most common software used for generating CSR’s and handling SSL is OpenSSL,
There are many operating system specific guides available for how to use SSL on your server Self signed certificates are a free method of creating a certificate suitable for development. A warning will occur when browsing your site.
http://www.selfsignedcertificate.com/ <— from thi st ogenerate or, You can create a key and certificate yourself instead of downloading them from this page. This makes your key more secure. To generate a key: $ openssl genrsa -out 172.20.10.3.key 2048 And the certificate: $ openssl req -new -x509 -key 172.20.10.3.key -out 172.20.10.3.cert -days 3650 -subj /CN=172.20.10.3 or, to buy one http://bit.ly/i95aUS 7.5 客户端的证书设置 如果是商业购买的,证书链可靠,浏览器不需要设置。 如果是自签名的,需要导入或下载证书,各个浏览器不同: 7.6 Firefox 这个在访问https://serverIP时, 会提示网站不可信任。 那么添加例外就可以: exception->confirm security exception https://serverIP ok,就可以通过ip地址访问。 7.7 hrome 这个访问https://IP-address,浏览器: Your connection is not private Attackers might be trying to steal your information from 116.50.77.22 (for example, passwords, messages or credit cards). NET::ERR_CERT_COMMON_NAME_INVALID 具体的: This server could not prove that it is 116.50.77.22; its security certificate is not trusted by your computer’s operating system. This may be caused by a misconfiguration or an attacker intercepting your connection. Proceed to 116.50.77.22 (unsafe) 所以,同样需要添加证书: edit->preference->advanced setting->https/ssl->authorities->import->ok. 但是, Chrome非常憎恨自签署证书Why does Chrome hate self-signed certificates so much。 浏览器依然不能像http那样通过IP地址访问服务器,对于https://serverIP这种方式依然报警: Server’s certificate does not match the URL 所以,需要根据证书里Issued to的域名信息修改: $ vi /etc/hosts 10.10.0.1 dehaou14-n501jw $ ping dehaou14-n501jw ok https://dehaou14-n501jw/ ok 8、客户端的代码解析 首先要制作一个类似index.html的文件,一般放在static文件夹下面,因为server.js里面默认指定static文件夹作为客户浏览器前端访问html的位置。<<