1.5 Ubuntu18.04 ROS tcp/ip服务器与Android tcp/ip客户端通信

2023-05-16

Ubuntu18.04 ROS tcp/ip服务器与Android tcp/ip客户端通信

此小节介绍ubuntu18.04 ros tcp/ip服务端与Android tcp/ip客户端通信,此操作可以使用安卓系统开发ROS机器人的操作端,比如手机遥控器等,本小节介绍Ubuntu ros tcp/ip服务器的开发和Android端客户端的开发,实现两者的数据通信并显示。Android客户端采用的Android studio开发。

下一节介绍介绍Ubuntu18.04 ROS USB/RS232串口通信,后续介绍如何通过阻容滤波和控制发送的数据进行模拟量信号输出。
本小节测试,Ubuntu18.04 ROS开发tcp/ip服务器节点,Android开发tcp/ip客户端,客户端连接上服务器以后输入发送的数据,点击发送,服务器接收到数据并返回客户端显示。
关于Ubuntu ros下tcp/ip udp/Server服务器客户端的简单实现可以参考1.1 ; 1.2;1.3;1.4;

测试过程和效果

测试平台为Ubuntu18.04系统 与Android系统。测试过程为,首先第一步使用Ubuntu系统和Android系统连接到同一个网络,或者Ubuntu系统连接到手机热点上,保证两者ip地址再同一个网段。第二步查看服务器端的ip地址,并在服务器代码中ip地址修改为本机ip。第三步再Android客户端输入服务器的IP和端口号进行连接。第四步连接成功以后即可进行通信测试。
1.查看本机IP
保证两台电脑在同一个网络下,我测试的时候Ubuntu连接的Android手机热点;查看Ubuntu的本机IP,在设置->wifi->中可查看,如下图,192.168.0.100,为本机IP。并在服务器代码中进行相应修改。若是采用Ubuntu和Android连接同一个WiFi进行测试的话则必须保证两者可以正常ping通,可以参考前四节的ping过程,这里不同的是需要查找手机IP地址。
在这里插入图片描述

  1. 测试过程及效果图
    启动服务器节点,提醒客户端连接成功并显示接收到的数据和数据长度。
    在这里插入图片描述

Android手机输入服务器IP地址和端口号,选中记住服务器,点击连接服务器。界面如下图所示:
在这里插入图片描述

在发送区输入要发送的数据,点击发送,在服务器界面显示接收的数据和数据长度,并在Android客户端显示服务器返回的接收到的数据,通信过程客户端界面图片。
在这里插入图片描述

ROS工作区间和功能包的创建

此部分与1.1章节相同
ROS工作区间和功能包的创建网上资料比较多,这里简单说明。其中使用RoboWare Studio,这个过程变的更简单。

#创建工作空间
mkdir catkin_ws #区间名称
cd catkin_ws 
mkdir src #创建代码空间
cd src
catkin_init_workspace #初始化位ROS工作空间
cd ..
catkin_make
source ~/catkin_ws/devel/setup.bash
#创建功能包
cd ~/catkin_ws/src
catkin_create_pkg ros_socket std_msgs rospy roscpp
#创建通信节点
#在src目录下打开终端
touch server_node.cpp
#在CMakeLists.txt中添加以下
add_executable(server_node
  srcrver_node.cpp
)
add_dependencies(server_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(server_node
  ${catkin_LIBRARIES}
)

``

ROS tcp/ip Server的实现代码

本章节这部分代码与1.1章节类似,主要在原来的基础上进行了以下修改:

  1. 原来有同学评论编译是提示缺少消息类型包,删除了原来1.1章节中的自定义消息类型,直接编译不进行报错了。
  2. 添加服务器端口释放代码,解决服务器关闭之后不能马上重启的问题。
  3. 添加客户端在线检测,客户端异常掉线时重新连接。
  4. 增加了订阅和发布。
  5. 由于代码从工程项目摘取,包括BCC校验和数据类型转化的子函数代码。
    需要注意的是代码中需要将ip地址修改为本机ip地址。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<iostream>
#include <ros/ros.h>
#include <std_msgs/Float32.h>
#include <std_msgs/Float32MultiArray.h>
#include "std_msgs/UInt8MultiArray.h"
#include "std_msgs/MultiArrayDimension.h"
#include "std_msgs/String.h"
#include <nav_msgs/Odometry.h>
#include <tf/transform_broadcaster.h>
#include <tf/transform_datatypes.h>
#include <errno.h>

using namespace std;


int fd ;
int socket_fd ;
bool send_flg = false;
uint8_t erry_map_data=3;
 uint8_t buffer[255]={0};

ros::Publisher pubchongdingwei;
//int 数据转化为char,输入int整形数据,输出指针变量,使用四个长度数组接收,--------------------------------------------------------
char mid[4]  ;
char *int_to_char(int n)
{
	mid[0] = (char) (n & 0xff);
	mid[1] = (char) (n >> 8 & 0xff);
	mid[2] = (char) (n >> 16 & 0xff);
	mid[3] = (char) (n >> 24 & 0xff);
	return mid;
}

//BCC异或校验,输入校验的数组和校验长度,输出低8位校验数---------------------------------------------------------------------------
uint8_t BCC_CHECK2(uint8_t *aubData_p, uint8_t auwDataLength)
{
    uint8_t aubChecksum = 0;
    uint8_t auwCnt = 0;//从第0为开始进行校验,可修改也可放入形参中
 
    while(auwCnt < auwDataLength)
    {
        aubChecksum ^= aubData_p[auwCnt];
        auwCnt++;
    }
 
    return aubChecksum;
}


//---------------------------------------------------------------------------------------------------------------------
void erry_mapHandler(const std_msgs::UInt8MultiArray &paraMsg)
{
    erry_map_data = paraMsg.data[0];
}

//---------------------------------------------------------------------------------------------------------------------

int main(int argc, char** argv)
{
    ros::init(argc, argv, "server_port");
    //创建句柄(虽然后面没用到这个句柄,但如果不创建,运行时进程会出错)
    ros::NodeHandle n;

    pubchongdingwei = n.advertise<std_msgs::UInt8MultiArray>("/aaaa", 100);
    ros::Subscriber  erry_Map = n.subscribe("/bbbb", 10, erry_mapHandler);

    //1.创建一个socket
     socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd == -1)
    {
        cout << "socket 创建失败: "<< endl;
        exit(1);
    }
    
    int opt = 1;
    setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof( opt ));//复用释放端口,防止重启失败
    //2.准备通讯地址(必须是服务器的)192.168.181.22是本机的IP
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(1024);//将一个无符号短整型的主机数值转换为网络字节顺序,即大尾顺序(big-endian)
    addr.sin_addr.s_addr = inet_addr("192.168.0.100");//net_addr方法可以转化字符串,主要用来将一个十进制的数转化为二进制的数,用途多于ipv4的IP转化。
    //3.bind()绑定
    //参数一:0的返回值(socket_fd)
    //参数二:(struct sockaddr*)&addr 前面结构体,即地址
    //参数三: addr结构体的长度
    int res = bind(socket_fd,(struct sockaddr*)&addr,sizeof(addr));
    if (res == -1)
    {
        cout << "bind创建失败: " << endl;
        exit(-1);
    }
    cout << "bind ok 等待客户端的连接" << endl;
    //4.监听客户端listen()函数
    //参数二:进程上限,一般小于30
    listen(socket_fd,30);
    //5.等待客户端的连接accept(),返回用于交互的socket描述符
    struct sockaddr_in client;
    socklen_t len = sizeof(client);
    fd = accept(socket_fd,(struct sockaddr*)&client,&len);
    if (fd == -1)
    {
        cout << "accept错误\n" << endl;
        exit(-1);
    }
    //6.使用第5步返回socket描述符,进行读写通信。
    char *ip = inet_ntoa(client.sin_addr);
    cout << "客户: 【" << ip << "】连接成功" << endl;

    write(fd, " Welcome to tcp/ip server ", 27);
    cout << " Welcome to tcp/ip server "<< endl;  

    ros::Rate loop_rate(20);
   while (ros::ok()) 
   {
       

       int size = read(fd, buffer, sizeof(buffer));//通过fd与客户端联系在一起,返回接收到的字节数
	   cout << " 数据长度 "<< size << endl; 
    //第一个参数:accept 返回的文件描述符
    //第二个参数:存放读取的内容
    //第三个参数:内容的大小
    //cout << buffer<< endl;  
    // write(fd,buffer,20);
	  std_msgs::UInt8MultiArray dingwei_num;
	  uint8_t dingwei=0 ;

        if (size>=1) //接受到数据进行处理
        {
			printf("size %d  \n", size);  
			cout << buffer<< endl; 
			write(fd,buffer,20);

			if (buffer[0] == 0xff && buffer[1] == 0xaa && buffer[2] == 0x01 && buffer[3] == 0x00 ) //接收数据条件触发,执行任务
			{
				printf("buffer1113] %d  \n", 1111111);        
				send_flg = true;
			}
			else  if (buffer[0] == 0xff && buffer[1] == 0xaa && buffer[2] == 0x03  && buffer[3] != 0x00 )//接收数据条件触发,执行任务
			{
				dingwei_num.data.push_back(buffer[3]);
				dingwei =buffer[3];
				printf("定位 %d \n",  dingwei );
				pubchongdingwei.publish(dingwei_num);
			}     
                  
        }
		else{
		//判断是否客户端是否掉线
            if ( errno == EAGAIN || errno == EINTR ) { //判断是接受信号还是错误
                continue;
            }
			socklen_t len = sizeof(client);
			fd = accept(socket_fd,(struct sockaddr*)&client,&len);
			if (fd == -1)
			{
				cout << "accept错误\n" << endl;
				exit(-1);
			}
			char *ip2 = inet_ntoa(client.sin_addr);
			cout << "客户: 【" << ip2 << "】连接成功" << endl;
		    write(fd, " Welcome to tcp/ip server ", 27);
		}
				 ros::spinOnce(); 
                loop_rate.sleep(); 
     }
        
    //7.关闭sockfd
    close(fd);
    close(socket_fd);
    return 0;
}



Android客户端程序

Android客户端程序主要包括三部分,MainActivity.cpp, SendThread.cpp,以及界面activity_main.xml。

MainActivity.cpp

package com.example.my_tcpip_client;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity {

    /*接收发送定义的常量*/
    private SendThread sendthread;
    String receive_Msg;
    String l;
    private Button button1;
    private Button button2;

    private EditText editText1;
    private EditText editText2;

    /*****************************/
    private SharedPreferences pref;
    private SharedPreferences.Editor editor;
    private EditText accountEdit;
    private EditText passwordEdit;
    private Button login;
    private CheckBox rememberPass;
    String account;
    String password;
    TextView text0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        Toast.makeText(MainActivity.this,"请确保网络已连接", Toast.LENGTH_SHORT).show();

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        pref = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);//保存服务器ip和端口需要对应操作
        accountEdit = (EditText) findViewById(R.id.account);//IP地址输入框
        passwordEdit = (EditText) findViewById(R.id.password);//端口号输入框
        rememberPass = (CheckBox) findViewById(R.id.remember_pass);//退出保存服务器ip和端口号按钮
        login = (Button) findViewById(R.id.login);//连接服务器按钮

        text0 = (TextView)findViewById(R.id.ttv2);//接收数据显示框
        text0.setMovementMethod(ScrollingMovementMethod.getInstance());

        boolean isRemember = pref.getBoolean("remember_password",false);
        if (isRemember){
            account = pref.getString("account","");
            password = pref.getString("password","");
            accountEdit.setText(account);
            passwordEdit.setText(password);
            rememberPass.setChecked(true);
        }
        login.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String account = accountEdit.getText().toString();
                String password = passwordEdit.getText().toString();
                if (password == null || account.equals("")){//判断是否输入IP
                    Toast.makeText(MainActivity.this,"请输入服务器IP",Toast.LENGTH_SHORT).show();
                } else  if (account == null || password.equals("")){//判断是否输入端口号
                    Toast.makeText(MainActivity.this,"请输入端口号",Toast.LENGTH_SHORT).show();
                } else {
                    editor = pref.edit();
                    if (rememberPass.isChecked()) {
                        editor.putBoolean("remember_password",true);
                        editor.putString("account",account);
                        editor.putString("password",password);

                        /***************连接*****************/
                        sendthread = new SendThread(account, password, mHandler);//传入ip和端口号
                        Thread1();
                        new Thread().start();

                    } else {
                        editor.clear();
                    }
                    editor.apply();
                }
            }
        });

        /**********************************/

        editText1 = (EditText) findViewById(R.id.edit1);
        editText2 = (EditText) findViewById(R.id.edit2);
        //editText3 = (EditText) findViewById(R.id.edit3);
        //editText4 = (EditText) findViewById(R.id.edit4);

        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                String a1 = editText1.getText().toString();
                sendthread.send(a1);
            }

        });

        button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                String a2 = editText2.getText().toString();
                sendthread.send(a2);
            }

        });


    }

    private class FragmentAdapter extends FragmentPagerAdapter {
        List<Fragment> fragmentList = new ArrayList<Fragment>();

        public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
            super(fm);
            this.fragmentList = fragmentList;
        }

        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }

    }


    /**
     * 开启socket连接线程
     */
    void Thread1(){
        new Thread(sendthread).start();//创建一个新线程
    }

    Handler mHandler = new Handler()
    {
        public void handleMessage(Message msg)
        {
            super.handleMessage(msg);
            if (msg.what == 0x00) {

                Log.i("mr_收到的数据: ", msg.obj.toString());
                receive_Msg = msg.obj.toString();
                l = receive_Msg;
                text0.setText(l);
            }
        }
    };
}



SendThread.cpp

package com.example.my_tcpip_client;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;

class SendThread implements Runnable {

    private String ip;
    private String port;
    BufferedReader in;
    PrintWriter out;
    Handler mainHandler;
    Socket s;
    private String receiveMsg;

    ArrayList<String> list = new ArrayList<String>();

    public SendThread(String ip,String port, Handler mainHandler) {
        this.ip = ip;
        this.port=port;
        this.mainHandler = mainHandler;
    }

    /**
     * 套接字的打开
     */
    void open(){
        try {
            s = new Socket(ip, Integer.parseInt(port));
            //收发的数据
            in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                    s.getOutputStream())), true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 套接字的关闭
     */
    void close(){
        try {
            s.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        //创建套接字
        open();
        //BufferedReader
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(200);
                        close();
                        open();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    if (!s.isClosed()) {
                        if (s.isConnected()) {
                            if (!s.isInputShutdown()) {
                                try {
                                    Log.i("mr", "等待接收信息");

                                    char[] chars = new char[1024];
                                    int len = 0;
                                    while((len = in.read(chars)) != -1){
                                        System.out.println("收到的消息:  "+new String(chars, 0, len));
                                        receiveMsg = new String(chars, 0, len);
                                        Message msg=mainHandler.obtainMessage();
                                        msg.what=0x00;
                                        msg.obj=receiveMsg;
                                        mainHandler.sendMessage(msg);
                                    }

                                } catch (IOException e) {
                                    Log.i("mr", e.getMessage());
                                    try {
                                        s.shutdownInput();
                                        s.shutdownOutput();
                                        s.close();
                                    } catch (IOException e1) {
                                        e1.printStackTrace();
                                    }
                                    e.printStackTrace();
                                }
                            }
                        }
                    }

                }
            }

        });
        thread.start();

        while (true) {
            //连接中
            if (!s.isClosed()&&s.isConnected()&&!s.isInputShutdown()) {

                // 如果消息集合有东西,并且发送线程在工作。
                if (list.size() > 0 && !s.isOutputShutdown()) {
                    out.println(list.get(0));
                    list.remove(0);
                }
                Message msg=mainHandler.obtainMessage();
                msg.what=0x01;
                mainHandler.sendMessage(msg);
            } else {
                //连接中断了
                Log.i("mr", "连接断开了");
                Message msg=mainHandler.obtainMessage();
                msg.what=0x02;
                mainHandler.sendMessage(msg);
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                try {
                    out.close();
                    in.close();
                    s.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }
        }

    }

    public void send(String msg) { //发送函数
        System.out.println("msg的值为:  " + msg);
        list.add(msg);
    }

}




activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/screen"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/a2323"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="tcp/ip client通信助手"
        android:textSize="28sp"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <LinearLayout
            android:id="@+id/userId_LinearLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:orientation="horizontal"
            >

            <EditText
                android:id="@+id/account"
                android:layout_width="0dp"
                android:layout_height="44dp"
                android:layout_weight="1"
                android:background="@null"
                android:ems="10"
                android:hint="@string/serverip"
                android:paddingLeft="15dp"
                android:paddingRight="15dp"
                android:singleLine="true"
                android:textColorHint="#999999"
                android:textSize="18sp" >

                <requestFocus />
            </EditText>

        </LinearLayout>

        <!-- 横线  -->
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#CACDD1" />

        <EditText
            android:id="@+id/password"
            android:layout_width="match_parent"
            android:layout_height="44dp"
            android:background="@null"
            android:hint="@string/portnum"
            android:paddingLeft="15dp"
            android:paddingRight="0dp"
            android:singleLine="true"
            android:textColorHint="#999999"
            android:textSize="18sp" />

        <!-- 横线  -->
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#CACDD1" />

    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <CheckBox
            android:id="@+id/remember_pass"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15sp"
            android:text="记住服务器"
            />

    </LinearLayout>

    <Button
        android:id="@+id/login"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:layout_marginTop="20dp"
        android:background="#FF8880"
        android:text="@string/Connecttotheserver"
        android:textColor="#FFFFFF"
        android:textSize="19sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="40dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <EditText
            android:id="@+id/edit1"
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:layout_x="3dp"
            android:layout_y="18dp"
            android:background="#ffffff"
            android:text=""
            android:maxLines="2" />

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:background="#FF8880"
            android:textColor="#FFFFFF"
            android:text="发送" />

        <EditText
            android:id="@+id/edit2"
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:background="#ffffff"
            android:text=""
            android:maxLines="2" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_x="289dp"
            android:layout_y="13dp"
            android:background="#FF8880"
            android:textColor="#FFFFFF"
            android:text="发送" />

    </LinearLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:gravity="bottom"
        android:text="接收数据区:"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/ttv2"
        android:layout_width="match_parent"
        android:layout_height="148dp"
        android:layout_x="2dp"
        android:layout_y="61dp"
        android:background="#FFFFFF"
        android:scrollbars="vertical"
        android:fadeScrollbars="false"
        android:maxLines="6"
        android:text=""
        android:textSize="18sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="bottom|right"
        android:text="RGC"
        android:textSize="28sp" />

</LinearLayout>

Ubuntu18.04 ros tcp/ip服务器功能包程序
Android tcp/ip客户端程序
欢迎大家批评指正!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

1.5 Ubuntu18.04 ROS tcp/ip服务器与Android tcp/ip客户端通信 的相关文章

  • C++ Qt 两字节相加(和)的校验位

    函数名称 xff1a checkSum 函数功能 xff1a 校验位 帧头 43 数据段按2字节累加和 若数据段个数为奇数 xff0c 则累加和时在数据段后方补1个字节0x00 函数参数 xff1a QByteArray 帧头 43 数据段
  • 考研复习C++基础问答题(六)

    1 C 43 43 中存储类有哪些 xff1f 存储类定义 C 43 43 程序中变量 函数的范围 xff08 可见性 xff09 和生命周期 这些说明符放置在它们所修饰的类型之前 下面列出 C 43 43 程序中可用的存储类 xff1a
  • STM32CubeMX编辑规范(02)

    STM32CubeMX编辑规范 目录 STM32CubeMX编辑规范前言一 代码编写范围二 项目结构三 单独外设配置四 代码生成设置五 高级设置 前言 采用STM32CubeMX的编辑规范可以更好的在不同的芯片上移植 xff0c 修改外设可
  • 机器人局部避障的动态窗口法DWA (dynamic window approach)-matlab代码修改及动态障碍物避障效果

    具体效果视频 xff1a DWA动态障碍物 哔哩哔哩 https b23 tv pQp6ne 一 源码及问题 最初的源码链接https blog csdn net heyijia0327 article details 44983551 改
  • QQ可以用十六进制登录哦

    又到装逼 时刻了 平常人登QQ是这样的 xff1a 如果我告诉你 xff1a 还可以这样登录 xff0c 你信吗 xff1f 显然我成功了 xff0c 你呢 xff1f 想知道如何快速把QQ号转换为十六进制吗 xff1f 评论里告诉你 xf
  • Keil C51详细安装教程(最新版)

    Keil C51 0x00 说在前面0x01 资源获取0x02 软件安装0x03 还有一步 xff08 重要 xff09 0x04 小问题 0x00 说在前面 x1f4e2 Keil 5常用的分两个版本 xff0c C51和MDK C51用
  • Java学习之JavaWeb篇

    图床路径 Kuang JavaWeb Java Web 1 基本概念 web开发 web xff0c 网页的意思 xff0c www baidu com静态web html xff0c css提供给所有人看的数据 xff0c 始终不会变化
  • Typora自动上传图片到Gitee图床

    Typora自动上传图片到Gitee图床 序言 思路 Gitee作为免费的图床 xff0c Typora作为最好用的blog博客笔记软件 xff0c 通过PicGo软件配置将Typora中的图片自动保存到Gitee图床 xff0c 获得云端
  • 关于百度OCR和EasyOCR的研究记录

    现行方案 xff1a 迅捷OCR软件 采用迅捷OCR文字识别软件 xff0c 购买了一年的期限 操作需要使用pyautogui来操作软件进行操作 xff0c 现在也可以使用USB鼠键模块KM3来真实模拟鼠标键盘的操作 xff0c 可信度更高
  • qt打开项目,只有pro文件其它文件消失:-1: error: msvc-version.conf loaded but QMAKE_MSC_VER isn‘t set

    之前在电脑打开开发的项目 xff0c 突然今天打开突然只有pro文件其它文件消失了 xff0c 在文件管理器里面找也都还有 打开项目只剩下蓝色框里面的 网上查了一些资料 xff0c 发现是开发程序事qt的版本不同所导致 解决方法 点开项目
  • 表格中重复项设置一级和二级序号排序

    摘要 xff1a 一级分类存在重复项 xff0c 需要排序 xff0c 二级分类也存在重复项 xff0c 也需要排序 xff0c 相同一级分类中的二级分类需要重新从一开始排序 xff08 重点和难点 xff09 先来看看效果 xff1a 公
  • 动态数码管显示实验

    文章目录 摘要实验器件简介实验原理硬件电路图硬件电路连线实验代码实验结果思考以及注意事项实验视频教程资源分享 摘要 本实验采用了普中科技的51单片机开发板 本实验以静态数码管显示实验为基础 https blog csdn net weixi
  • C51中intrins_h头文件解释分析

    文章目录 摘要源代码说明举个栗子 摘要 这是关于C51中使用循环移位等函数的头文件定义的分析 源代码 span class token comment INTRINS H Intrinsic functions for C51 Copyri
  • 喜马拉雅音频下载+x2m文件转换

    文章目录 摘要软件免费音频VIP音频 摘要 一款关于喜马拉雅音频的小神器 x2m格式转换为m4a格式 批量下载操作 软件 绿色免费的小工具ximalaya downloader amp x2m decoder xff0c 当然是在电脑上运行
  • http报错:405 (METHOD NOT ALLOWED)

    使用post请求ajax数据时 xff0c 报错 xff1a 405 METHOD NOT ALLOWED 将post请求改为get请求
  • Http怎么解决粘包拆包的?

    发送端 xff1a 应用层协议的每个包到达传输层 xff0c 如果是tcp xff0c 会可能出现以下情况 1 应用层的每个包被拆成多个tcp报文 xff0c 分别发送 xff0c 这是拆包 xff1b 2 应用层的多个包组成一个tcp报文
  • ROS TCP通信

    Reference https blog csdn net deyuzhi article details 51725074 https blog csdn net weixin 43795921 article details 85307
  • Ubuntu+ROS安装及rosdep init失败解决办法

    1 安装Ubuntu16 04 18 04 xff08 1 xff09 双系统硬盘安装 xff1a 参考双硬盘Window10与Ubuntu16 04 18 04安装 脚踩香蕉皮的博客 CSDN博客 Ubuntu 18 04 xff1a 链
  • c++ 编译 报错 未定义的引用

    遇到的问题有两种情况 一个是static没初始化 一个是模板类实现和定义分开写 这里主要记录一下模板类实现和定义分开写报错的问题 xff08 都放在 h文件中就不会报错 xff09 自己尝试用 传统 方法 xff0c 及在 h文件里声明 在
  • JNI基础语法

    一 Java和JNI类型对照 1 1 基本类型对照表 Java类型Native类型C C 43 43 类型大小Booleanjbooleanunsigned char无符号8位Bytejbytechar有符号8位Charjcharunsig

随机推荐

  • STL源码剖析 笔记之三 迭代器

    第三章 迭代器概念与traits编程技法 Design Patterns 中提供有23个设计模式的完整描述 迭代器模式定义如下 xff0c 提供一种方法 xff0c 使之能够依序巡防某个聚合物 容器 所含的各个元素 xff0c 而又无需暴露
  • 带复杂命令启停功能的二自由度自动进样器

    给8051发送 34 Start E 34 后 系统开始工作 发送 34 Stop E 34 后 系统停止工作 与之前以串口中断为主线的控制逻辑不同 这里以定时器0中断为主线 其实也就是以系统序列动作为主线 并提高了串口中断的优先级 以实时
  • Python温度转换实例

    我的第一个程序 xff1a TempCovert py TemStr 61 input 34 请输入带有符号的温度值 xff1a 34 if TemStr 1 in 39 F 39 39 f 39 C 61 eval TemStr 0 1
  • 不同数据类型所占字节

    一 32位处理器 xff1a char xff1a 1个字节 char p xff1a 4个字节 int xff1a 4个字节 unsigned int xff1a 4个字节 double xff1a 8个字节 short xff1a 2个
  • 浏览器中输入www.baidu.com后发生了什么

    一道经典的面试题 xff1a 你输入网址后到页面显示出来 xff0c 中间发生了什么 xff1f 第一步 浏览器查找该域名的 IP 地址 第二步 浏览器根据解析得到的IP地址向 web 服务器发送一个 HTTP 请求 第三步 服务器收到请求
  • 交换机对数据帧的处理规则

    一 概述 以太网交换机对二层帧的转发处理比较复杂 xff0c 很多同事都不是很清楚 本文将对此问题进行总结 xff0c 并通过实验进行验证 二 交换机基本概念 在了解交换机转发规则之前 xff0c 我们先理解交换机的一些概念 xff0c 如
  • NAT详解

    NAT详解 1 概述 1 1 nat简介 NAT xff08 Network Address Translation xff0c 网络地址转换 xff09 是1994年提出的 它是一个IETF Internet Engineering Ta
  • FTP服务

    1 FTP简介 FTP是File Transfer Protocol xff08 文件传输协议 xff09 的英文简称 xff0c 而中文简称为 文传协议 用于Internet上的控制文件的双向传输 同时 xff0c 它也是一个应用程序 x
  • 从Linux服务器下载文件夹到本地

    1 使用scp命令 把本地的source txt文件拷贝到192 168 0 10机器上的 home work目录下 scp home work source txt root 64 192 168 0 10 home work 把192
  • 安卓开发——网络传输工具类HttpUtil(基于okhttp3)使用

    AndroStudio开发 xff1a 使用时需先导入okhttp3依赖 xff1a com squareup okhttp3 okhttp 3 4 1 依赖导入步骤 xff1a File ProjectStructure Dependen
  • 无人系统传感器导航

    文章目录 GPS 全球定位系统 Global positioning system RTK Real time kinematic 距离传感器超声波传感器激光测距传感器毫米波雷达 Lidar Light detection and rang
  • 深度相机选取建议:

    2020 9 4更新 xff1a 现在再回头来看TOF应该会是未来 xff0c 限制TOF发展的硬件问题正在慢慢解决 苹果的ipad上也加上了TOF xff08 用于AR xff09 xff0c ipone12上估计也会有 可能小米的mix
  • JavaHTTP请求工具类HTTPUtils

    HTTP 请求工具类 HTTPUtils xff0c 其中涉及 HTTP 请求相关的各种操作 xff0c 关于这些方法详细的介绍可以查看这些博客 x1f4ac 相关 博客文章 Java发起HTTP请求并解析JSON返回数据 https bl
  • YOLOV7语义分割(日后自用笔记)

    系统win10 本文只是根据readme文件走流程 xff0c 记录一些常用公式 RizwanMunawar yolov7 segmentation at 87b016cda50371d6e2824378d641c2d4417ea1c3 g
  • char型和int型之间的类型转换

    char转换为int型数据 通过赋值方式将char类型变量转换为int型变量 xff0c 变量值为char类型变量的ASCII码值 例如 xff1a int a 61 0 那么打印a的结果为48 xff0c 如果想要得到正确的数字 xff0
  • ROS出现Cannot find source file的错误和add_dependencies,add_executable,target_link_libraries三者先后顺序不对所造成的错误。

    出现上面这个报错 xff0c 往往是 CMakeLists txt中的问题 add executable server tutorial ws src dynamic tutorials src server cpp 这行代码的问题 xff
  • 利用python ast包,绘制python代码的调用关系图(可分析互相调用的多个py文件)

    我的目的是辅助代码阅读 xff08 也方便写文档 xff09 xff0c 因此不需要太详细的信息 xff0c 只需要看用户定义的函数的函数调用关系 文章目录 1 开源项目staticfg的安装和直接使用2 绘制python的简单调用关系图
  • 1.3 Ubuntu18.04 ROS udp server 通信实现

    Ubuntu18 04 ROS udp Server通信实现 此小节介绍udp Server收发数据 udp通信属于帧传输 xff0c 在帧传输过程中对于消息的次序和到达情况没有需求 xff0c 没有进行校验 xff0c 所以UDP属于不可
  • 1.4 Ubuntu18.04 ROS udp Client通信实现

    Ubuntu18 04 ROS udp Client通信实现 此小节介绍udp Client收发数据 udp通信属于帧传输 xff0c 在帧传输过程中对于消息的次序和到达情况没有需求 xff0c 没有进行校验 xff0c 所以UDP属于不可
  • 1.5 Ubuntu18.04 ROS tcp/ip服务器与Android tcp/ip客户端通信

    Ubuntu18 04 ROS tcp ip服务器与Android tcp ip客户端通信 此小节介绍ubuntu18 04 ros tcp ip服务端与Android tcp ip客户端通信 xff0c 此操作可以使用安卓系统开发ROS机