【笔记】ROSjava-android控制ROS机器人——ROSjava与ROS构建的机器人设计综述

ROS学习笔记之——ROSAndroid 与 rosjava 之前博客已经介绍过一些在ROS系统上的Android环境的配置及项目的搭建。《ROS学习笔记之——基于ROS的Android开发》《基于linux系统安装Android Studio》本博文来学习一下其整体框架 目录 ROS Android 概述 ROSJAVA 概述 rosjava的构建环境 java Gradle Maven Catkin rosjava_core Ros Android 应用 RosActivity Android Interactions(交互) . 阅读详情

在看文章之前,请确定你已经熟悉了ROS和rosjava,并且具备基本的android开发经验

首先,放上视频:基于SLAM的室内自主导航服务机器人

这个机器人由上网本作为核心,在ubuntu上运行ROS系统,由android端辅助控制。这里主要将android的ROSjava部分,会在以后分篇详述。

第一篇,总体介绍ROSjava-android在这个机器人设计中发挥了怎么样的作用。这个android控制程序有如下功能:英文语音识别,能在脱机状况下语音控制机器人的基本运动;中文语音识别,语音控制并可以布置机器人任务(比如去某地区寻找某物体,和人对话等);最基本的按键控制和舵机控制


整个rosjava程序由主程序PocketSphinxROS.java、处理发送命令的dispose.java、IsrActivity.java中文语音识别、R开头的几个英文语音识别文件和Talk开头的几个负责发送各种命令的文件组成。这里就先介绍下PocketSphinxROS.java,为什么取这个名字,因为最开始主要为了开发PocketSphinx英文语音,后来功能增多名字也就没改。

package rosjava.wtf.pocketsphinx.version1;

import java.util.Date;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.SeekBar.OnSeekBarChangeListener;

import org.ros.address.InetAddressFactory;
import org.ros.android.MessageCallable;
import org.ros.android.RosActivity;
import org.ros.android.view.RosTextView;
import org.ros.node.NodeConfiguration;
import org.ros.node.NodeMainExecutor;

import rosjava.wtf.pocketsphinx.version1.IsrActivity;
import rosjava.wtf.pocketsphinx.version1.RecognitionListener;
import rosjava.wtf.pocketsphinx.version1.RecognizerTask;
import rosjava.wtf.pocketsphinx.version1.TalkChnString;
import rosjava.wtf.pocketsphinx.version1.TalkEnString;
import rosjava.wtf.pocketsphinx.version1.TalkParam;

import edu.cmu.pocketsphinx.demo.R;

public class PocketSphinxROS extends RosActivity implements OnTouchListener, RecognitionListener {

  private RosTextView<std_msgs.String> rosTextView;
  private TalkParam talker;
  private TalkEnString talkerenstring;
  private TalkChnString talkerchnstring;
  private TalkServo talkerserver;
  private TalkObject talkerobject;
  public Button forward,back,right,left,stop,btn_isr_demo,revive;
  public static boolean send=false,sendenstring=false,sendchnstring=false,sendservo=true,sendobject=false;
  public Handler handler = new Handler(){};
  //servo
  public TextView Value01,Value02;
  public static SeekBar servo1;
  public static SeekBar servo2;
  
  public PocketSphinxROS() {
    // The RosActivity constructor configures the notification title and ticker
    // messages.
    super("Pubsub Tutorial", "Pubsub Tutorial");
  }
//*pocketsphinx***************************************************************************************

  static {
    System.loadLibrary("pocketsphinx_jni");
  }
  /**
   * Recognizer task, which runs in a worker thread.
   */
  RecognizerTask rec;
  /**
   * Thread in which the recognizer task runs.
   */
  Thread rec_thread;
  /**
   * Time at which current recognition started.
   */
  Date start_date;
  /**
   * Number of seconds of speech.
   */
  float speech_dur;
  /**
   * Are we listening?
   */
  boolean listening;
  /**
   * Progress dialog for final recognition.
   */
  ProgressDialog rec_dialog;
  /**
   * Performance counter view.
   */
  static TextView performance_text;
  /**
   * Editable text view.
   */

  public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
      start_date = new Date();
      this.listening = true;
      this.rec.start();
      break;
    case MotionEvent.ACTION_UP:
      if (this.listening) {
        Log.d(getClass().getName(), "Showing Dialog");
        this.rec_dialog = ProgressDialog.show(this, "", "Recognizing speech...", true);
        this.rec_dialog.setCancelable(false);
        this.listening = false;
      }
      this.rec.stop();
      break;
    default:
      ;
    }
    /* Let the button handle its own state */
    return false;
  }
//****************************************************************************************
  @SuppressWarnings("unchecked")
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    rosTextView = (RosTextView<std_msgs.String>) findViewById(R.id.text);
    rosTextView.setTopicName("recognizer/output");
    rosTextView.setMessageType(std_msgs.String._TYPE);
    rosTextView.setMessageToStringCallable(new MessageCallable<String, std_msgs.String>() {
      @Override
      public String call(std_msgs.String message) {
        return message.getData();
      }
    });
    this.rec = new RecognizerTask();
    this.rec_thread = new Thread(this.rec);
    this.listening = false;
    Button voice = (Button) findViewById(R.id.Voice);
    voice.setOnTouchListener(this);
    performance_text = (TextView) findViewById(R.id.PerformanceText); 
    this.rec.setRecognitionListener(this);
    this.rec_thread.start();
    
    forward = (Button)findViewById(R.id.forward);
    back = (Button)findViewById(R.id.back);
    right = (Button)findViewById(R.id.right);
    left = (Button)findViewById(R.id.left);
    stop = (Button)findViewById(R.id.stop);
    revive = (Button)findViewById(R.id.revive);
    btn_isr_demo=(Button)findViewById(R.id.btn_isr_demo);
    
    Value01 = (TextView)findViewById(R.id.value1);
    Value02 = (TextView)findViewById(R.id.value2);
    final SeekBar servo1 = (SeekBar)findViewById(R.id.servo1); //左右
    final SeekBar servo2 = (SeekBar)findViewById(R.id.servo2); //上下
    servo1.setMax(180);
    servo1.setProgress(73);
    servo2.setMax(150);
    servo2.setProgress(145);
    
    forward.setOnTouchListener(new OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
          if (event.getAction() == MotionEvent.ACTION_DOWN)
          {
        	  dispose.control("forward");
			send=true;
          }
          else if(event.getAction() == MotionEvent.ACTION_UP)
          {
        	  send=false;
        	  sendenstring=true;
        	  sendchnstring=true;
          }
         return false;
         }
          });
    back.setOnTouchListener(new OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
          if (event.getAction() == MotionEvent.ACTION_DOWN)
          {
        	  dispose.control("back");
			 send=true;
          }
          else if(event.getAction() == MotionEvent.ACTION_UP)
          {
        	  send=false;
        	  sendenstring=true;
        	  sendchnstring=true;
          }
         return false;
         }
          });
    left.setOnTouchListener(new OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
          if (event.getAction() == MotionEvent.ACTION_DOWN)
          {
			dispose.control("left");
			send=true;
          }
          else if(event.getAction() == MotionEvent.ACTION_UP)
          {
        	  send=false;
        	  sendenstring=true;
        	  sendchnstring=true;
          }
         return false;
         }
          });
    right.setOnTouchListener(new OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
          if (event.getAction() == MotionEvent.ACTION_DOWN)
          {
        	  dispose.control("right");
			send=true;
          }
          else if(event.getAction() == MotionEvent.ACTION_UP)
          {
        	  send=false;
        	  sendenstring=true;
        	  sendchnstring=true;
          }
         return false;
         }
          });
       stop.setOnTouchListener(new OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
          if (event.getAction() == MotionEvent.ACTION_DOWN)
          {
        	  dispose.control("stop");
			send = false;				
          }
          else if(event.getAction() == MotionEvent.ACTION_UP)
          {
        	  sendenstring=true;
        	  sendchnstring=true;
          }
         return false;
         }
          });
       btn_isr_demo.setOnTouchListener(new OnTouchListener(){
           @Override
           public boolean onTouch(View v, MotionEvent event) {
             if (event.getAction() == MotionEvent.ACTION_DOWN)
             {
             }
             else if(event.getAction() == MotionEvent.ACTION_UP)
             {
     			Intent intent = new Intent();
     			intent.setClass(PocketSphinxROS.this,IsrActivity.class);
            	 startActivity(intent);
             }
            return false;
            }
             });
       revive.setOnTouchListener(new OnTouchListener(){
           @Override
           public boolean onTouch(View v, MotionEvent event) {
             if (event.getAction() == MotionEvent.ACTION_DOWN)
             {
            	 dispose.control("revive");
             }
             else if(event.getAction() == MotionEvent.ACTION_UP)
             {
           	  send=false;
         	 servo1.setProgress(73);
         	 servo2.setProgress(145);
             }
            return false;
            }
             });
       
       servo1.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
    	      @Override
    	      public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
    	      {
    	    	  if(progress > 150){
    	    	        Value01.setText("当前角度:" + 0.6 );
    	    	        TalkServo.pos[0]=0.6;
    	    	  }
    	    	  else{
    	    		  Value01.setText("当前角度:" + ((float)(progress-90)/100 ));
    	    		  TalkServo.pos[0]=(float)(progress-90)/100;
    			}
    			sendservo=true;
    	      }
    	      @Override
    	      public void onStartTrackingTouch(SeekBar seekBar)
    	      {
    	      }
    	      @Override
    	      public void onStopTrackingTouch(SeekBar seekBar)
    	      { 
    	      }   	      
    	    });
    	    
    	    servo2.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
    	      @Override
    	      public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser)
    	      {
    	        Value02.setText("当前角度:" +((float)(progress-75)/100));      	       
    	        TalkServo.pos[1]=(float)(progress-75)/100;
    			sendservo=true;
    	      }
    	      @Override
    	      public void onStartTrackingTouch(SeekBar seekBar)
    	      {
    	      }
    	      @Override
    	      public void onStopTrackingTouch(SeekBar seekBar)
    	      {
    	      }
    	      });
  }
    //Voice Control 
    /** Called when partial results are generated. */
    public void onPartialResults(Bundle b) {
      final String hyp = b.getString("hyp");
      handler.post(new Runnable() {
          public void run() {
            performance_text.setText(hyp);
          }
        });
    }

    /** Called with full results are generated. */
    public void onResults(Bundle b) {
		final String hyp = b.getString("hyp");
		final PocketSphinxROS that = this;
		  handler.post(new Runnable() {
			public void run() {
				performance_text.setText(hyp);
				dispose.control(hyp);
				sendenstring=true;
				send=true;
				Log.d(getClass().getName(), "Hiding Dialog");
				that.rec_dialog.dismiss();
			}
		});
	}

    public void onError(int err) {   
    }   
	@Override
	protected void init(NodeMainExecutor nodeMainExecutor) {
		// TODO Auto-generated method stub
	    talker = new TalkParam();
	    talkerenstring = new TalkEnString();
	    talkerchnstring = new TalkChnString();
	    talkerserver = new TalkServo();
	    talkerobject = new TalkObject();
	     NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic(InetAddressFactory.newNonLoopback().getHostAddress(), getMasterUri());
	     // 这里用户已经被提示输入master的URI来开始或启动本地master
	     nodeConfiguration.setMasterUri(getMasterUri());
	     nodeMainExecutor.execute(talker, nodeConfiguration);
	     nodeMainExecutor.execute(talkerenstring, nodeConfiguration);
	     nodeMainExecutor.execute(talkerchnstring, nodeConfiguration);
	     nodeMainExecutor.execute(talkerserver, nodeConfiguration);
	     nodeMainExecutor.execute(talkerobject, nodeConfiguration);
	     //  RosTextView作为显示输入信息是必须存在的
	     nodeMainExecutor.execute(rosTextView, nodeConfiguration);
	   }	
}
打开程序首先是填写masterURI,告诉rosjava连接到哪个master上。然后进入这个简陋的操作界面。其中有前后左右的基本命令按钮,2个舵机控制滑条,英文识别语音按钮和跳转到中文语音识别activity的按钮。

开发过pocketsphinx语音识别的一定很熟悉其中部分代码,这个是pocketsphinx的固定套路。中文语音我用了讯飞的引擎,联网的状况下效果很好。信息通道建立部分,我建了6个ROS节点,talker(TalkParam)负责发送控制电机的参数命令,使用geometry_msgs/Twist格式。talkerchnstring(TalkChnString)负责发送中文语音识别信息到PC的ROS,使用std_msgs.String._TYPE格式。talkerenstring(TalkEnString)负责发送英文语音识别信息。这里要说明,中文使用讯飞是需要联网才能识别的,而英文pocketsphinx是可以脱机小范围语音识别,用于应对恶劣情况(没网络)。talkerserver(TalkServo)是负责发送控制舵机的命令,使用sensor_msgs/JointState格式。talkerobject(TalkObject)负责把需要寻找的物体名发给机器人,使用std_msgs.String._TYPE格式。这里说明下,我们的机器人具有物体识别能力,通过发送物体名称给机器人,机器人就会明白自己的任务,然后去寻找该物体。

总结,以上代码是由3部分组成:RosActivity中固定格式,包括master连接和节点以及主题的建立;各个功能按键的设定;pocketsphinx英文语音。详细的请看后续文章。



by:season

ROS学习笔记之——基于ROS的Android开发 之前博客已经介绍了在linux下安装Android studio《基于linux系统安装Android Studio》,同时也实现了用手机控制turtlebot3的移动。本博文来系统性的学习一下Android与ROS联合开发~ ROSJAVA ROSjava为ros在java中的通信提供了一个客户端库,以及一系列的核心工具及驱动 ROSAndroid 参考资料 http://wiki.ros.org/rosjava http://... 阅读详情

相关推荐

ROS机器人控制新姿势:用旧手机打造低成本Android遥控器(基于rosjava_core)

本文详细介绍了如何利用闲置Android手机和ROSJava库,打造一个低成本、高集成的ROS机器人遥控器。通过rosjava_core构建Android ROS节点,实现与ROS主机的Wi-Fi通信,并融合手机触摸屏、陀螺仪等传感器进行高级控制。文章提供了从环境搭建、核心通信到传感器融合的完整实践指南,为机器人开发提供了灵活、经济的交互解决方案。

weixin_29007809的博客 370

rosjava零散

笔者之前想在非ros环境下使用通信,了解到rosjava可以实现,不过后来换成了rosbridge,也搜集了一些rosjava的资料,放在这里供参考(没时间整理了,格式较乱请见谅)

gls_nuaa的博客 1870

Android Studio + ROS开发实战:5分钟搞定rosjava环境配置(附避坑指南)

本文为Android开发者提供了在Android Studio中快速配置rosjava开发环境的实战指南。通过清晰的Gradle依赖配置、核心代码示例和详细的避坑说明,帮助开发者5分钟内连接ROS网络,实现Android设备与ROS系统的通信,并涵盖自定义消息、后台服务等进阶内容。

rr23456的博客 504

ROS_java源码编译开发android APP项目

ROS官方源码编译安卓APP项目

qq_45787306的博客 1983

ROSAndroid与rosjava实战:从环境搭建到机器人交互开发

本文详细介绍了ROSAndroid与rosjava的实战开发,从环境搭建到机器人交互开发的全流程。通过Gradle配置技巧、RosActivity深度定制及机器人交互开发进阶内容,帮助开发者快速掌握在Android设备上实现机器人控制的技术要点。特别适合想要利用旧手机改造为机器人遥控器或开发跨平台机器人监控APP的开发者。

weixin_29011239的博客 317

ROS与Android的结合:编程与实践指南

本文将详细介绍如何在ROS网络中运行和控制机器人,以及如何通过Android设备与ROS机器人进行交互。首先,解释了如何加载和运行MATLAB应用程序,并确保与ROS机器人成功连接。接着,深入探讨了Android与ROS接口的重要性,以及如何利用这种接口扩展机器人的功能。文章还提供了安装Android-ROS接口的方法,包括从Ubuntu包管理器和源代码安装,以及设置android-sdk的步骤。

weixin_42430341的博客 833

Rossum--ROSjava-android控制ROS机器人

From:http://blog.csdn.net/f_season/article/details/9177545 在看文章之前,请确定你已经熟悉了ROS和rosjava,并且具备基本的android开发经验 这个机器人由上网本作为核心,在ubuntu上运行ROS系统,由android端辅助控制。这里主要将android的ROSjava部分,会在以后分篇详述。 第一篇,总体

WTFRobot的专栏 5005

ROS机器人安卓遥控App完整工程包:含Java源码、Gradle构建配置与签名密钥路径

一套开箱即用的ROS机器人Android控制应用工程,用Java编写,兼容主流ROS通信协议,能连接ROS主节点实现移动机器人遥控、传感器数据订阅和控制指令发布。项目已配置好Android Studio开发环境所需全部文件:包括build.gradle、settings.gradle、gradlew脚本,以及Gradle 4.10.3/5.1.1/5.4版本适配声明;同时包含IDE配置文件(workspace.xml、compiler.xml、modules.xml等)和已编译好的diego-robot.a

m2n3b4v5c6的博客 197

android app控制ros机器人一

android app控制ros机器人,本节主要记录找到合适的资源及熟悉使用过错,后续会记录二次开发

qq_38988221的博客 2913

ros2_java_examples:ROS2 Java绑定的示例Java应用程序

ROS2 Java示例 这是使用ROS2的Java绑定的示例的集合 从于2016年11月1日 话题 Listener.java :聊天侦听器。 ListenerBestEffort.java :颤动侦听器(传感器类型)。 Talker.java说话者。 TalkerBestEffort.java说话者(传感器类型)。 ImuListener.java传感器侦听器。 服务 AddTwoIntServer.java :添加两个int服务提供者。 AddTwoIntClient.java :添加两个int服务使用者。 参数 ListParameters.java :列表参数。 ParameterEvents.java :测试参数事件(更改时) SetAndGetParameters.java :设置和获取参数。

ros2_java:ROS2的Java和Android绑定

Java的ROS2 建造状态 目标 状态 Ubuntu Xenial(OpenJDK) Ubuntu Xenial(Android) 介绍 这是一组项目(绑定,代码生成器,示例等),使开发人员能够为JVM和Android编写ROS2应用程序。 除了该存储库本身之外,还有: ,它为Ament添加了对Gradle的支持 ,一个Gradle插件,可以更轻松地在Java和Android项目中使用ROS2。 可以从Gradle Central 安装Gradle插件 运行时环境的示例 ,适用于Android的示例 仅此Java吗? 不可以,任何针对JVM的语言都可以用来编写ROS2应用程序。 包括Android吗? 是的确保将Fast-RTPS用作DDS供应商,至少使用。 产品特点 当前的功能集包括: 生成所有内置和复杂的ROS类型,包括数组,字符串,嵌套类型,常量等。 支持发布者和订阅 可调整的服务质量(例如,有损网络,可靠的交付等) 客户与服务 计时器 组成(即每个进程一个以上的节点) 时间处理(系统且稳定,尚不支持ROS时间 ) 支援Android 参数服务和客户

ROSBridge简介以及理解使用

安卓与ROS通信的现状 因为ROS官方支持的语言绑定只有C++和Python,所以目前安卓想与ROS通信,必须借助半官方的rosjava包,而Rosjava太重了,因为它跟C++/Python一样,是一个全功能的ROS绑定,意即你可以在Java(android)平台上创建Master Node,然后其他Node(C++/Python)可以连上这个Master,进行分布式通信!这对于桌面Java或许......

lovely_yoshino的博客 3万+

ros2_java:机器人操作系统,java绑定

rcljava-Java / JVM语言的ROS2客户端(Alfred变体) 平台 Linux(Debian) Linux(ubuntu) 苹果系统 视窗 的OpenJDK 安卓 这是什么? 这是一组项目(绑定,代码生成器,示例等),使开发人员能够使用rosjava(ROS1)设计为JVM和Android编写ROS2应用程序。 2016年12月27日从esteve / ros2_java分叉 如何使用 开始=> Wiki API规范 API规范是由javadoc生成的,您可以手动运行javadoc来自己创建它们。 要访问在线版本,请在浏览器中导航到https://ros2-java-alfred.readthedocs.io/en/latest/ 。 贡献 如果要为该项目贡献代码,则首先需要派生该项目。 下一步是发送拉取请求(PR)进行审查。 PR将由项目团队成员进行审查

ROSjava探索(更新完结)

rosjava 资料 关于rosjava的东西,我的目标是能够做成一个界面, https://github.com/rosjava 然后这个地方里面是那些代码的 地方,像界面这种东西看起来应该会方便很多。 https://github.com/rosjava/android_apps 这个人的rosjava的还是不粗的 http://blog.csdn.net/f_season/arti

DavidHan008 7655

rosjava_core:支持 Android 的纯 Java ROS 实现

rosjava 是第一个纯 Java 的 ROS 实现。 来自 :ROS 是一个用于机器人的开源元操作系统。 它提供了您期望从操作系统获得的服务,包括硬件抽象,低级设备控制,常用功能的实现,进程之间的消息传递以及程序包管理。 rosjava 由 Google 与 Willow Garage 合作开发,能够集成 Android 和 ROS 兼容机器人。 该项目正在积极开发中,目前是 alpha 质量的软件。 请在报告错误和功能请求。 首先,请访问和页面以获取有关核心库和示例的文档。 另请访问 roswiki 和页面以获取更一般的 rosjava-android 信息。 还有问题吗? 查看 ros-users,使用标签“rosjava”将问题发布到 ,或加入 irc.oftc.net 上的 #ROS。 rosjava的公开宣布。 寻找一个机器人平台来尝试ROS,Android和云机

C/C++ 计算程序运行的时间

C/C++计算程序执行时间的方法,精度依次增加,推荐度也依次增加 1.#include <time.h> clock_t start, finish; double process_interval ; start=clock(); process(); //要计时的程序 finish=clock(); process_interval =(double)(finish-star...

stu_shanghui的博客 1013

SLAM导航机器人零基础实战系列:(八)高阶拓展——1.miiboo机器人安卓手机APP开发

SLAM+语音机器人DIY系列:(八)高阶拓展——1.miiboo机器人安卓手机APP开发 android要与ROS通讯,一种是基于rosbridge,另一种是基于rosjava库。 相关参考例子工程 rosbridge例子: https://github.com/hibernate2011/RosClient rosbridge(rosbridge_suite)是ros官方为开发者提供...

小虎哥哥爱学习-CSDN 3141

Zynq UltraScale+ MPSoC-dp14 standalone

EDID HDCP AR# 64652 How to port the DisplayPort 1.4 TX subsystem example to a custom board dp v2.1 example design color format change DisplayPort-DP接口知识

zhuxl24的博客 2668

Rossum--Android上ROS开发——android_core创建一个android应用

前面已经讲了很多android_core,rosjava的介绍,如果你配置好了android_core,接下来就可以开发rosjava-android程序了。 首先在eclipse下创建一个android程序,然后使用RosActivity,下面给出官方范例详细介绍。 RosActivity是所有ROS Android应用的基本类,我们给出android_tutorial_pubsub

WTFRobot的专栏 3238

机器学习中正则化项L1和L2的直观理解

正则化(Regularization) 机器学习中几乎都可以看到损失函数后面会添加一个额外项,常用的额外项一般有两种,一般英文称作ℓ1ℓ1\ell_1-norm和ℓ2ℓ2\ell_2-norm,中文称作L1正则化和L2正则化,或者L1范数和L2范数。 L1正则化和L2正则化可以看做是损失函数的惩罚项。所谓『惩罚』是指对损失函数中的某些参数做一些限制。对于线性回归模型,使用L1正则化的模型建叫做...

小平子的专栏 43万+

TI CC2642R蓝牙5.2模块实战:从零搭建智能门锁原型(附电路图)

本文详细介绍了如何基于TI CC2642R蓝牙5.2模块从零搭建智能门锁原型,涵盖硬件选型、低功耗配置、蓝牙安全交互等关键环节。通过CC2642R的高性能MCU和蓝牙5.2技术,开发者可实现低功耗、高安全性的智能门锁设计,并提供实用的电路图和PCB布局建议。

o5p6q的博客 104

【笔记】ROSjava-android控制ROS机器人——ROSjava消息发送的解密

通过前面一篇Android上ROS开发——android_core创建一个android应用 应该已经懂了怎么把消息发布给某主题,但是由于发送消息的格式不同,代码有些许改动。虽然通过eclipse可以自己琢磨出如何处理某消息格式下的数据,或者直接google ROS的格式,但是找起来还是有点麻烦,我这还是详细讲解下。 首先是最基本最简单的发送std_msg格式: package ros

F_season的专栏 6242

SAP 零售 FMS 物料主数据(一)

SAP 零售 FMS 物料主数据(一) SAP 对于鞋服行业最新的解决方案-FMS(相当于原来的AFS+Retail);更偏向与零售; 商品主数据与原来的AFS大不相同,取消了原来的Grid的网格概念,取而代之的是变式;商品主数据维护也偏向于Retail的维护模式;事物代码也不是MM01而是MM41 /MM46; 在维护商品主数据前,需要与商品部沟通定义各种商品相关的规范如编码规则,大中小类 ,颜色库,尺码库等,此处不赘述; 创建商品需要确定哪些物料是变式物料,哪些是常规不带特性的单一物料;这决定了在创建商

weixin_45518759的博客 5052
上一篇: 【笔记】Android上ROS开发——android_core创建一个android应用
下一篇: 【笔记】ROSjava-android控制ROS机器人——ROSjava消息发送的解密
茶叽
博客等级 码龄14年 86粉丝 13原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值