lab 4

Dependencies:   BufferedSerial

Files at this revision

API Documentation at this revision

Comitter:
ccpjboss
Date:
Thu May 27 08:53:19 2021 +0000
Commit message:
tet

Changed in this revision

BufferedSerial.lib Show annotated file Show diff for this revision Revisions of this file
Communication.cpp Show annotated file Show diff for this revision Revisions of this file
Communication.h Show annotated file Show diff for this revision Revisions of this file
MessageBuilder.cpp Show annotated file Show diff for this revision Revisions of this file
MessageBuilder.h Show annotated file Show diff for this revision Revisions of this file
Robot.cpp Show annotated file Show diff for this revision Revisions of this file
Robot.h Show annotated file Show diff for this revision Revisions of this file
inc/rplidar_cmd.h Show annotated file Show diff for this revision Revisions of this file
inc/rplidar_protocol.h Show annotated file Show diff for this revision Revisions of this file
inc/rptypes.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
rplidar/RPlidar.cpp Show annotated file Show diff for this revision Revisions of this file
rplidar/rplidar.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BufferedSerial.lib	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/sam_grove/code/BufferedSerial/#7e5e866edd3d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Communication.cpp	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,43 @@
+#include "Communication.h"
+#include "mbed.h"
+#include "MessageBuilder.h"
+
+Serial *serial_object;
+MessageBuilder bin_msg;
+
+void init_communication(Serial *serial_in)
+{
+    serial_object = serial_in;
+}
+
+void write_bytes(char *ptr, unsigned char len)
+{
+    for(int i=0; i<len; i++)
+    {
+        serial_object->putc(ptr[i]);
+    }
+}
+
+void send_odometry(float x, float y, float theta)
+{
+    bin_msg.reset();
+    bin_msg.add('O');
+
+    bin_msg.add(x);
+    bin_msg.add(y);
+    bin_msg.add(theta);
+
+    write_bytes(bin_msg.message, bin_msg.length());
+}
+
+void send_map(int x, int y, float map)
+{
+    bin_msg.reset();
+    bin_msg.add('M');
+
+    bin_msg.add(x);
+    bin_msg.add(y);
+    bin_msg.add(map);
+
+    write_bytes(bin_msg.message, bin_msg.length());
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Communication.h	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,10 @@
+#ifndef COMMUNICATION_H
+#define COMMUNICATION_H
+
+#include "mbed.h"
+
+void init_communication(Serial *serial_in);
+void write_bytes(char *ptr, unsigned char len);
+void send_odometry(float x, float y, float theta);
+void send_map(int x, int y, float map);
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MessageBuilder.cpp	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,87 @@
+#include "MessageBuilder.h"
+#include "mbed.h"
+
+MessageBuilder::MessageBuilder() {
+	reset();
+}
+
+MessageBuilder::~MessageBuilder() {
+	// TODO Auto-generated destructor stub
+}
+
+char MessageBuilder::add(const void* data, size_t len) {
+	if (available() >= len) {
+		memcpy(_pointer, data, len);
+		_pointer += len;
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+void MessageBuilder::reset() {
+	message[0] = 0x06;
+	message[1] = 0x85;
+	_pointer = &message[2];
+}
+
+// Note: if message size grow beyond 32 bytes, return "size_t" insted, because it
+// is the most appropriate type for "sizeof" operator. Now, unsgined char is used
+// for memory economy.
+unsigned char MessageBuilder::available() {
+	return &message[max_len - 1] - _pointer + 1;
+}
+
+unsigned char MessageBuilder::length() {
+	return _pointer - &message[0];
+}
+
+char MessageBuilder::add(float data) {
+	if (available() >= sizeof(data)) {
+		memcpy(_pointer, &data, sizeof(data));
+		_pointer += sizeof(data);
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+char MessageBuilder::add(double data) {
+	if (available() >= sizeof(data)) {
+		memcpy(_pointer, &data, sizeof(data));
+		_pointer += sizeof(data);
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+char MessageBuilder::add(int data) {
+	if (available() >= sizeof(data)) {
+		memcpy(_pointer, &data, sizeof(data));
+		_pointer += sizeof(data);
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+char MessageBuilder::add(char data) {
+	if (available() >= sizeof(data)) {
+		memcpy(_pointer, &data, sizeof(data));
+		_pointer += sizeof(data);
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+char MessageBuilder::add(unsigned int data) {
+	if (available() >= sizeof(data)) {
+		memcpy(_pointer, &data, sizeof(data));
+		_pointer += sizeof(data);
+		return 0;
+	} else {
+		return 1;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MessageBuilder.h	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,30 @@
+#ifndef MESSAGEBUILDER_H_
+#define MESSAGEBUILDER_H_
+
+#include "mbed.h"
+
+class MessageBuilder
+{
+private:
+    static const char max_len = 32;
+    char *_pointer;
+
+public:
+    char message[max_len];
+
+    MessageBuilder();
+    virtual ~MessageBuilder();
+    char add(const void* data, size_t len);
+    char add(char data);
+    char add(float data);
+    char add(int data);
+    char add(double data);
+    char add(unsigned int data);
+    void reset();
+    unsigned char available();
+    unsigned char length();
+};
+
+#endif /* MESSAGEBUILDER_H_ */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Robot.cpp	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,63 @@
+#include "Robot.h"
+#include "mbed.h"
+
+I2C i2c(I2C_SDA, I2C_SCL );
+const int addr8bit = 20 << 1; // 7bit I2C address is 20; 8bit I2C address is 40 (decimal).
+
+int16_t countsLeft = 0;
+int16_t countsRight = 0;
+
+void setSpeeds(int16_t leftSpeed, int16_t rightSpeed)
+{
+    char buffer[5];
+    
+    buffer[0] = 0xA1;
+    memcpy(&buffer[1], &leftSpeed, sizeof(leftSpeed));
+    memcpy(&buffer[3], &rightSpeed, sizeof(rightSpeed));
+
+    i2c.write(addr8bit, buffer, 5); // 5 bytes
+}
+
+void setLeftSpeed(int16_t speed)
+{
+    char buffer[3];
+    
+    buffer[0] = 0xA2;
+    memcpy(&buffer[1], &speed, sizeof(speed));
+
+    i2c.write(addr8bit, buffer, 3); // 3 bytes
+}
+
+void setRightSpeed(int16_t speed)
+{
+    char buffer[3];
+    
+    buffer[0] = 0xA3;
+    memcpy(&buffer[1], &speed, sizeof(speed));
+
+    i2c.write(addr8bit, buffer, 3); // 3 bytes
+}
+
+void getCounts()
+{
+    char write_buffer[2];
+    char read_buffer[4];
+    
+    write_buffer[0] = 0xA0;
+    i2c.write(addr8bit, write_buffer, 1); wait_us(100);
+    i2c.read( addr8bit, read_buffer, 4);
+    countsLeft = (int16_t((read_buffer[0]<<8)|read_buffer[1]));
+    countsRight = (int16_t((read_buffer[2]<<8)|read_buffer[3]));
+}
+
+void getCountsAndReset()
+{
+    char write_buffer[2];
+    char read_buffer[4];
+    
+    write_buffer[0] = 0xA4;
+    i2c.write(addr8bit, write_buffer, 1); wait_us(100);
+    i2c.read( addr8bit, read_buffer, 4);
+    countsLeft = (int16_t((read_buffer[0]<<8)|read_buffer[1]));
+    countsRight = (int16_t((read_buffer[2]<<8)|read_buffer[3]));
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Robot.h	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,49 @@
+/** @file */
+#ifndef ROBOT_H_
+#define ROBOT_H_
+
+#include "mbed.h"
+
+extern int16_t countsLeft;
+extern int16_t countsRight;
+
+/** \brief Sets the speed for both motors.
+ *
+ * \param leftSpeed A number from -300 to 300 representing the speed and
+ * direction of the left motor. Values of -300 or less result in full speed
+ * reverse, and values of 300 or more result in full speed forward.
+ * \param rightSpeed A number from -300 to 300 representing the speed and
+ * direction of the right motor. Values of -300 or less result in full speed
+ * reverse, and values of 300 or more result in full speed forward. */
+void setSpeeds(int16_t leftSpeed, int16_t rightSpeed);
+
+/** \brief Sets the speed for the left motor.
+ *
+ * \param speed A number from -300 to 300 representing the speed and
+ * direction of the left motor.  Values of -300 or less result in full speed
+ * reverse, and values of 300 or more result in full speed forward. */
+void setLeftSpeed(int16_t speed);
+
+/** \brief Sets the speed for the right motor.
+ *
+ * \param speed A number from -300 to 300 representing the speed and
+ * direction of the right motor. Values of -300 or less result in full speed
+ * reverse, and values of 300 or more result in full speed forward. */
+void setRightSpeed(int16_t speed);
+
+/*! Returns the number of counts that have been detected from the both
+ * encoders.  These counts start at 0.  Positive counts correspond to forward
+ * movement of the wheel of the Romi, while negative counts correspond
+ * to backwards movement.
+ *
+ * The count is returned as a signed 16-bit integer.  When the count goes
+ * over 32767, it will overflow down to -32768.  When the count goes below
+ * -32768, it will overflow up to 32767. */
+void getCounts();
+
+/*! This function is just like getCounts() except it also clears the
+ *  counts before returning.  If you call this frequently enough, you will
+ *  not have to worry about the count overflowing. */
+void getCountsAndReset();
+
+#endif /* ROBOT_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/rplidar_cmd.h	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, RoboPeak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ *  RoboPeak LIDAR System
+ *  Data Packet IO packet definition for RP-LIDAR
+ *
+ *  Copyright 2009 - 2014 RoboPeak Team
+ *  http://www.robopeak.com
+ *
+ */
+
+
+#pragma once
+#include "rptypes.h"
+#include "rplidar_protocol.h"
+
+// Commands
+//-----------------------------------------
+
+// Commands without payload and response
+#define RPLIDAR_CMD_STOP               0x25
+#define RPLIDAR_CMD_SCAN               0x20
+#define RPLIDAR_CMD_FORCE_SCAN         0x21
+#define RPLIDAR_CMD_RESET              0x40
+
+
+// Commands without payload but have response
+#define RPLIDAR_CMD_GET_DEVICE_INFO      0x50
+#define RPLIDAR_CMD_GET_DEVICE_HEALTH    0x52
+
+#if defined(_WIN32)
+#pragma pack(1)
+#endif
+
+
+// Response
+// ------------------------------------------
+#define RPLIDAR_ANS_TYPE_MEASUREMENT      0x81
+
+#define RPLIDAR_ANS_TYPE_DEVINFO          0x4
+#define RPLIDAR_ANS_TYPE_DEVHEALTH        0x6
+
+
+#define RPLIDAR_STATUS_OK                 0x0
+#define RPLIDAR_STATUS_WARNING            0x1
+#define RPLIDAR_STATUS_ERROR              0x2
+
+#define RPLIDAR_RESP_MEASUREMENT_SYNCBIT        (0x1<<0)
+#define RPLIDAR_RESP_MEASUREMENT_QUALITY_SHIFT  2
+#define RPLIDAR_RESP_MEASUREMENT_CHECKBIT       (0x1<<0)
+#define RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT    1
+
+typedef struct _rplidar_response_measurement_node_t {
+    _u8    sync_quality;      // syncbit:1;syncbit_inverse:1;quality:6;
+    _u16   angle_q6_checkbit; // check_bit:1;angle_q6:15;
+    _u16   distance_q2;
+} __attribute__((packed)) rplidar_response_measurement_node_t;
+
+typedef struct _rplidar_response_device_info_t {
+    _u8   model;
+    _u16  firmware_version;
+    _u8   hardware_version;
+    _u8   serialnum[16];
+} __attribute__((packed)) rplidar_response_device_info_t;
+
+typedef struct _rplidar_response_device_health_t {
+    _u8   status;
+    _u16  error_code;
+} __attribute__((packed)) rplidar_response_device_health_t;
+
+#if defined(_WIN32)
+#pragma pack()
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/rplidar_protocol.h	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, RoboPeak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ *  RoboPeak LIDAR System
+ *  Data Packet IO protocol definition for RP-LIDAR
+ *
+ *  Copyright 2009 - 2014 RoboPeak Team
+ *  http://www.robopeak.com
+ *  
+ */
+//#ifndef RPLIDAR_PROTOCOL_H
+//#define RPLIDAR_PROTOCOL_H
+
+#pragma once
+
+// RP-Lidar Input Packets
+
+#define RPLIDAR_CMD_SYNC_BYTE        0xA5
+#define RPLIDAR_CMDFLAG_HAS_PAYLOAD  0x80
+
+
+#define RPLIDAR_ANS_SYNC_BYTE1       0xA5
+#define RPLIDAR_ANS_SYNC_BYTE2       0x5A
+
+#define RPLIDAR_ANS_PKTFLAG_LOOP     0x1
+
+
+#if defined(_WIN32)
+#pragma pack(1)
+#endif
+
+typedef struct _rplidar_cmd_packet_t {
+    _u8 syncByte; //must be RPLIDAR_CMD_SYNC_BYTE
+    _u8 cmd_flag; 
+    _u8 size;
+    _u8 data[0];
+} __attribute__((packed)) rplidar_cmd_packet_t;
+
+
+typedef struct _rplidar_ans_header_t {
+    _u8  syncByte1; // must be RPLIDAR_ANS_SYNC_BYTE1
+    _u8  syncByte2; // must be RPLIDAR_ANS_SYNC_BYTE2
+    _u32 size:30;
+    _u32 subType:2;
+    _u8  type;
+} __attribute__((packed)) rplidar_ans_header_t;
+
+#if defined(_WIN32)
+#pragma pack()
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/rptypes.h	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2014, RoboPeak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+ * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ *  RoboPeak LIDAR System
+ *  Common Types definition
+ *
+ *  Copyright 2009 - 2014 RoboPeak Team
+ *  http://www.robopeak.com
+ * 
+ */
+
+#pragma once
+
+
+#ifdef _WIN32
+
+//fake stdint.h for VC only
+
+typedef signed   char     int8_t;
+typedef unsigned char     uint8_t;
+
+typedef __int16           int16_t;
+typedef unsigned __int16  uint16_t;
+
+typedef __int32           int32_t;
+typedef unsigned __int32  uint32_t;
+
+typedef __int64           int64_t;
+typedef unsigned __int64  uint64_t;
+
+#else
+
+#include <stdint.h>
+
+#endif
+
+
+//based on stdint.h
+typedef int8_t         _s8;
+typedef uint8_t        _u8;
+
+typedef int16_t        _s16;
+typedef uint16_t       _u16;
+
+typedef int32_t        _s32;
+typedef uint32_t       _u32;
+
+typedef int64_t        _s64;
+typedef uint64_t       _u64;
+
+#define __small_endian
+
+#ifndef __GNUC__
+#define __attribute__(x)
+#endif
+
+
+// The _word_size_t uses actual data bus width of the current CPU
+#ifdef _AVR_
+typedef _u8            _word_size_t;
+#define THREAD_PROC    
+#elif defined (WIN64)
+typedef _u64           _word_size_t;
+#define THREAD_PROC    __stdcall
+#elif defined (WIN32)
+typedef _u32           _word_size_t;
+#define THREAD_PROC    __stdcall
+#elif defined (__GNUC__)
+typedef unsigned long  _word_size_t;
+#define THREAD_PROC   
+#elif defined (__ICCARM__)
+typedef _u32            _word_size_t;
+#define THREAD_PROC  
+#endif
+
+
+typedef uint32_t u_result;
+
+#define RESULT_OK              0
+#define RESULT_FAIL_BIT        0x80000000
+#define RESULT_ALREADY_DONE    0x20
+#define RESULT_INVALID_DATA    (0x8000 | RESULT_FAIL_BIT)
+#define RESULT_OPERATION_FAIL  (0x8001 | RESULT_FAIL_BIT)
+#define RESULT_OPERATION_TIMEOUT  (0x8002 | RESULT_FAIL_BIT)
+#define RESULT_OPERATION_STOP    (0x8003 | RESULT_FAIL_BIT)
+#define RESULT_OPERATION_NOT_SUPPORT    (0x8004 | RESULT_FAIL_BIT)
+#define RESULT_FORMAT_NOT_SUPPORT    (0x8005 | RESULT_FAIL_BIT)
+#define RESULT_INSUFFICIENT_MEMORY   (0x8006 | RESULT_FAIL_BIT)
+
+#define IS_OK(x)    ( ((x) & RESULT_FAIL_BIT) == 0 )
+#define IS_FAIL(x)  ( ((x) & RESULT_FAIL_BIT) )
+
+typedef _word_size_t (THREAD_PROC * thread_proc_t ) ( void * );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,512 @@
+#include "mbed.h"
+#include "BufferedSerial.h"
+#include "rplidar.h"
+#include "Robot.h"
+#include "Communication.h"
+
+#define     D_EIXO          14.05   // Distancia entre rodas
+#define     D_RODA          7.0     // Raio da roda ( cm )
+#define     KV              10.0 //uperior a zero
+#define     KS              70.0  //superior a KV
+#define     KI              0.05   // superior a KV
+#define     D_ERRO          0.5     // cm
+#define     MAX_SPEED       70.0
+#define     MIN_MAX_SPEED   70.0
+#define     MIN_SPEED       50.0
+#define     DIST_STOP       8.0
+
+// Mapa
+#define     D_QUAD      5.0         // tamanho do quadrado ... cm
+#define     D_JANELA    70.0     // tamanho da janela ... cm (tem de ser multiplo impar de D_QUAD)
+#define     D_MAPAX     200.0      // comprimento mapa em x ... cm
+#define     D_MAPAY     200.0       // comprimento mapa em y ... cm
+#define     MAPBUFFER   5.0         // buffer de 5cm para cada direcao
+
+double  PI_val      = 3.14159265358979323846f;
+
+// Configuracao GPIO
+DigitalIn mybutton(USER_BUTTON);
+
+// Configuracao comunicacao
+Serial bt(PA_0, PA_1, 38400);               // Bluetooth
+Serial pc(SERIAL_TX, SERIAL_RX, 115200);    // USB
+
+// Lidar
+RPLidar lidar;
+BufferedSerial se_lidar(PA_9, PA_10);
+PwmOut rplidar_motor(D3);
+struct RPLidarMeasurement data;
+double  lidar_angle, lidar_dist;
+double  lidar_distMin = 7.5f;
+double  lidar_distMax = 200.0f;
+double  offSetLidarX = -2.8, offSetLidarY = -1.5, lidar_angRet = 1.1*PI_val/180.0;
+double  lidar_angleCs, lidar_angleSn, tMaxX, tMaxY, tDeltaX, tDeltaY;
+int     stepX, stepY;
+double  angDif, posDifX, posDifY;
+
+
+// Dados a modificar
+double  pos_x[]     = {30.0f,130.0f,30.0f,30.0f};
+double  pos_y[]     = {30.0f,130.0f,130.0f,30.0f};
+double  THETA_Start = 0.0f;
+
+// Periodos
+int     T_printOdo = 250; int flag_printOdo = 1;    // Periodo para print da odometria
+int     T_upOdo = 10;                           // Periodo para update dos Encoders
+
+// Variaveis Globais
+float  X           = 0.0f;
+float  Y           = 0.0f;
+float  THETA       = 0.0f;
+double  delta_D     = 0.0f;
+double  delta_TH    = 0.0f;
+double  goal_x, goal_y;
+double  v, w, phi, racio, df, delta_theta;
+double  DR_cm, DL_cm;
+int     lastEncR = -1, lastEncL = -1, cont, pos_cont = 1;
+int     w_e, w_d, dir_e, dir_d, sw_e, sw_d;
+int     size_pos;
+bool    running = true;
+double  thetaCs, thetaSn;
+
+// Mapa
+double  fca = 30; double fcr = 2000;
+float  mapa[42][42];
+int     t_mapax = floor((D_MAPAX + MAPBUFFER*2.0)/D_QUAD);
+int     t_mapay = floor((D_MAPAY + MAPBUFFER*2.0)/D_QUAD);
+int     xa, ya, x_janela, y_janela;
+double  frx, fry, da, delta_dax, delta_day, T_JANELA = D_JANELA/D_QUAD;         // tamanho da janela em quadrados (janela) ;
+double  delta_fx, delta_fy, fax, fay, Fx, Fy, x_prox, y_prox;
+double  erro, erro_int = 0;
+int     X_ind, Y_ind;
+double  exp_mapa;
+
+// Obstaculos
+double  obstX, obstY;
+int     obstX_ind, obstY_ind;
+    
+// Tempos
+uint32_t last_printOdo  = 0, now_time  = 0;    // Referencia do ultimo print
+uint32_t last_upOdo  = 0, t_control = 0;    // Referencia do ultimo print
+uint32_t last_upMap  = 0, t_map = 0;    // Referencia do ultimo updateMap
+uint32_t start_upLid = 0;                   // Referencia do ultimo print
+uint32_t last_printMap =0;
+Timer t;                                    // Variavel print
+
+// Declaracao de funcoes
+void start_system();
+void lidar_setUp();
+int  check_enc();
+void wait_user();
+void print_odo();
+void update_goal();
+void update_odo();
+void update_map(int, int);
+void update_control();
+void update_vel(double v, double w);
+void update_pos();
+void check_error();
+void shutdown_system();
+void print_mapa();
+
+int main(){
+    size_pos = sizeof(pos_x)/sizeof(pos_x[0]);
+    const double v = 175;
+    const double w = 4.5;
+    
+    start_system();
+    update_vel(v,w);
+    
+    /*while(running) {
+        now_time = t.read_ms();
+        t_control = now_time - last_upOdo;
+        if( t_control >= T_upOdo){
+            if(check_enc()){
+                update_odo();
+                update_pos();
+                update_map(2, 2);
+                update_control();
+                update_vel();
+                check_error();
+                last_upOdo = now_time;
+            }
+        }
+        
+        now_time = t.read_ms();
+        if((now_time - last_printOdo >= T_printOdo) && (flag_printOdo)){
+            print_odo();
+            last_printOdo = now_time;
+        }
+    }*/
+    //shutdown_system();
+}
+
+void update_goal(){
+    goal_x = pos_x[pos_cont] + MAPBUFFER;
+    goal_y = pos_y[pos_cont] + MAPBUFFER;
+    pos_cont++;
+}    
+    
+void start_system(){
+    init_communication(&pc);
+    
+    X = pos_x[0] + MAPBUFFER;
+    Y = pos_y[0] + MAPBUFFER;
+    THETA = THETA_Start;
+
+    update_goal();
+    
+    pc.printf("Robo Speed to Zero...\n");
+    setSpeeds(0, 0);
+    pc.printf(" Done!\n");
+
+    pc.printf("Initiating Lidar...\n");
+    lidar_setUp();
+    pc.printf(" Done!\n");
+    
+    wait_user();
+    
+    pc.printf("START\n");
+    pc.printf("LAB3\n");
+    pc.printf("VFF\n");
+    
+    char str[100], str2[10];
+    for(int posInt = 1; posInt < size_pos; posInt++){
+        sprintf(str2,"/%.2f/%2.f", pos_x[posInt], pos_y[posInt]);
+        strcat(str, str2);
+    }
+    pc.printf("%.2f/%.2f/%.2f%s/%.2f/%.2f/%.2f/%.2f/%.2f/%.2f \n", pos_x[0], pos_y[0], THETA_Start, str, KV, KS, KI, DIST_STOP, fca, fcr);
+    
+    pc.printf("BEGIN\n");
+    
+    pc.printf("Lidar Speed to 100%%...\n");
+    //rplidar_motor.write(0.35f);
+    //pc.printf(" Done!\n");
+    
+    pc.printf("Stabilizing for 0.7 Second...\n");
+    wait(0.7);
+    pc.printf(" Done!\n");
+    
+    pc.printf("Reseting Encoders...\n");
+    getCountsAndReset();
+    pc.printf(" Done!\n");
+    
+    print_odo();
+    
+    t.start();
+
+    pc.printf("Updating Map with 250 Measures...\n");
+    last_upMap = t.read_ms();
+    //update_map(2, 700);
+    t_map = t.read_ms() - last_upMap;
+    pc.printf(" Done! %f\n", t_map/250.0);
+}
+
+void lidar_setUp(){
+    // Lidar initialization
+
+    rplidar_motor.period(0.01f);
+    lidar.begin(se_lidar);
+    lidar.setAngle(0,360);
+    lidar.startThreadScan();
+    rplidar_motor.write(0.0f);
+}
+
+int check_enc(){
+    
+    getCountsAndReset(); // Obtem encoder e reset encoder 
+    //pc.printf("%d %d ", countsRight, countsLeft);
+    if(!(abs(countsRight) == 1 && countsLeft == 255)){
+        lastEncR = countsRight;
+        lastEncL = countsLeft;
+        //pc.printf("|1| %d %d\n\r", countsRight, countsLeft);
+        return 1;
+    }else{
+        if(lastEncR == -1 && lastEncL == -1){
+            //pc.printf("|2| %d %d\n\r", countsRight, countsLeft);
+            return 0;
+        }else{
+            countsRight = lastEncR;
+            countsLeft = lastEncL;
+            //pc.printf("|3| %d %d\n\r", countsRight, countsLeft);    
+            return 1;
+        }
+    }
+ }
+ 
+void update_odo(){  
+    
+    DR_cm = (double)countsRight * ((D_RODA*PI_val)/1440.0);
+    DL_cm = (double)countsLeft * ((D_RODA*PI_val)/1440.0);
+    
+    delta_D = (DR_cm + DL_cm)/2.0; 
+    delta_TH = (DR_cm - DL_cm)/D_EIXO;
+    delta_TH = atan2(sin(delta_TH), cos(delta_TH));
+}
+
+void update_pos(){
+    if(delta_TH == 0){
+        X = X + delta_D * cos(THETA);
+        Y = Y + delta_D * sin(THETA);
+    }else{
+        X = X + delta_D*sin(delta_TH/2.0)*cos(THETA+delta_TH/2.0)/(delta_TH/2.0);
+        Y = Y + delta_D*sin(delta_TH/2.0)*sin(THETA+delta_TH/2.0)/(delta_TH/2.0);
+        THETA += delta_TH;
+        THETA = atan2(sin(THETA), cos(THETA));
+    }
+}
+
+void update_map(int update_mode, int qnt){
+    // update_mode = 1 -> Timer
+    // update_mode = 2 -> Contador
+    
+    X_ind = (int)floor(X/D_QUAD);   // Indice célula posicao X
+    Y_ind = (int)floor(Y/D_QUAD);   // Indice célula posicao Y
+    
+    thetaCs = cos(THETA);
+    thetaSn = sin(THETA);
+    mapa[X_ind][Y_ind] -= 0.65;     // Posição inicial está livre
+
+    cont = 0;
+    start_upLid = t.read_ms();
+      while((cont < qnt)){  
+        if(lidar.pollSensorData(&data)==0){
+            X_ind = (int)floor(X/D_QUAD);   // Indice célula posicao X
+            Y_ind = (int)floor(Y/D_QUAD);   // Indice célula posicao Y
+            
+            lidar_dist = (double) data.distance/10.0;
+            lidar_angle = (double) data.angle;
+            if((lidar_dist > lidar_distMin) && (lidar_dist < lidar_distMax)){
+
+                lidar_angle = lidar_angle*PI_val/180.0 ;
+                
+                obstX = X + offSetLidarX*thetaCs - offSetLidarY*thetaSn - lidar_dist*sin(lidar_angRet - THETA + lidar_angle);
+                obstY = Y + offSetLidarY*thetaCs + offSetLidarX*thetaSn - lidar_dist*cos(lidar_angRet - THETA + lidar_angle);
+                
+                posDifX = obstX - X;
+                posDifY = obstY - Y;
+                angDif = atan2(posDifY, posDifX);
+                lidar_angleCs = cos(angDif);
+                lidar_angleSn = sin(angDif);
+                
+                obstX_ind =  (int)floor(obstX/D_QUAD);
+                obstY_ind =  (int)floor(obstY/D_QUAD);
+                
+                if(obstX < X){
+                    stepX = -1;
+                }else{
+                    stepX = 1;
+                }
+                if(obstY < Y){
+                    stepY = -1;
+                }else{
+                    stepY = 1;
+                }
+
+                tMaxX = X;
+                tMaxY = Y;
+
+                while(1){
+                    // tDeltaX = (abs(((X_ind+1*(stepX>0))*D_QUAD) - tMaxX))/lidar_angleCs;
+                    // tDeltaY = (abs(((Y_ind+1*(stepY>0))*D_QUAD) - tMaxY))/lidar_angleSn;
+
+                    tDeltaX = (X_ind+1*(stepX>0))*D_QUAD;
+                    tDeltaY = (Y_ind+1*(stepY>0))*D_QUAD;
+                    tDeltaX = abs(tDeltaX - tMaxX);
+                    tDeltaY = abs(tDeltaY - tMaxY);
+                    tDeltaX = (tDeltaX)/lidar_angleCs;
+                    tDeltaY = (tDeltaY)/lidar_angleSn;
+
+                    if(abs(tDeltaX) < abs(tDeltaY)){
+                        X_ind += stepX;
+                        tMaxX = (X_ind+1*(stepX<0))*D_QUAD;
+                        tMaxY += tDeltaX*lidar_angleSn*stepX;
+                    }else{
+                        Y_ind += stepY;
+                        tMaxY = (Y_ind+1*(stepY<0))*D_QUAD;
+                        tMaxX += tDeltaY*lidar_angleCs*stepY;
+                    }
+                    //pc.printf("%d %d\n\r", X_ind, Y_ind);
+                    if((X_ind >= 0) && (X_ind < t_mapax) && (Y_ind >= 0) && (Y_ind < t_mapay)){
+                        if(X_ind == obstX_ind && Y_ind == obstY_ind){
+                            mapa[X_ind][Y_ind] += 0.65;
+                            //pc.printf("break\n\r");
+                            break;
+                        //}else if(X_ind == 0 || Y_ind == 0 || X_ind == t_mapax-1 || Y_ind == t_mapay-1 ){
+                        //    mapa[X_ind][Y_ind] += 0.65;
+                        }else{
+                            //pc.printf("livre\n\r");
+                            mapa[X_ind][Y_ind] -= 0.65;
+                        }
+                    }else{
+                        break;
+                    }
+                }
+                //pc.printf("%d\n",cont);
+                cont++;
+            }
+        }
+    }
+}
+
+void update_control(){
+    xa = (int)floor(X/D_QUAD);      // Indice célula posicao X
+    ya = (int)floor(Y/D_QUAD);      // Indice célula posicao Y
+
+    frx = 0; fry = 0;
+    x_janela = xa - floor(T_JANELA/2.0);
+    for(int i = 0; i < T_JANELA; i++){
+        y_janela = ya - floor(T_JANELA/2.0);
+        for(int j = 0; j < T_JANELA; j++){
+            
+            if((x_janela >= 0) && (x_janela < t_mapax) && (y_janela >= 0) && (y_janela < t_mapay)){
+
+                delta_dax = x_janela*D_QUAD;
+                delta_day = y_janela*D_QUAD;
+                
+                if(X >= delta_dax+D_QUAD){
+                    delta_dax = delta_dax+D_QUAD-X;
+                }else{
+                    delta_dax = delta_dax-X;
+                }
+                
+                if(Y >= delta_day+D_QUAD){
+                    delta_day = delta_day+D_QUAD-Y;
+                }else{
+                    delta_day = delta_day-Y;
+                }
+                
+                if(delta_dax == 0){
+                    delta_dax = 0.1;
+                }
+                if(delta_day == 0){
+                    delta_day = 0.1;
+                }
+
+                exp_mapa = 1-(1/(1+exp(mapa[x_janela][y_janela])));
+                if(exp_mapa <= 0.5){
+                    exp_mapa = 0;
+                }
+                
+                da = sqrt(pow(delta_dax,2)+pow(delta_day,2));
+                frx += fcr*exp_mapa*delta_dax/pow(da,3);
+                fry += fcr*exp_mapa*delta_day/pow(da,3);
+            }
+            y_janela ++;
+        }
+        x_janela ++;
+    }
+    
+    delta_fx = goal_x-X;
+    delta_fy = goal_y-Y;
+    
+    df = sqrt(pow(delta_fx,2)+pow(delta_fy,2));
+    
+    fax = fca*delta_fx/df;
+    fay = fca*delta_fy/df;
+    
+    Fx = fax - frx;
+    Fy = fay - fry;
+    
+    x_prox = X + Fx;
+    y_prox = Y + Fy;
+    
+    erro = sqrt(pow(x_prox-X,2)+pow(y_prox-Y,2))-D_ERRO;
+    erro_int = erro_int + erro;
+
+    phi = atan2((y_prox-Y), (x_prox-X));
+    delta_theta = atan2(sin(phi - THETA), cos(phi - THETA));
+    
+    v = KV*erro+KI*erro_int;
+    w = KS*delta_theta;
+}
+
+void update_vel(double v, double w){
+    
+    w_e = (v-(D_EIXO/2.0)*w)/(D_RODA/2.0);
+    w_d = (v+(D_EIXO/2.0)*w)/(D_RODA/2.0);
+
+    sw_e = w_e; 
+    sw_d = w_d;
+
+    if(abs(w_e) > MAX_SPEED || abs(w_d) > MAX_SPEED){
+        racio = fabs((double)w_e/w_d);
+        
+        if( w_e < 0 ) dir_e = -1; else dir_e = 1;
+        if( w_d < 0 ) dir_d = -1; else dir_d = 1;
+        
+        if(fabs(racio) >= 1.0){
+            sw_e = dir_e*MAX_SPEED;
+            sw_d = dir_d*MAX_SPEED/racio;
+        }else{
+            sw_e = dir_e*MAX_SPEED*racio;
+            sw_d = dir_d*MAX_SPEED;
+        }
+    }
+    if(abs(w_e) < MIN_SPEED || abs(w_d) < MIN_SPEED){
+        racio = fabs((double)w_e/w_d);
+        
+        if( w_e < 0 ) dir_e = -1; else dir_e = 1;
+        if( w_d < 0 ) dir_d = -1; else dir_d = 1;
+        
+        if(fabs(racio) >= 1.0){
+            if(MIN_SPEED*racio <= MIN_MAX_SPEED){
+                sw_e = dir_e*MIN_SPEED*racio;
+                sw_d = dir_d*MIN_SPEED;
+            }
+        }else{
+            if(MIN_SPEED/racio <= MIN_MAX_SPEED){
+                sw_e = dir_e*MIN_SPEED;
+                sw_d = dir_d*MIN_SPEED/racio;
+            }
+        }
+    }
+    
+    setSpeeds(sw_e, sw_d);
+}
+
+void check_error(){
+    if(df > DIST_STOP){
+        running = true;
+    }else{
+        if(pos_cont < size_pos){
+            //pc.printf("Goal Completed!\n");
+            //pc.printf("Changing Goal...\n");
+            update_goal();
+            //pc.printf(" Done!\n");
+            erro_int = 0;
+            running = true;
+        }else{
+            running = false;
+        }
+    }
+}
+
+void print_mapa(){
+    for( int xx = 0; xx < 42; xx++){
+        for( int yy = 0; yy < 42; yy++){
+            pc.printf("%d/%d/%.2f \n",xx,yy,mapa[xx][yy]);
+            wait(0.0001);
+        }
+    }
+}
+
+void print_odo(){
+    pc.printf("%.2f/%.2f/%.2f/%.2f/%.2f \n", X - MAPBUFFER, Y - MAPBUFFER, THETA, x_prox - MAPBUFFER, y_prox - MAPBUFFER);
+}
+
+void wait_user(){
+    pc.printf("Press UserButton to continue...\n");
+    while(mybutton);        // Espera por butao USER ser primido
+    pc.printf(" Done!\n");
+}
+
+void shutdown_system(){
+    setSpeeds(0,0);
+
+    rplidar_motor.write(0.0f);
+
+    print_mapa();
+    pc.printf("END!\n");
+    t.stop();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,1 @@
+https://github.com/armmbed/mbed-os/#51d55508e8400b60af467005646c4e2164738d48
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rplidar/RPlidar.cpp	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,591 @@
+/*
+ * RoboPeak RPLIDAR Driver for Arduino
+ * RoboPeak.com
+ *
+ * Copyright (c) 2014, RoboPeak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "rplidar.h"
+//BufferedSerial _bined_serialdev( PA_11,  PA_12); // tx, rx
+Timer timers;
+
+/*
+    Thread that handles reading the sensor measurements
+    
+    This thread parses the buffered serial bytes into Lidar measurements.
+    If there's space in the mail box it adds a measurement to it. In case there 
+    isn't space, it takes 1 element out of the mail box and then puts the new 
+    measurement. This makes sure recent data is in the mailbox instead of really 
+    old data. Messages are lost anyway but this way the application will read 
+    measurements of the current robot position.
+    if the mail box still has 100 max messages then this means that the oldest
+    measurement was 50ms in a full mail box. 
+    Note that since the thread runs every 20ms then there will be measurements 
+    as old as 20ms.
+*/
+void RPLidar::Thread_readSensor(void)
+{
+
+    //pc->printf("starting thread\n");
+    while(1)
+    {   
+    
+        mutex_measurements.lock();
+        while (IS_OK(pollPoint()))
+        {    
+            
+            currentMeasurement_fromThread = getCurrentPoint();
+            newMeasurement = 1;
+               
+          
+            /*if(!mail_box.full())
+            {            
+                struct RPLidarMeasurement current = getCurrentPoint();
+                struct RPLidarMeasurement *mail = mail_box.alloc();
+                if(mail == NULL)
+                {   
+                    //there was an error allocating space in heap
+                    continue;
+                }
+                mail->distance = current.distance;
+                mail->angle = current.angle;
+                mail->quality = current.quality;
+                mail->startBit = current.startBit;
+                
+                mail_box.put(mail);
+                
+            }
+            else
+            {
+                osEvent evt = mail_box.get();
+                if (evt.status == osEventMail) {
+                    struct RPLidarMeasurement *mail = (struct RPLidarMeasurement*)evt.value.p;
+                    mail_box.free(mail);
+                    
+                    struct RPLidarMeasurement current = getCurrentPoint();
+                    mail = mail_box.alloc();
+                    if(mail == NULL)
+                    {   
+                        //there was an error allocating space in heap
+                        continue;
+                    }
+                    mail->distance = current.distance;
+                    mail->angle = current.angle;
+                    mail->quality = current.quality;
+                    mail->startBit = current.startBit;
+                    
+                    mail_box.put(mail);
+                }
+                
+
+            }*/
+        }
+        mutex_measurements.unlock();    
+        wait_us(2000);
+    }   
+
+    
+}
+
+/*
+  Poll for new measurements in the mail box
+  Returns: 0 if found data, -1 if not data available.
+*/
+int32_t RPLidar::pollSensorData(struct RPLidarMeasurement *_data)
+{
+    
+    mutex_measurements.lock();
+    if(newMeasurement)
+    {
+        currentMeasurement_fromThread = getCurrentPoint();
+        _data->distance = currentMeasurement_fromThread.distance;
+        _data->angle = currentMeasurement_fromThread.angle;
+        _data->quality = currentMeasurement_fromThread.quality;
+        _data->startBit = currentMeasurement_fromThread.startBit;
+        newMeasurement = 0;
+        mutex_measurements.unlock();    
+        return 0;
+    }
+    mutex_measurements.unlock();    
+    
+    /*osEvent evt = mail_box.get();
+    if (evt.status == osEventMail) {
+        
+        struct RPLidarMeasurement *mail = (struct RPLidarMeasurement*)evt.value.p;
+        //struct RPLidarMeasurement data;
+        _data->distance = mail->distance;
+        _data->angle = mail->angle;
+        _data->quality = mail->quality;
+        _data->startBit = mail->startBit;
+        mail_box.free(mail);
+        return 0;
+
+        
+
+    }*/
+    
+    return -1;
+}
+
+
+RPLidar::RPLidar()
+{
+    
+
+    _currentMeasurement.distance = 0;
+    _currentMeasurement.angle = 0;
+    _currentMeasurement.quality = 0;
+    _currentMeasurement.startBit = 0;
+    
+    useThread = 0;
+    thread.set_priority(osPriorityAboveNormal);
+    //Thread thread(osPriorityAboveNormal, OS_STACK_SIZE, NULL, "RPLidar");
+    //thread_p = &thread;
+}
+
+
+RPLidar::~RPLidar()
+{
+    end();
+}
+
+// open the given serial interface and try to connect to the RPLIDAR
+/*
+bool RPLidar::begin(BufferedSerial &serialobj)
+{
+
+    //Serial.begin(115200);
+
+    if (isOpen()) {
+      end();
+    }
+    _bined_serialdev = &serialobj;
+  //  _bined_serialdev->end();
+    _bined_serialdev->baud(RPLIDAR_SERIAL_BAUDRATE);
+}
+*/
+
+void RPLidar::begin(BufferedSerial &serialobj)
+{
+    _bined_serialdev = &serialobj;
+    timers.start();
+    _bined_serialdev->baud(RPLIDAR_SERIAL_BAUDRATE);
+    recvPos_g = 0;
+}
+// close the currently opened serial interface
+void RPLidar::end()
+{/*
+    if (isOpen()) {
+       _bined_serialdev->end();
+       _bined_serialdev = NULL;
+    }*/
+}
+
+
+// check whether the serial interface is opened
+/*
+bool RPLidar::isOpen()
+{
+    return _bined_serialdev?true:false;
+}
+*/
+// ask the RPLIDAR for its health info
+
+u_result RPLidar::getHealth(rplidar_response_device_health_t & healthinfo, _u32 timeout)
+{
+    _u32 currentTs = timers.read_ms();
+    _u32 remainingtime;
+
+    _u8 *infobuf = (_u8 *)&healthinfo;
+    _u8 recvPos = 0;
+
+    rplidar_ans_header_t response_header;
+    u_result  ans;
+
+
+  //  if (!isOpen()) return RESULT_OPERATION_FAIL;
+
+    {
+        if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_DEVICE_HEALTH, NULL, 0))) {
+            return ans;
+        }
+
+        if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
+            return ans;
+        }
+
+        // verify whether we got a correct header
+        if (response_header.type != RPLIDAR_ANS_TYPE_DEVHEALTH) {
+            return RESULT_INVALID_DATA;
+        }
+
+        if ((response_header.size) < sizeof(rplidar_response_device_health_t)) {
+            return RESULT_INVALID_DATA;
+        }
+
+        while ((remainingtime=timers.read_ms() - currentTs) <= timeout) {
+            int currentbyte = _bined_serialdev->getc();
+            if (currentbyte < 0) continue;
+
+            infobuf[recvPos++] = currentbyte;
+
+            if (recvPos == sizeof(rplidar_response_device_health_t)) {
+                return RESULT_OK;
+            }
+        }
+    }
+    return RESULT_OPERATION_TIMEOUT;
+}
+// ask the RPLIDAR for its device info like the serial number
+u_result RPLidar::getDeviceInfo(rplidar_response_device_info_t & info, _u32 timeout )
+{
+    _u8  recvPos = 0;
+    _u32 currentTs = timers.read_ms();
+    _u32 remainingtime;
+    _u8 *infobuf = (_u8*)&info;
+    rplidar_ans_header_t response_header;
+    u_result  ans;
+
+  //  if (!isOpen()) return RESULT_OPERATION_FAIL;
+
+    {
+        if (IS_FAIL(ans = _sendCommand(RPLIDAR_CMD_GET_DEVICE_INFO,NULL,0))) {
+            return ans;
+        }
+
+        if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
+            return ans;
+        }
+
+        // verify whether we got a correct header
+        if (response_header.type != RPLIDAR_ANS_TYPE_DEVINFO) {
+            return RESULT_INVALID_DATA;
+        }
+
+        if (response_header.size < sizeof(rplidar_response_device_info_t)) {
+            return RESULT_INVALID_DATA;
+        }
+
+        while ((remainingtime=timers.read_ms() - currentTs) <= timeout) {
+            int currentbyte = _bined_serialdev->getc();
+            if (currentbyte<0) continue;
+            infobuf[recvPos++] = currentbyte;
+
+            if (recvPos == sizeof(rplidar_response_device_info_t)) {
+                return RESULT_OK;
+            }
+        }
+    }
+
+    return RESULT_OPERATION_TIMEOUT;
+}
+
+// stop the measurement operation
+u_result RPLidar::stop()
+{
+//    if (!isOpen()) return RESULT_OPERATION_FAIL;
+    u_result ans = _sendCommand(RPLIDAR_CMD_STOP,NULL,0);
+    return ans;
+}
+
+
+
+u_result RPLidar::startThreadScan()
+{
+    startScan();
+    useThread = true;
+    thread.start(callback(this, &RPLidar::Thread_readSensor));
+        
+    return RESULT_OK;
+}
+// start the measurement operation
+/*
+ This was altered to also start the thread that parses measurements in the background
+*/
+u_result RPLidar::startScan(bool force, _u32 timeout)
+{
+    //pc.printf("RPLidar::startScan\n");
+    u_result ans;
+
+//    if (!isOpen()) return RESULT_OPERATION_FAIL;
+
+    stop(); //force the previous operation to stop
+
+
+        ans = _sendCommand(force?RPLIDAR_CMD_FORCE_SCAN:RPLIDAR_CMD_SCAN, NULL, 0);
+        if (IS_FAIL(ans)) return ans;
+
+        // waiting for confirmation
+        rplidar_ans_header_t response_header;
+        if (IS_FAIL(ans = _waitResponseHeader(&response_header, timeout))) {
+            return ans;
+        }
+
+        // verify whether we got a correct header
+        if (response_header.type != RPLIDAR_ANS_TYPE_MEASUREMENT) {
+            return RESULT_INVALID_DATA;
+        }
+
+        if (response_header.size < sizeof(rplidar_response_measurement_node_t)) {
+            return RESULT_INVALID_DATA;
+        }
+        
+
+    return RESULT_OK;
+}
+
+// wait for one sample point to arrive
+/*
+    Do not use if startScan was called with starThread == 1!
+*/
+u_result RPLidar::waitPoint(_u32 timeout)
+{
+   
+   if(useThread)
+        return RESULT_OPERATION_NOT_SUPPORT;
+        
+   _u32 currentTs = timers.read_ms();
+   _u32 remainingtime;
+   rplidar_response_measurement_node_t node;
+   _u8 *nodebuf = (_u8*)&node;
+
+   _u8 recvPos = 0;
+
+   while ((remainingtime = timers.read_ms() - currentTs) <= timeout) {
+        int currentbyte = _bined_serialdev->getc();
+        if (currentbyte<0) continue;
+//Serial.println(currentbyte);
+        switch (recvPos) {
+            case 0: // expect the sync bit and its reverse in this byte          {
+                {
+                    _u8 tmp = (currentbyte>>1);
+                    if ( (tmp ^ currentbyte) & 0x1 ) {
+                        // pass
+                    } else {
+                        continue;
+                    }
+
+                }
+                break;
+            case 1: // expect the highest bit to be 1
+                {
+                    if (currentbyte & RPLIDAR_RESP_MEASUREMENT_CHECKBIT) {
+                        // pass
+                    } else {
+                        recvPos = 0;
+                        continue;
+                    }
+                }
+                break;
+          }
+          nodebuf[recvPos++] = currentbyte;
+          if (recvPos == sizeof(rplidar_response_measurement_node_t)) {
+              // store the data ...
+              _currentMeasurement.distance = node.distance_q2/4.0f;
+              _currentMeasurement.angle = (node.angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f;
+              _currentMeasurement.quality = (node.sync_quality>>RPLIDAR_RESP_MEASUREMENT_QUALITY_SHIFT);
+              _currentMeasurement.startBit = (node.sync_quality & RPLIDAR_RESP_MEASUREMENT_SYNCBIT);
+              ang = _currentMeasurement.angle;
+              dis = _currentMeasurement.distance;
+
+
+              if(ang>=angMin&&ang<=angMax)Data[ang] = dis;
+
+              return RESULT_OK;
+          }
+
+
+   }
+
+   return RESULT_OPERATION_TIMEOUT;
+}
+
+
+/*
+    This is very similar to waitPoint and it's only to be used by the thread, 
+    hence why it private.
+    
+    It checks for data in the buffered serial until it finds a message or there
+    are no more bytes. 
+    If it finds a message it returns RESULT_OK
+    If there are no more bytes it returns RESULT_OPERATION_TIMEOUT.
+    
+    The state of the parsing is saved so it can continue parsing a measurement
+    midway. (Note that does not mean it's re-entrant and should only be used
+    in the same context)
+*/
+u_result RPLidar::pollPoint()
+{
+   
+   //_u32 currentTs = timers.read_ms();
+   _u32 remainingtime;
+   //rplidar_response_measurement_node_t node;
+   _u8 *nodebuf = (_u8*)&(node_g);
+
+
+   int currentbyte;
+   while(_bined_serialdev->readable() > 0)
+   {
+   //while ((remainingtime = timers.read_ms() - currentTs) <= timeout) {
+        currentbyte = _bined_serialdev->getc();
+        //if (_bined_serialdev->readable() == 0) continue; 
+        //Serial.println(currentbyte);
+        switch (recvPos_g) {
+            case 0: // expect the sync bit and its reverse in this byte          {
+                {
+                    _u8 tmp = (currentbyte>>1);
+                    if ( (tmp ^ currentbyte) & 0x1 ) {
+                        // pass
+                        
+                    } else {
+                        continue;
+                    }
+
+                }
+                break;
+            case 1: // expect the highest bit to be 1
+                {
+                    if (currentbyte & RPLIDAR_RESP_MEASUREMENT_CHECKBIT) {
+                        // pass
+                    } else {
+                        recvPos_g = 0;
+                        continue;
+                    }
+                }
+                break;
+          }
+          nodebuf[recvPos_g++] = currentbyte;
+          if (recvPos_g == sizeof(rplidar_response_measurement_node_t)) {
+              recvPos_g = 0;
+              // store the data ...
+              _currentMeasurement.distance = node_g.distance_q2/4.0f;
+              _currentMeasurement.angle = (node_g.angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f;
+              _currentMeasurement.quality = (node_g.sync_quality>>RPLIDAR_RESP_MEASUREMENT_QUALITY_SHIFT);
+              _currentMeasurement.startBit = (node_g.sync_quality & RPLIDAR_RESP_MEASUREMENT_SYNCBIT);
+              ang = _currentMeasurement.angle;
+              dis = _currentMeasurement.distance;
+
+
+              if(ang>=angMin&&ang<=angMax)Data[ang] = dis;
+
+              return RESULT_OK;
+          }
+
+
+   }//while(_bined_serialdev->readable() > 0);
+
+   return RESULT_OPERATION_TIMEOUT;
+}
+
+
+void RPLidar::setAngle(int min,int max){
+  angMin = min;
+  angMax = max;
+}
+void RPLidar::get_lidar(){
+  if (!IS_OK(waitPoint())) startScan();
+}
+u_result RPLidar::_sendCommand(_u8 cmd, const void * payload, size_t payloadsize)
+{
+
+    rplidar_cmd_packet_t pkt_header;
+    rplidar_cmd_packet_t * header = &pkt_header;
+    _u8 checksum = 0;
+
+    if (payloadsize && payload) {
+        cmd |= RPLIDAR_CMDFLAG_HAS_PAYLOAD;
+    }
+
+    header->syncByte = RPLIDAR_CMD_SYNC_BYTE;
+    header->cmd_flag = cmd;
+
+    // send header first
+    _bined_serialdev->putc(header->syncByte );
+    _bined_serialdev->putc(header->cmd_flag );
+
+  //  _bined_serialdev->write( (uint8_t *)header, 2);
+
+    if (cmd & RPLIDAR_CMDFLAG_HAS_PAYLOAD) {
+        checksum ^= RPLIDAR_CMD_SYNC_BYTE;
+        checksum ^= cmd;
+        checksum ^= (payloadsize & 0xFF);
+
+        // calc checksum
+        for (size_t pos = 0; pos < payloadsize; ++pos) {
+            checksum ^= ((_u8 *)payload)[pos];
+        }
+
+        // send size
+        _u8 sizebyte = payloadsize;
+        _bined_serialdev->putc(sizebyte);
+      //  _bined_serialdev->write((uint8_t *)&sizebyte, 1);
+
+        // send payload
+    //    _bined_serialdev.putc((uint8_t )payload);
+    //    _bined_serialdev->write((uint8_t *)&payload, sizebyte);
+
+        // send checksum
+        _bined_serialdev->putc(checksum);
+      //  _bined_serialdev->write((uint8_t *)&checksum, 1);
+
+    }
+
+    return RESULT_OK;
+}
+
+u_result RPLidar::_waitResponseHeader(rplidar_ans_header_t * header, _u32 timeout)
+{
+    _u8  recvPos = 0;
+    _u32 currentTs = timers.read_ms();
+    _u32 remainingtime;
+    _u8 *headerbuf = (_u8*)header;
+    while ((remainingtime = timers.read_ms() - currentTs) <= timeout) {
+
+        int currentbyte = _bined_serialdev->getc();
+        if (currentbyte<0) continue;
+        switch (recvPos) {
+        case 0:
+            if (currentbyte != RPLIDAR_ANS_SYNC_BYTE1) {
+                continue;
+            }
+            break;
+        case 1:
+            if (currentbyte != RPLIDAR_ANS_SYNC_BYTE2) {
+                recvPos = 0;
+                continue;
+            }
+            break;
+        }
+        headerbuf[recvPos++] = currentbyte;
+
+        if (recvPos == sizeof(rplidar_ans_header_t)) {
+            return RESULT_OK;
+        }
+
+
+    }
+
+    return RESULT_OPERATION_TIMEOUT;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rplidar/rplidar.h	Thu May 27 08:53:19 2021 +0000
@@ -0,0 +1,118 @@
+/*
+ * RoboPeak RPLIDAR Driver for Arduino
+ * RoboPeak.com
+ *
+ * Copyright (c) 2014, RoboPeak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+#include "mbed.h"
+#include "inc/rptypes.h"
+#include "inc/rplidar_cmd.h"
+#include <BufferedSerial.h>
+//#include "../BufferedSerial/BufferedSerial.h"
+struct RPLidarMeasurement
+{
+    float distance;
+    float angle;
+    uint8_t quality;
+    bool  startBit;
+};
+
+class RPLidar
+{
+public:
+    enum {
+        RPLIDAR_SERIAL_BAUDRATE = 115200,
+        RPLIDAR_DEFAULT_TIMEOUT = 500,
+    };
+
+    void Thread_readSensor(void);
+    int32_t pollSensorData(struct RPLidarMeasurement *_data);
+    RPLidar(Serial *_pc);
+    RPLidar();
+    ~RPLidar();
+
+    // open the given serial interface and try to connect to the RPLIDAR
+    //bool begin(BufferedSerial &serialobj);
+    void begin(BufferedSerial &serialobj);
+    // close the currently opened serial interface
+    void end();
+
+    // check whether the serial interface is opened
+  //  bool isOpen();
+
+    // ask the RPLIDAR for its health info
+    u_result getHealth(rplidar_response_device_health_t & healthinfo, _u32 timeout = RPLIDAR_DEFAULT_TIMEOUT);
+
+    // ask the RPLIDAR for its device info like the serial number
+    u_result getDeviceInfo(rplidar_response_device_info_t & info, _u32 timeout = RPLIDAR_DEFAULT_TIMEOUT);
+
+    // stop the measurement operation
+    u_result stop();
+
+    // start the measurement operation
+    u_result startThreadScan();
+    u_result startScan(bool force = true, _u32 timeout = RPLIDAR_DEFAULT_TIMEOUT*2);
+
+
+    // wait for one sample point to arrive
+    u_result waitPoint(_u32 timeout = RPLIDAR_DEFAULT_TIMEOUT);
+
+    u_result _sendCommand(_u8 cmd, const void * payload, size_t payloadsize);
+    // retrieve currently received sample point
+    int Data[360];
+    int ang,dis;
+    int angMin,angMax;
+    void setAngle(int min,int max);
+    void get_lidar();
+    const RPLidarMeasurement & getCurrentPoint()
+    {
+        return _currentMeasurement;
+    }
+
+private:
+    _u8 recvPos_g;
+    rplidar_response_measurement_node_t node_g;
+    
+     //Thread *thread_p;
+    Thread thread;
+    //Mail<struct RPLidarMeasurement, 100> mail_box; //
+    Mutex mutex_measurements;
+    bool useThread;
+    
+    struct RPLidarMeasurement currentMeasurement_fromThread;
+    bool newMeasurement;
+    
+    u_result pollPoint();
+    //Serial *pc;
+protected:
+//    u_result _sendCommand(_u8 cmd, const void * payload, size_t payloadsize);
+    u_result _waitResponseHeader(rplidar_ans_header_t * header, _u32 timeout);
+
+protected:
+    BufferedSerial * _bined_serialdev;
+    RPLidarMeasurement _currentMeasurement;
+};