答:
When working with robotic matrices, such as transforms or dynamics, long-long-long equations are usually expected when everything is numerical. Using a symbolic platform such as MuPad or Maple will allow you to easily simplify the matrices symbolically (usually by using trigonometric identities).

Cheers,

Title: Why I'm getting very long terms in the inertia matrix (or dynamics model) of the robot using matlab script?

Body:
I'm working on the dynamics model of a RRRR articulated robot, I'm following Euler-Lagrange approach and developing my code in m-file in matlab; I'm looking for dynamic model of this form: $$
D(q) \ddot{q} + C(q,\dot{q})\dot{q}+ g(q) = \tau
$$
where $D$ and $C$ are $4 \times4$ matrices and $g$ and $\tau$ (torque) are $4\times1$ vectors; by formulating the kinetic and potential energies;;

The problem is that, I'm getting very long equations, and the term in $D$ matrix are very huge and nonlinear, involving sin and cos; I'm talking about a several pages per equation;
After I published the code - 7 pages - and the output I got around 45 pages in total;
I searched around there was some guy he faced the same problem before, but there was no helpful proposal.

Any Suggestions ??


问:
PID line follow with three sensors in Not eXactly C
I'm currently working on a line-following robot which uses three sensors to follow a black line. The sensors are pretty much in line and right next to each other.

Right now, I'm doing a simple line follow: if on the line go forward, otherwise turn left or right to regain the line. This means that the robot is wiggling along the line most of the time.

I'm looking for a better way for this robot to follow the line using three sensors. The program I'm writing is in Not eXactly C code. I'm trying to get the robot to utilize the power of PID control, but I'm not sure how one would go about writing a three-sensor PID line-follower program in NXC.

答:
I don't think traditional PID control is appropriate per se, since your sensors only provide a binary "is the line under me" signal; PID controls need to be able to calculate error (error = actual - desired).  Also, you need motors that can adjust their speed instead of simply turning on and off.

One way to get PID control might be to increase the number of sensors from 3 to 9, with barely-overlapping sense area.  That might get you a range of 17 values, 9 from sensors and 8 more in cases where 2 adjacent sensors are triggered.  I'm not sure how many points you'll need to be able to measure in order for PID control to become effective.

A more abstract way to approach this would be to consider the wiggles-per-second to be the value controlled by the PID.  In this case, the PID would control the maximum difference in speed between the two motors -- the maximum rate of turn.  If your robot is wiggling to much, such a PID should cause it to turn in more gradual arcs.  In this case, the correct target wiggles-per-second will depend on the radius of the tightest turn that the robot will have to make.

ContentLicense: CC BY-SA 3.0


问:
Turning an epilog laser into a 3d printer?
We have an epilog laser cutter around here and I was wondering if it would possibly work as a base for a 3d printer? Here is a Dropbox photo album of the laser cutter. I am thinking I will have to get a new control system but I am unsure if I will be able to use the motor controllers or if they are embedded in the current control's board. I am also unsure if it has fine enough control on the z axis but if not that can be modified.

What would be a good head to look at?
Any other thoughts?

答: Great idea for a repurpose! Check out ReplicatorG or ROS robotic control for the controller side. For the mechanical parts, I've worked with http://folger-technologies-llc.myshopify.com/ before, and their support was great.</p>


问:
Compound vision system or Megapixel camera reduction
Are any commercially available compound vision sensors available?
Not a simple 8 sensor system using photo-diodes but a genuine sensor that can provide a >32x32 compound matrix. Would some form of reduction in the granularity of a megapixel camera be a better option? The real purpose is to reduce processing time to a minimum, while extracting the maximum basic information. </p>

答:
The following people have used a compound eye for the development of their insect inspired rotor craft to demonstrate panoramic optical flow methods without the use of accelerometers.

Flying over uneven moving terrain based on optic-flow cues without
any need for reference frames or accelerometers

The sensors are described here; Curvace

Paper here; Miniature curved artificial compound eyes

Video here; https://www.youtube.com/watch?feature=player_embedded&v=xKi5wSpslPE

With a detailed description of the fabrication here;
Supporting Information


问:
Open Source software for Quadcopters
my question is general so please bear with me. I'm now interested in buying a quadcopter and develop some functions that it does for example an android app to control it, or objects detection.
So my question is what are the available quadcopters which has a software that allows me to do such things not just a flying toy?

P.S: I'm asked to buy a kit within 600$ and not build it by myself

答:
ROS is not the Jack of all trades when there is a question related to robotics. It is just a frame to help you handle package communication between different nodes(functions).

You can buy a kit of 3D-robotics' quadcopter. Their APM flight controller is an open-sourced control system based on Arduino and you can modify its framework and download it into the quadcopter. All source are available in their github.

If you don't want to pay too much attention on low-level development, which means the control control algorithm itself, and you want to develop some applications based on the quadcopter. It is another good choice to try AR.Drone, which provides many APIs.

Title: Open Source software for Quadcopters


问:
Don't understand how sensor works, metal wired directly to I/O pin of arduino
I'm trying to understand how an electronic musical instrument (called an e-chanter) works (imagine a recorder or other wind instrument, but with the holes replaced with metal contacts, and the sound played electronically, so no air is needed).

Basically, there are several metal contacts, as shown in this link: http://www.echanter.com/home/howto-build#TOC-WIRES-SCREW-SENSORS

They each appear to be wired only directly to one pin of the arduino:

I can't figure out for the life of me how this works.  Can anyone explain it, are the fingers being used as some kind of ground or what on earth is going on.  I have a physics background so can understand some technical info, but just can't fathom how on earth this magic works.

Thank you very much

答:
No, the fingers are not working as GND or other things, they just press the switch.

The switch inside should look like this: (or exchange switch and R if pin is init as LOW base)

----- VCC
   |
   R
   |-----pin of Arduino
   |
   \ the switch
   |
   |
  _|_  GND

Before you press the switch, the voltage of pin is VCC.

After you press the switch, the voltage of the Arduino pin is 0, since there is a resistance R.

The Arduino uses a ADC (Analog to Digital Converter) to detect the signal based on the input voltage, then it knows there was a HIGH signal and then it is LOW. So the system do something based on the change.

As for the pressure sensor, it works as a sliding rheostat and doesn't go through the ADC, so it is a continuous analog signal which can express the pressure value.

ContentLicense: CC BY-SA 4.0


答:
According to his code, he seems to be taking advantage of the fact that simply touching the digital input pins with your finger will cause a measurable change in signal:

```<code>/* Read the relevant pin registers and construct a single byte 'map'   */
/* of the pin states. Touched pins will be HIGH, untouched pins LOW    */

byte fb = 0;
byte fmap = 0;  //D2-D7 (bits 2,3,4,5,6,7)
fmap = PIND >> 2;  // get rid of lowest 2 bytes,  fill top 2 bytes
</code>```

In other words, there are no moving parts in his design.

I'm not sure of the exact circuitry that would allow this to work on an the Arduino, but it would be something along the lines of this AC hum touch switch:

Essentially, that the presence of a finger (which is a conductor) creates just enough change in the circuit to flip the digital bit.

Title: Don't understand how sensor works, metal wired directly to I/O pin of arduino

Body:
I'm trying to understand how an electronic musical instrument (called an e-chanter) works (imagine a recorder or other wind instrument, but with the holes replaced with metal contacts, and the sound played electronically, so no air is needed).

Basically, there are several metal contacts, as shown in this link: http://www.echanter.com/home/howto-build#TOC-WIRES-SCREW-SENSORS

They each appear to be wired only directly to one pin of the arduino:

I can't figure out for the life of me how this works.  Can anyone explain it, are the fingers being used as some kind of ground or what on earth is going on.  I have a physics background so can understand some technical info, but just can't fathom how on earth this magic works.

Thank you very much

Body:
According to his code, he seems to be taking advantage of the fact that simply touching the digital input pins with your finger will cause a measurable change in signal:

/* Read the relevant pin registers and construct a single byte 'map'   */
/* of the pin states. Touched pins will be HIGH, untouched pins LOW    */

byte fb = 0;
byte fmap = 0;  //D2-D7 (bits 2,3,4,5,6,7)
fmap = PIND >> 2;  // get rid of lowest 2 bytes,  fill top 2 bytes

In other words, there are no moving parts in his design.

I'm not sure of the exact circuitry that would allow this to work on an the Arduino, but it would be something along the lines of this AC hum touch switch:

Essentially, that the presence of a finger (which is a conductor) creates just enough change in the circuit to flip the digital bit.


问:
Is the crazyflie control board considered a microcontroller
I am currently doing a project for school and we are told that we must use a micro controller that ends up controlling some external hardware, now i know the crazyflie is controlling the motors which counts as external hardware but is it a micro controller? My second question is i want to purchase the kit so i can assembly it myself however I saw that you can use an expansion board so you need not solder and also i plan on not buying a remote its possible to control the crazyflie via my iPhone correct? I would appreciate it if someone could answer my questions. Thank you in advance</p>

答: It sounds like your school intends for you to program the microcontroller, in which case the crazyflie -- an off-the-shelf product -- would not be sufficient.


答: Anything's possible in the world of fabrication and computers, the question is how much time, effort, and money it will cost you.  If you haven't built a 3D printer from scratch before, then it might not be a good idea to attempt this; you would have no way to tell whether any problems you experience would be caused by your own design or the existing laser cutter components.</p>

Title: Turning an epilog laser into a 3d printer?

Body:
We have an epilog laser cutter around here and I was wondering if it would possibly work as a base for a 3d printer? Here is a Dropbox photo album of the laser cutter. I am thinking I will have to get a new control system but I am unsure if I will be able to use the motor controllers or if they are embedded in the current control's board. I am also unsure if it has fine enough control on the z axis but if not that can be modified.

What would be a good head to look at?
Any other thoughts?


答:
I dont use NXC, so I am hesitant to propose this as an answer, but I will comment that the sensors ARE linear - not binary. They measure dark, grey, and light - On, middle, off of line. You simply devise a scheme to get a unique #, and use that as the SetPoint to PID - works great. See Mindsensors light array for sample NXC code for their array. Adopt it to 3 sensors.

I don't know if this helps or not but is the scheme I use in RobotC; (higly shortened)

```<code>int LSA_GetAvg()
{
    char value[8];
    int som = 0;
    I2Cread(MINDSENSORS_LSA, LSA_ADDRESS, 0x42, value, 8);  // read 8 sensor values into an array
    int bits = 0;
    for (int i=0;i<8;i++)
        if (value[i] < 0x32)
    {
        som += ((8-i)*10);
        bits++;
    }
    return som / bits;
}

main loop {

    int avg = LSA_GetAvg();
    printf("avg %d\n", avg);

    if (avg != 0)
    {
      steering = S3Pid(Oval, avg, 45, elapsedTime); // 45 is our goal, set point
      printf("Steer %d\n", steering);

      motor[LEFT] = clipBAD((basePower - steering), -100, 100);
      motor[RIGHT] = clipBAD((basePower + steering), -100, 100);
    }
    else
    {
        // stuff gone wrong, we lost the line, check packed bits=0xff for a crossing
      PlaySound(soundBlip);
    }

}
</code>```

Edit: as I look at that OLD code - i see that is is not very optimum, and would work just fine with 3 binary sensors - just FYI.

Title: PID line follow with three sensors in Not eXactly C

Body:
I'm currently working on a line-following robot which uses three sensors to follow a black line. The sensors are pretty much in line and right next to each other.

Right now, I'm doing a simple line follow: if on the line go forward, otherwise turn left or right to regain the line. This means that the robot is wiggling along the line most of the time.

I'm looking for a better way for this robot to follow the line using three sensors. The program I'm writing is in Not eXactly C code. I'm trying to get the robot to utilize the power of PID control, but I'm not sure how one would go about writing a three-sensor PID line-follower program in NXC.

Body:
I dont use NXC, so I am hesitant to propose this as an answer, but I will comment that the sensors ARE linear - not binary. They measure dark, grey, and light - On, middle, off of line. You simply devise a scheme to get a unique #, and use that as the SetPoint to PID - works great. See Mindsensors light array for sample NXC code for their array. Adopt it to 3 sensors.

I don't know if this helps or not but is the scheme I use in RobotC; (higly shortened)

int LSA_GetAvg()
{
    char value[8];
    int som = 0;
    I2Cread(MINDSENSORS_LSA, LSA_ADDRESS, 0x42, value, 8);  // read 8 sensor values into an array
    int bits = 0;
    for (int i=0;i<8;i++)
        if (value[i] < 0x32)
    {
        som += ((8-i)*10);
        bits++;
    }
    return som / bits;
}

main loop {

    int avg = LSA_GetAvg();
    printf("avg %d\n", avg);

    if (avg != 0)
    {
      steering = S3Pid(Oval, avg, 45, elapsedTime); // 45 is our goal, set point
      printf("Steer %d\n", steering);

      motor[LEFT] = clipBAD((basePower - steering), -100, 100);
      motor[RIGHT] = clipBAD((basePower + steering), -100, 100);
    }
    else
    {
        // stuff gone wrong, we lost the line, check packed bits=0xff for a crossing
      PlaySound(soundBlip);
    }

}

Edit: as I look at that OLD code - i see that is is not very optimum, and would work just fine with 3 binary sensors - just FYI.


问:
Raspberry Pi quadcopter thrashes at high speeds
I am attempting to build a Raspberry Pi based quadcopter. So far I have succeeded in interfacing with all the hardware, and I have written a PID controller that is fairly stable at low throttle. The problem is that at higher throttle the quadcopter starts thrashing and jerking. I have not even been able to get it off the ground yet, all my testing has been done on a test bench. I have ruled out bad sensors by testing each sensor individually, and they seem to be giving correct values. Is this a problem with my code, or perhaps a bad motor? Any suggestions are greatly appreciated.

Here is my code so far:

QuadServer.java:

```<code>package com.zachary.quadserver;

import java.net.*;
import java.io.*;
import java.util.*;

import se.hirt.pi.adafruit.pwm.PWMDevice;
import se.hirt.pi.adafruit.pwm.PWMDevice.PWMChannel;

public class QuadServer {
    private static Sensor sensor = new Sensor();

    private final static int FREQUENCY = 490;

    private static double PX = 0;
    private static double PY = 0;

    private static double IX = 0;
    private static double IY = 0;

    private static double DX = 0;
    private static double DY = 0;

    private static double kP = 1.3;
    private static double kI = 2;
    private static double kD = 0;

    private static long time = System.currentTimeMillis();

    private static double last_errorX = 0;
    private static double last_errorY = 0;

    private static double outputX;
    private static double outputY;

    private static int val[] = new int[4];

    private static int throttle;

    static double setpointX = 0;
    static double setpointY = 0;

    static long receivedTime = System.currentTimeMillis();

    public static void main(String[] args) throws IOException, NullPointerException {

        PWMDevice device = new PWMDevice();
        device.setPWMFreqency(FREQUENCY);

        PWMChannel BR = device.getChannel(12);
        PWMChannel TR = device.getChannel(13);
        PWMChannel TL = device.getChannel(14);
        PWMChannel BL = device.getChannel(15);

        DatagramSocket serverSocket = new DatagramSocket(8080);

        Thread read = new Thread(){
                public void run(){
                    while(true) {
                    try {
                            byte receiveData[] = new byte[1024];
                            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                            serverSocket.receive(receivePacket);
                            String message = new String(receivePacket.getData());
                            throttle = (int)(Integer.parseInt((message.split("\\s+")[4]))*12.96)+733;
                            setpointX = Integer.parseInt((message.split("\\s+")[3]))-50;
                            setpointY = Integer.parseInt((message.split("\\s+")[3]))-50;

                        receivedTime = System.currentTimeMillis();

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
        };
        read.start();

        while(true)
        {
            Arrays.fill(val, calculatePulseWidth((double)throttle/1000, FREQUENCY));

            double errorX = -sensor.readGyro(0)-setpointX;
            double errorY = sensor.readGyro(1)-setpointY;

            double dt = (double)(System.currentTimeMillis()-time)/1000;

            double accelX = sensor.readAccel(0);
            double accelY = sensor.readAccel(1);
            double accelZ = sensor.readAccel(2);

            double hypotX = Math.sqrt(Math.pow(accelX, 2)+Math.pow(accelZ, 2));
            double hypotY = Math.sqrt(Math.pow(accelY, 2)+Math.pow(accelZ, 2));

            double accelAngleX = Math.toDegrees(Math.asin(accelY/hypotY));
            double accelAngleY = Math.toDegrees(Math.asin(accelX/hypotX));

            if(dt > 0.01)
            {

                PX = errorX;
                PY = errorY;

                IX += errorX*dt;
                IY += errorY*dt;

                IX = 0.95*IX+0.05*accelAngleX;
                IY = 0.95*IY+0.05*accelAngleY;

                DX = (errorX - last_errorX)/dt;
                DY = (errorY - last_errorY)/dt;

                outputX = kP*PX+kI*IX+kD*DX;
                outputY = kP*PY+kI*IY+kD*DY;
                time = System.currentTimeMillis();
            }

            System.out.println(setpointX);

            add(-outputX+outputY, 0);
            add(-outputX-outputY, 1);
            add(outputX-outputY, 2);
            add(outputX+outputY, 3);

            //System.out.println(val[0]+", "+val[1]+", "+val[2]+", "+val[3]);
            if(System.currentTimeMillis()-receivedTime < 1000)
            {
                BR.setPWM(0, val[0]);
                TR.setPWM(0, val[1]);
                TL.setPWM(0, val[2]);
                BL.setPWM(0, val[3]);
            } else
            {
                BR.setPWM(0, 1471);
                TR.setPWM(0, 1471);
                TL.setPWM(0, 1471);
                BL.setPWM(0, 1471);
            }

        }
    }

    private static void add(double value, int i)
    {
        value = calculatePulseWidth(value/1000, FREQUENCY);
        if(val[i]+value > 1471 && val[i]+value < 4071)
        {
            val[i] += value;
        }else if(val[i]+value < 1471)
        {
            //System.out.println("low");
            val[i] = 1471;
        }else if(val[i]+value > 4071)
        {
            //System.out.println("low");
            val[i] = 4071;
        }
    }

    private static int calculatePulseWidth(double millis, int frequency) {
        return (int) (Math.round(4096 * millis * frequency/1000));
    }
}
</code>```

Sensor.java:

```<code>package com.zachary.quadserver;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.i2c.*;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.i2c.*;

import java.net.*;
import java.io.*;

public class Sensor {
    static I2CDevice sensor;
    static I2CBus bus;
    static byte[] accelData, gyroData;
    static long accelCalib[] = new long[3];
    static long gyroCalib[] = new long[3];

    static double gyroX = 0;
    static double gyroY = 0;
    static double gyroZ = 0;

    static double accelX;
    static double accelY;
    static double accelZ;

    static double angleX;
    static double angleY;
    static double angleZ;

    public Sensor() {
        //System.out.println("Hello, Raspberry Pi!");
        try {
            bus = I2CFactory.getInstance(I2CBus.BUS_1);

            sensor = bus.getDevice(0x68);

            sensor.write(0x6B, (byte) 0x0);
            sensor.write(0x6C, (byte) 0x0);
            System.out.println("Calibrating...");

            calibrate();

            Thread sensors = new Thread(){
                    public void run(){
                        try {
                            readSensors();
                        } catch (IOException e) {
                        System.out.println(e.getMessage());
                    }
                    }
            };
            sensors.start();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    private static void readSensors() throws IOException {
        long time = System.currentTimeMillis();
        long sendTime = System.currentTimeMillis();

        while (true) {
            accelData = new byte[6];
            gyroData = new byte[6];
            int r = sensor.read(0x3B, accelData, 0, 6);
            accelX = (((accelData[0] << 8)+accelData[1]-accelCalib[0])/16384.0)*9.8;
            accelY = (((accelData[2] << 8)+accelData[3]-accelCalib[1])/16384.0)*9.8;
            accelZ = ((((accelData[4] << 8)+accelData[5]-accelCalib[2])/16384.0)*9.8)+9.8;
            accelZ = 9.8-Math.abs(accelZ-9.8);

            double hypotX = Math.sqrt(Math.pow(accelX, 2)+Math.pow(accelZ, 2));
            double hypotY = Math.sqrt(Math.pow(accelY, 2)+Math.pow(accelZ, 2));

            double accelAngleX = Math.toDegrees(Math.asin(accelY/hypotY));
            double accelAngleY = Math.toDegrees(Math.asin(accelX/hypotX));

            //System.out.println((int)gyroX+", "+(int)gyroY);

            //System.out.println("accelX: " + accelX+" accelY: " + accelY+" accelZ: " + accelZ);

            r = sensor.read(0x43, gyroData, 0, 6);
            if(System.currentTimeMillis()-time >= 5)
            {
                gyroX = (((gyroData[0] << 8)+gyroData[1]-gyroCalib[0])/131.0);
                gyroY = (((gyroData[2] << 8)+gyroData[3]-gyroCalib[1])/131.0);
                gyroZ = (((gyroData[4] << 8)+gyroData[5]-gyroCalib[2])/131.0);

                angleX += gyroX*(System.currentTimeMillis()-time)/1000;
                angleY += gyroY*(System.currentTimeMillis()-time)/1000;
                angleZ += gyroZ;

                angleX = 0.95*angleX + 0.05*accelAngleX;
                angleY = 0.95*angleY + 0.05*accelAngleY;

                time = System.currentTimeMillis();
            }
            //System.out.println((int)angleX+", "+(int)angleY);
            //System.out.println((int)accelAngleX+", "+(int)accelAngleY);
        }
    }

    public static void calibrate() throws IOException {
        int i;
        for(i = 0; i < 3000; i++)
        {
            accelData = new byte[6];
            gyroData = new byte[6];
            int r = sensor.read(0x3B, accelData, 0, 6);
            accelCalib[0] += (accelData[0] << 8)+accelData[1];
            accelCalib[1] += (accelData[2] << 8)+accelData[3];
            accelCalib[2] += (accelData[4] << 8)+accelData[5];

            r = sensor.read(0x43, gyroData, 0, 6);
            gyroCalib[0] += (gyroData[0] << 8)+gyroData[1];
            gyroCalib[1] += (gyroData[2] << 8)+gyroData[3];
            gyroCalib[2] += (gyroData[4] << 8)+gyroData[5];
            try {
                Thread.sleep(1);
            } catch (Exception e){
                e.printStackTrace();
            }
        }
        gyroCalib[0] /= i;
        gyroCalib[1] /= i;
        gyroCalib[2] /= i;

        accelCalib[0] /= i;
        accelCalib[1] /= i;
        accelCalib[2] /= i;
        System.out.println(gyroCalib[0]+", "+gyroCalib[1]+", "+gyroCalib[2]);
    }

    public double readAngle(int axis)
    {
        switch (axis)
        {
            case 0:
                return angleX;
            case 1:
                return angleY;
            case 2:
                return angleZ;
        }

        return 0;
    }

    public double readGyro(int axis)
    {
        switch (axis)
        {
            case 0:
                return gyroX;
            case 1:
                return gyroY;
            case 2:
                return gyroZ;
        }

        return 0;
    }

    public double readAccel(int axis)
    {
        switch (axis)
        {
            case 0:
                return accelX;
            case 1:
                return accelY;
            case 2:
                return accelZ;
        }

        return 0;
    }
}
</code>```

Edit:

I have re-written my code in C++ to see if it will run faster but it's still running at about the same speed(about 15 ms per cycle or about 66 Hz).

This is my new code in C++:

```<code>#include <wiringPi.h>
#include <wiringPiI2C.h>

#include <sys/socket.h>
#include <netinet/in.h>

#include <string.h>
#include <string>
#include <iostream>
#include <unistd.h>

#include <boost/thread.hpp>

#include <time.h>

#include <cmath>

#define axisX 0
#define axisY 1
#define axisZ 2

#define kP 20
#define kI 0
#define kD 0

#define FREQUENCY 490

#define MODE1 0x00
#define MODE2 0x01
#define SUBADR1 0x02
#define SUBADR2 0x03
#define SUBADR13 0x04
#define PRESCALE 0xFE
#define LED0_ON_L 0x06
#define LED0_ON_H 0x07
#define LED0_OFF_L 0x08
#define LED0_OFF_H 0x09
#define ALL_LED_ON_L 0xFA
#define ALL_LED_ON_H 0xFB
#define ALL_LED_OFF_L 0xFC
#define ALL_LED_OFF_H 0xFD

// Bits
#define RESTART 0x80
#define SLEEP 0x10
#define ALLCALL 0x01
#define INVRT 0x10
#define OUTDRV 0x04

#define BILLION 1000000000L

using namespace std;

double accelCalX = 0;
double accelCalY = 0;
double accelCalZ = 0;

double gyroCalX = 0;
double gyroCalY = 0;
double gyroCalZ = 0;

double PX;
double PY;

double IX = 0;
double IY = 0;

double DX;
double DY;

double lastErrorX;
double lastErrorY;

int throttle = 1471;

int sensor = wiringPiI2CSetup(0x68);
int pwm = wiringPiI2CSetup(0x40);

array<int,4> motorVal;

struct timespec now, then;

int toSigned(int unsignedVal)
{
    int signedVal = unsignedVal;
    if(unsignedVal > 32768)
    {
        signedVal = -(32768-(unsignedVal-32768));
    }
    return signedVal;
}

double getAccel(int axis)
{
    double X = (toSigned((wiringPiI2CReadReg8(sensor, 0x3B) << 8)+wiringPiI2CReadReg8(sensor, 0x3C)))/1671.8;
    double Y = (toSigned((wiringPiI2CReadReg8(sensor, 0x3D) << 8)+wiringPiI2CReadReg8(sensor, 0x3E)))/1671.8;
    double Z = (toSigned((wiringPiI2CReadReg8(sensor, 0x3F) << 8)+wiringPiI2CReadReg8(sensor, 0x40)))/1671.8;

    X -= accelCalX;
    Y -= accelCalY;
    Z -= accelCalZ;
    Z = 9.8-abs(Z-9.8);

    switch(axis)
    {
        case axisX:
            return X;
        case axisY:
            return Y;
        case axisZ:
            return Z;
    }
}

double getGyro(int axis)
{
    double X = (toSigned((wiringPiI2CReadReg8(sensor, 0x43) << 8)+wiringPiI2CReadReg8(sensor, 0x44)))/1671.8;
    double Y = (toSigned((wiringPiI2CReadReg8(sensor, 0x45) << 8)+wiringPiI2CReadReg8(sensor, 0x46)))/1671.8;
    double Z = (toSigned((wiringPiI2CReadReg8(sensor, 0x47) << 8)+wiringPiI2CReadReg8(sensor, 0x48)))/1671.8;

    X -= gyroCalX;
    Y -= gyroCalY;
    Z -= gyroCalZ;

    switch(axis)
    {
        case axisX:
            return X;
        case axisY:
            return Y;
        case axisZ:
            return Z;
    }
}

void calibrate()
{
    int i;
    for(i = 0; i < 1500; i++)
    {
        accelCalX += (toSigned((wiringPiI2CReadReg8(sensor, 0x3B) << 8)+wiringPiI2CReadReg8(sensor, 0x3C)))/1671.8;
        accelCalY += (toSigned((wiringPiI2CReadReg8(sensor, 0x3D) << 8)+wiringPiI2CReadReg8(sensor, 0x3E)))/1671.8;
        accelCalZ += (toSigned((wiringPiI2CReadReg8(sensor, 0x3F) << 8)+wiringPiI2CReadReg8(sensor, 0x40)))/1671.8;

        gyroCalX += (toSigned((wiringPiI2CReadReg8(sensor, 0x43) << 8)+wiringPiI2CReadReg8(sensor, 0x44)))/1671.8;
        gyroCalX += (toSigned((wiringPiI2CReadReg8(sensor, 0x45) << 8)+wiringPiI2CReadReg8(sensor, 0x46)))/1671.8;
        gyroCalX += (toSigned((wiringPiI2CReadReg8(sensor, 0x45) << 8)+wiringPiI2CReadReg8(sensor, 0x46)))/1671.8;
        usleep(1000);
    }

    accelCalX /= i;
    accelCalY /= i;
    accelCalZ /= i;
    accelCalZ -= 9.8;

    gyroCalX /= i;
    gyroCalY /= i;
    gyroCalZ /= i;

    cout << accelCalX << " " << accelCalY << " " << accelCalZ << "\n";
}

int calculatePulseWidth(double millis, int frequency) {
    return (int)(floor(4096 * millis * frequency/1000));
}

void add(double value, int i)
{
    value = calculatePulseWidth(value/1000, FREQUENCY);
    if(motorVal[i]+value > 1471 && motorVal[i]+value < 4071)
    {
        motorVal[i] += value;
    }else if(motorVal[i]+value < 1471)
    {
        //System.out.println("low");
        motorVal[i] = 1471;
    }else if(motorVal[i]+value > 4071)
    {
        //System.out.println("low");
        motorVal[i] = 4071;
    }
}

void getThrottle()
{
    int sockfd,n;
    struct sockaddr_in servaddr,cliaddr;
    socklen_t len;
    char mesg[1000];

    sockfd=socket(AF_INET,SOCK_DGRAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(8080);
    bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    while(true)
    {
        len = sizeof(cliaddr);
        n = recvfrom(sockfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&len);
        mesg[n] = 0;
        string message(mesg);
        string values[5];

        int valIndex = 0;
        int lastIndex = 0;
        for(int i = 0; i < message.length(); i++)
        {
            if(message[i] == ' ')
            {
                values[valIndex] = message.substr(lastIndex+1, i);
                lastIndex = i;
                valIndex++;
            }
        }
        values[valIndex] = message.substr(lastIndex+1, message.length());

        throttle = calculatePulseWidth(((stoi(values[4])*12.96)+733)/1000, FREQUENCY);
    }
}

void setAllPWM(int on, int off) {
    wiringPiI2CWriteReg8(pwm, ALL_LED_ON_L, (on & 0xFF));
    wiringPiI2CWriteReg8(pwm, ALL_LED_ON_H, (on >> 8));
    wiringPiI2CWriteReg8(pwm, ALL_LED_OFF_L, (off & 0xFF));
    wiringPiI2CWriteReg8(pwm, ALL_LED_OFF_H, (off >> 8));
}

void setPWM(int on, int off, int channel) {
    wiringPiI2CWriteReg8(pwm, LED0_ON_L + 4 * channel, (on & 0xFF));
    wiringPiI2CWriteReg8(pwm, LED0_ON_H + 4 * channel, (on >> 8));
    wiringPiI2CWriteReg8(pwm, LED0_OFF_L + 4 * channel, (off & 0xFF));
    wiringPiI2CWriteReg8(pwm, LED0_OFF_H + 4 * channel, (off >> 8));
}

void setPWMFrequency(double frequency) {
    double prescaleval = 25000000.0;
    prescaleval /= 4096.0;
    prescaleval /= frequency;
    prescaleval -= 1.0;
    double prescale = floor(prescaleval + 0.5);
    int oldmode = wiringPiI2CReadReg8(pwm, MODE1);
    int newmode = (oldmode & 0x7F) | 0x10;
    wiringPiI2CWriteReg8(pwm, MODE1, newmode);
    wiringPiI2CWriteReg8(pwm, PRESCALE, (floor(prescale)));
    wiringPiI2CWriteReg8(pwm, MODE1, oldmode);
    usleep(50000);
    wiringPiI2CWriteReg8(pwm, MODE1, (oldmode | 0x80));
}

void initSensor()
{
    wiringPiI2CWriteReg8(sensor, 0x6B, 0x0);
    wiringPiI2CWriteReg8(sensor, 0x6C, 0x0);
}

void initPWM()
{
    setAllPWM(0, 0);
    wiringPiI2CWriteReg8(pwm, MODE2, OUTDRV);
    wiringPiI2CWriteReg8(pwm, MODE1, ALLCALL);
    usleep(50000);
    int mode1 = wiringPiI2CReadReg8(pwm, MODE1);
    mode1 = mode1 & ~SLEEP;
    wiringPiI2CWriteReg8(pwm, MODE1, mode1);
    usleep(50000);
    setPWMFrequency(FREQUENCY);
}

double millis(timespec time)
{
    return (time.tv_sec*1000)+(time.tv_nsec/1.0e6);
}

double intpow( double base, int exponent )
{
    int i;
    double out = base;
    for( i=1 ; i < exponent ; i++ )
    {
        out *= base;
    }
    return out;
}

int main (void)
{

    initSensor();
    initPWM();

    cout << "Calibrating..." << "\n";
    calibrate();

    boost::thread server(getThrottle);

    clock_gettime(CLOCK_MONOTONIC, &then);

    while(true)
    {
        motorVal.fill(throttle);

        clock_gettime(CLOCK_MONOTONIC, &now);

        double dt = (millis(now)-millis(then))/1000;

        then = now;

        double accelX = getAccel(0);
        double accelY = getAccel(1);
        double accelZ = getAccel(2);

        double hypotX = sqrt(intpow(accelX, 2)+intpow(accelZ, 2));
        double hypotY = sqrt(intpow(accelY, 2)+intpow(accelZ, 2));

        double accelAngleX = (180/3.14)*(asin(accelY/hypotY));
        double accelAngleY = (180/3.14)*(asin(accelX/hypotX));

        double errorX = -getGyro(0);
        double errorY = getGyro(1);

        PX = errorX;
        PY = errorY;

        IX += errorX*dt;
        IY += errorY*dt;

        IX = 0.95*IX+0.05*accelAngleX;
        IY = 0.95*IY+0.05*accelAngleY;

        DX = (errorX-lastErrorX)*dt;
        DY = (errorY-lastErrorY)*dt;

        lastErrorX = errorX;
        lastErrorY = errorY;

        double outputX = kP*PX+kI*IX+kD*DX;
        double outputY = kP*PY+kI*IY+kD*DY;

        add(outputY, 0);//-outputX+
        add(outputY, 1);//-outputX-
        add(outputY, 2);//outputX-
        add(outputY, 3);//outputX+

        setPWM(0, motorVal[0], 12);
        setPWM(0, motorVal[1], 13);
        setPWM(0, motorVal[2], 14);
        setPWM(0, motorVal[3], 15);
    }
}
</code>```

In addition two of the motors seem like they are lagging when I turn the quadcopter fast in one direction. Also for some strange reason the quadcopter seems less responsive to P gain; I have it at 20 in the C++ version and it is working about the same as when I had it at 1.5 in the java version.

Edit:

After doing some more testing I have determined that reading from the MPU6050 and writing to the PCA9685 board that I am using to control the ESCs is the source of the delay. Does anybody know how to speed this up?

Edit:

I managed to speed up my code to about 200 Hz by changing the i2c baud rate, but the quadcopter is still thrashing. I have spent hours trying to tune the pid controller, but it doesn't seem to help at all.

答:
You are using a PID incorrectly.  You are reading sensor values that in terms of acceleration, but you are using that to correct an error in velocity (without conversion).  Your PID should be reading and controlling the same measurement -- velocity vs velocity, acceleration vs acceleration, or position vs position.

The behavior you are seeing can be explained simply by $$
a = \frac{dv}{dt}
$$

At low velocities, $dv$ can only be as high as your maximum velocity, so your system appears to work properly within that bound.  But as you increase the maximum velocity, your acceleration can spike much higher.

This is simply a logic error in your code played out in physical space.


问:
Does an electronic compass work underwater
I'm building a submersible ROV, so I need a way to navigate. So using a compass would help but this brings up the question, does an electronic compass work underwater?

My thoughts are the water might act as a faraday cage, and therefore interfere with the magnetic field. Therefore it might not even work. Maybe a gyroscope might be a better solution.

答: A compass will work fine.  However, you will find that without a way to measure your velocity (speed-over-ground) in both forward and sideways directions, you will have a tough time keeping track of where you are.</p>


答:
Any magnetic compass absolutely will work underwater.

Several companies (e.g., PNI, OceanServer) build and sell electronic compass modules based on flux-gate technology specifically for underwater applications.

Buoyancy gliders and small AUVs or ROVs usually rely on flux gate compasses to sense heading because they are small, relatively inexpensive, and consume little power. Larger, more expensive vehicles often have a magnetic compass for backup, but use a gyrocompass (RLG or FOG) as the primary orientation sensor because it is more accurate than a magnetic compass and is not susceptible to local magnetic disturbances (like the vehicle's motors or batteries).

The accuracy of your compass is important because if you are trying to navigate by dead reckoning -- or by inertial navigation -- any errors in your orientation estimate make errors in your position estimate grow quickly. To improve the data rate and accuracy of a magnetic compass, and to make it less susceptible to local magnetic disturbances, you can combine angular rates from a gyro with the angles from a compass using a complementary filter or a Kalman filter. But trying to use only a gyro, you will run into trouble as you integrate to get angle -- over long periods, your integration will drift. That's why the complementary filter solution works -- the magnetic compass is a bit noisy, but stable over the long term, while the gyro is accurate and fast over the short term, but drifts unbounded in the long term.

As Ian mentioned, if you are trying to track your robot's position, you will also need a velocity estimate for dead reckoning. If you are in stationary body of water, like a pool, you can probably get away with "counting propeller turns", but you would need to calibrate your propeller. In the field, most vehicles will use a Doppler velocity log (DVL) to measure speed relative to the seafloor. That is an expensive sensor to add, but well worth it if your application requires precision navigation.

Refer to this article for a fairly recent survey on underwater navigation technology.

Title: Does an electronic compass work underwater

Body:
I'm building a submersible ROV, so I need a way to navigate. So using a compass would help but this brings up the question, does an electronic compass work underwater?

My thoughts are the water might act as a faraday cage, and therefore interfere with the magnetic field. Therefore it might not even work. Maybe a gyroscope might be a better solution.


问:
Iron man Jarvis like robot
I'm very passionate about robots from my childhood.I'm a java developer.
I love sci-fi movies.I have a little bit knowledge in embedded systems and electronics.
My ambition is to build a robot like Jarvis (In Iron Man Movie).Which is a voice controlled robot.I would like to implement that in my house as a home automation system.It would take voice as input and take appropriate action.. Please help me to do this.
Any kind of help is appreciated..</p>

答:
As it has already been pointed out, this is such a broad topic, it's almost impossible to answer it... People do entire doctoral thesis for years on "just" one aspect like speech recognition!!

But here is what you could do:

1) get a Raspberry Pi for the brain. You'll have to learn how to use Linux and a programming language like Python

2) get a cheap robotic arm: this one has been reverse-engineered before and you can find all the code on the web to control it with the raspberry pi

3) add a microphone and a little speaker and use the google Speech API for voice recognition

When you get there, you'll be where most hobbyist can get too easily without needing a lab or expensive equipment. Many people have done very similar projects, just google it, look on YouTube.

Title: Iron man Jarvis like robot


答:
Maybe they are using the capacitance of your hand touching the screw?

In this article the pin is first pulled low, and then the software measures how long it takes to charge it back up through the pull up resistor. If a finger is touching the sensor, it increases the sensor's capacitance, resulting in longer charging times.

(Don't ask me about any details, though -- I just remembered seeing the article a while ago, I don't have any experience with this.)


问:
What equipment has been used to design this robot
Look at this robot here http://www.meccanotec.com/step781b.JPG
I can see rods which have a lot of holes and planes which also have holes. This seems to be a way to create flexibility in how the things are connected together to create the final robot. Is there a name for this type of equipment, metals with holes. Where can I get it? I am aware of people using lego blocks to create robots, but am not sure about what these metal rods and plates with holes are.

Is there a free application in which I can design a mechanical structure like the one in the image and add gears and then simulate it to see how it will rotate and bend should a real robot like that be created?

What would be the quickest way to create a robot like this?

Edit: Thankyou; Frank and lanyusea. If one wants to do a simulation of the mechanical model, in others words play with the robot on the computer before actually building it (with all those gears in action), which software is most suitable for that purpose?

答:
Those are Erector Sets.
http://www.erector.us/

They are AWESOME!!
http://en.wikipedia.org/wiki/Erector_Set


问:
How can I know which system is easier to control using PID controller?
I have a inverted inertia wheel pendulum.
I suppose that if I have a wheel with larger inertia at its top, the system would be more stable.

How can I prove or disprove my conjecture?

答: Linearize the system around the operating point you're interested in. Look at the eigenvalues of the A and B matrices that represents the linearized system. Then compare the eigenvalues using from systems with different wheel sizes.  </p>


问:
Magnetometer to measure high angular velocity in small object
I have to measure the frequency of a little circle in rotation. You can image this circle flying in air, because this circle can't touch anything that is not in rotation. So I can't use some simple trick to count the number of complete rotation in an amount of time.

So I supposed my only chance was to use an accelerometer, a gyroscope, or a magnetometer. The accelerometer can detect the centripetal acceleration, and the gyroscope and the magnetometer with some calculus directly the frequency.

The problem is the high frequency of this circle (can reach up to 50 Hz). Doing some simple calculus we know we need a gyroscope that can measure big angular velocity: 50*360°/s = 18.000°/s. Also the accelerometer need big range of values (the radius of the circle is only 5 cm): w (angular velocity) = (2 * 3,14) / (1/50) = 314 rad/sec acc_centr = w^2 * R = 98596 * 0,05 ~ 5000m/s^2 ~ 500g

Now I have seen there are some accelerometer or gyroscope for industrial purposes with enough range, but my question is:

How I can understand if a magnetometer can used is this kind of application? Considering there is no magnetic field near the circle, can a magnetometer be used to measure quickly change in inclination? In the datasheet i can read how ofter the sensor can communicate with my arduino, but nothing about how quick the rotation can be.

Is the reason that a magnetometer don't have the limits of a gyroscope or an accelerometer?

答: Im not sure what kind of system you're trying to build but I think an encoder type sensor would work best. You could mount some amount of red leds on the edge of the disk and place a light sensor around the disk. This would let you measure the frequency of the disk without dealing with magnetometers. </p>


答:
well, besides Erector Sets, there are several other choices

The LEGO EV3 http://www.lego.com/en-us/mindstorms/products/31313-mindstorms-ev3

and

MakeBlock http://www.makeblock.cc/

They both can achieve the same goal.

Title: What equipment has been used to design this robot

Body:
Look at this robot here http://www.meccanotec.com/step781b.JPG
I can see rods which have a lot of holes and planes which also have holes. This seems to be a way to create flexibility in how the things are connected together to create the final robot. Is there a name for this type of equipment, metals with holes. Where can I get it? I am aware of people using lego blocks to create robots, but am not sure about what these metal rods and plates with holes are.

Is there a free application in which I can design a mechanical structure like the one in the image and add gears and then simulate it to see how it will rotate and bend should a real robot like that be created?

What would be the quickest way to create a robot like this?

Edit: Thankyou; Frank and lanyusea. If one wants to do a simulation of the mechanical model, in others words play with the robot on the computer before actually building it (with all those gears in action), which software is most suitable for that purpose?


问:
Is it tough to make a robotic workshop of your own
I want to make a robotic workshop.. I recruited 10 members to work...  Please give some tips about robotic workshop</p>

答:
It is tough if you don't have any knowledge on programming or electronic.

There are three parts related to Robotics:
Mechanical part, Hardware part and Software part.

You should focus on one or more parts of them.

Usually programming is the key thing. Because you can buy existing equipment(mech or hw) instead of designing your own and build them but you have to program by yourself.

So if you really know nothing, buy some devices like Arduino and using them to teach MCU/EmbeddedSystem programming.

Advanced, try to design circuit yourself. Either breadboard or designing PCB using Eagle or Altium Designer.

More advanced and if possible, design the mechanical part by yourself. Design the  joint and structure by Solidworks and produce what you draw using 3d printer or other ways.


问:
In the PID equation K[((s+a)^2)/s] what values correspond to the PID coefficients Kp, Ki, Kd?
I'm trying to understand how to obtain the Kp, Ki, Kd values after finding a combination of K and a that works for me. Do I just expand the equation and take the coefficients? </p>

答:
It is in frequency domain instead of time domain.

$$
G(s)=\frac{K(s+a)^2}{s} = \frac{Ks^2+2Kas+Ka^2}{s}
$$

according to the Laplace form of the PID controller
$$
G(s)=\frac{K_ds^2+K_ps+K_i}{s}
$$

so
$$
K_d = K, K_p = 2Ka, K_i = Ka^2
$$


问:
Detect human in proximity?
I'm looking for ways to detect human presense behind walls in close proximity (around 10 feet) in whatever way possible! Problem is I can't code! (I hope it's ok I'm posting here.)
I know there are different sensors but they all seem to be for detecting by motion of target humans.
How do you detect still persons?
Is there a sound amplification device that magnifies human breathing x 20?
Or detect body heat?
Or pick up radiation waves or something off humans?</p>

答:
A static human is well shielded by a wall.  Very long wave IR may pass a diffuse heat signature. The sound of breathing or exhaled CO2 may locate someone hiding in a wardrobe.

Micropower Impulse Radar or similar modern implementations for occupancy sensors that are used for turning on lights may work through walls a little but I believe they are Doppler based so need to have movement to detect a person.

The following light fitting incorporates a person sensor and they work through doors, operate at 5GHz and have a ~12mm long antenna on a shielded electronics module inside.

http://www.sahkonumerot.fi/4207001/doc/installationinstruction/

Title: Detect human in proximity?


问:
Good Microcontrollers/SOCs for a Robotics Project
I am looking for a starting point for my project, preferably using popular systems (ones there is a lot of support for). I have an Arduino Uno, a Raspberry Pi, and a lot of willpower :) Anyone here built a project using the systems above?

Observation: I'd like to start with a simple line-following vehicle and build up afterwards.

答:
You should use an ARM. Then you can run full linux or android and have access to powerful libraries, high-level functional languages, and a package manager and community. You can use gcc or LLVM, and a modern debugger like gdb.

ARMs used to be too expensive and/or too big, but nowadays you can get an ARM for $5 that's only 13x13 mm. You have to use reflow soldering, but you will anyways if you want to make a professional-quality robot.

http://www.eetimes.com/electronics-products/electronic-product-reviews/processors/4230227/TI-debuts--5-Sitara-AM335x-ARM-processors

All other instructions sets have lost the competition. If you  pick something like AVR, you will be forever stuck with inferior toolchains, weaker MIPS/dollar, and a much smaller community.

If you don't want to engineer the whole motherboard, then Gumstix, BeagleBone, BeagleBoard, and Raspberry Pi are all excellent pre-existing ARM-based devkits, and processor vendors also offer a devkit for every processor they make, bringing out at least a display bus and some serial busses.


问:
Why are Mars rovers so slow?
Mars rovers are typically very slow. Curiosity, for example, has average speed of about 30 meters per hour.

Why is it designed so slow? Is it because of some specific power restrictions or for other reasons? What is the top reason why it is so slow?

答:
I'm not such an expert in physics, but I can think of a few reasons:

Power. The amount of power you need to do a task is inversely proportional to the time it takes to do that task. I think it is well known that doing something faster requires more power, otherwise you could do everything infinitely fast at no cost.

Computation Speed. The statement about power (above) is not limited to movements. It is also true for computation. Have you noticed when your laptop is on power-saving mode, it runs slower? With processors, if you compute something twice as fast, you need four times more energy to do it. As a result, most probably, the CPU of mars rovers are also not working at a high speed. Therefore, if the rover needs time to process something before moving on (for example images of the environment), it needs to move slower so it would receive data at a slower rate. Slow enough so that it can process them.

Stability. I believe I don't need to give you formulas for this phenomenon:

Simply put, the slower you go, the smaller the chance of lifting off over a ridge and possibly losing your stability when you land.

Maneuverability. If you go at a reasonably slow speed, you wouldn't have any trouble steering. On the other hand, at high speeds, you need larger curvature to turn, as well as more pressure on the wheels on the outer side.

Note that some of these issues, such as stability, are true for robots on earth too. However, here on earth we can always flip the vehicle if it turned over, but on Mars we can't trust Martians on it (they may like the rover stuck on its back and start worshipping it, which is totally not cool for us).

Title: Why are Mars rovers so slow?


答:
Do you need the sensor to be installed on the circle itself? If so, can you move the accelerometer closer to the center so that less force is applied to it?

You might want to look into optical RPM sensors, like this. All you need to do is put a reflective tape on your rotary part so that the sensor can see the reflection once for each cycle.

Title: Magnetometer to measure high angular velocity in small object

Body:
I have to measure the frequency of a little circle in rotation. You can image this circle flying in air, because this circle can't touch anything that is not in rotation. So I can't use some simple trick to count the number of complete rotation in an amount of time.

So I supposed my only chance was to use an accelerometer, a gyroscope, or a magnetometer. The accelerometer can detect the centripetal acceleration, and the gyroscope and the magnetometer with some calculus directly the frequency.

The problem is the high frequency of this circle (can reach up to 50 Hz). Doing some simple calculus we know we need a gyroscope that can measure big angular velocity: 50*360°/s = 18.000°/s. Also the accelerometer need big range of values (the radius of the circle is only 5 cm): w (angular velocity) = (2 * 3,14) / (1/50) = 314 rad/sec acc_centr = w^2 * R = 98596 * 0,05 ~ 5000m/s^2 ~ 500g

Now I have seen there are some accelerometer or gyroscope for industrial purposes with enough range, but my question is:

How I can understand if a magnetometer can used is this kind of application? Considering there is no magnetic field near the circle, can a magnetometer be used to measure quickly change in inclination? In the datasheet i can read how ofter the sensor can communicate with my arduino, but nothing about how quick the rotation can be.

Is the reason that a magnetometer don't have the limits of a gyroscope or an accelerometer?


问:
How do I get MPU 6050 gyroscope data using "MPU6050_6Axis_MotionApps20.h" library
I'm currently calibrating the MPU6050 chip using an arduino mega 2560. I am using the J Rowberg 12c dev libraries. I can get it to print raw accelerometer and gyroscpe values (very unstable, wildly changing values). In the digital motion processing chip library, I can get it to print euler angles, quaternions, real world acceleration and actual acceleration but there is no option to get gyroscope data.

can I use the DMP library to get gyro data or is it only possible to get raw unprocessed gyro values?

答:
I went through the header files of the 12cdev lib and I figured it out.

you have to first add the line VectorInt16 gyro; to your motion variables, then you add the line

mpu.dmpGetGyro(&gyro, fifoBuffer);

to your outputs.


问:
How can I filter Gyroscopic data?
I am using an Arduino Mega with an MPU6050. I can get gyroscopic data as well as euler angles. The problem is my gyro data keeps going back and forth between 0 and -1 despite me not moving it at all (it stays on -1 the most). What can I do to filter what I assume is noise? I am going to use the gyro data for a quadcopter PID rate controller so I cant really have it telling me I am rotating at -1 deg/sec. That would be catastrophic for the quadcopter</p>

答: $1^\circ/s$ does not seem to be very catastrophic. The noise seems quite low. More interesting is if your euler angles are stable and drift-free. Then you can control the pitch and roll error based on these estimates. As far as I remember the MPU6050 already does the filtering of gyros and accelerometers for you. </p>

Title: How can I filter Gyroscopic data?


问:
Provides a 10 Degree-Of-Freedom IMU reduntant data?
Basic question concerning sensor fusion:

A standard 10 DoF IMU, I mean this cheap things for the tinkerer at home, provides 10 values:
3 Accelerometers
3 Gyroscope
3 Magnetic Field Measurements
1 Pressure sensor (+ 1 Temperature)

I know that the accel-data provide long term stability, but are useless for short term and the gyroscope is more or less vice versa.

So there are tons of strategies to "marry" this values, but how does the magnetic field measurement fit into this framework?

Basically the magnetic field measurement should provide an attitude, too. Like the other two sensors combined. I guess this measurement alone is neither reliable.

So how do all these sensors fit together?

BR

答:
The magnetometer is an electric compass. If you know the magnetic field that you are operating in, you should be able to tell which direction you're pointing in.

All three sensors can be fused together to give you an accurate estimate of attitude. This can be done using a nonlinear kalman filter.

Using only the accelerometer and the gyro, vehicle heading cannot be measured. You can integrate the gyro measurements but you have no way to account for drift. That is what the magnetometer brings to the system.


答:
One reason is because of the communications delay between Earth and Mars.

The round trip time for signals from Earth to Mars is several minutes, which means that you can't teleoperate the robot in realtime. That means that the robot needs some autonomous obstacle avoidance capability to help prevent it from getting stuck or otherwise in trouble.

The hazard avoidance equipment on mars rovers is generally designed in a very conservative way, which means drive slow and stop frequently to check your environment.

From Wikipedia, for the Mars Exploration Rovers (Spirit and Opportunity):

...hazard avoidance software causes it to stop every 10 seconds for 20
  seconds to observe and understand the terrain into which it has
  driven.

Title: Why are Mars rovers so slow?

Body:
Mars rovers are typically very slow. Curiosity, for example, has average speed of about 30 meters per hour.

Why is it designed so slow? Is it because of some specific power restrictions or for other reasons? What is the top reason why it is so slow?


问:
Driver Board to Control 16 Brushed DC Motors
I am building a humanoid robot with DC motor actuated fingers. There are 16 brushed DC motors to be position controlled with help of hall effect sensors implanted at the joints of each fingers. I need a developed driver board to control these 16, 3 watt, 12 v,DC motors.
Also each motor is equipped with an incremental encoder for speed control.

thank you

答:
Given that the brushed DC motors you are using can output a maximum power of 3 watts and are rated for 12 volts maximum, the max current will be 0.25 amps or 250 milliamps.  So you need to find something that can handle those specs.

In the most straightforward approach you have two options.  Either you can opt to use a dedicated driver board (e.g. like the adafruit motor shield) or you can use a dedicated IC that can serve the same function but at a fraction of a cost.  Given that you need to control 16 brushed DC motors, the IC route would probably be the most cost-effective.

Personally I have used the SN754410NE Quad Half-H Driver.  The interesting thing about this IC driver is you can control 2 DC motors in either direction and with supply voltages of up 36 volts and drive currents of up to 1 amp, which is suitable for your application.  If you're going to control brushless DC motors, then that's a different story.


问:
Particle Filter Sampling Step
I emphasize that my question is about sampling, not resampling.

I'm reading the Probabilistic Robotics book by Thrun et al, Chapter 4 on Non-Parametric Filters.  The section on Particle filters has an algorithm which states that for each particle index $m$ (see line 4):

sample $x_t^{[m]} \sim p(x_t|u_t,x_{t-1}^{[m]})$

The text's explanation of this step is quoted as:

Line 4. generates a hypothetical state $x_t^{[m]}$ for time t based on
  the particle $x_{t-1}$ and the control $u_t$.  The resulting sample is
  index by $m$, indicating that it is generated from the $m$-th particle
  in $\chi_{t-1}$.  This step involves sampling from the state
  transition distribution $p(x_t|u_t,x_{t-1})$.  To implement this step,
  one needs to be able to sample from this distribution.  The set of
  particles obtained after $M$ iterations is the filter's representation
  of $\bar{bel}(x_t)$.

If I understand correctly, this step says that the m-th sampled particle $x_t^{[m]}$ is obtained by advancing the previous m-th particle with control command $u_t$.  I assume that the motion is not deterministic, so the result of this motion is a conditional probability, based on the particle's previous position $u_t$.

However, I'm confused over how exactly to construct this conditional probability $p(x_t|u_t,x_{t-1}^{[m]})$.  Is this information usually given?  Or is it constructed from the distribution of the other particles?

答:
$p\left(x_t|u_t,x^{[m]}_{t-1}\right)$ should be created from your motion model. See chapter 5 in your book.
Algorithms can be found in table 5.3 for a velocity model or table 5.6 for a odometry model.

Roughly speaking: If your robot has a speed of 1m/s and it moves straight (which may be your $u_t$) and your update rate is 1Hz, then you could move each particle 1m forward. To respect the fact that nothing is known exactly you could then disturb each position by adding some position noise.

Title: Particle Filter Sampling Step


答:
The new particle should be created from your motion model, basically you select one random possible outcome of the data you measured.
This is an example for differential drive, the random.gauss calls are resoponsible for the sampling part:</p>

```<code>def update_sample(self, sample, left_ticks, right_ticks):
    """ Returns a new sample updated according to measured movement."""
    left_distance = left_ticks * self.left_resolution * random.gauss(1, self.left_sigma)
    right_distance = right_ticks * self.right_resolution * random.gauss(1, self.right_sigma)
    forward = (left_distance + right_distance) / 2
    turn = (right_distance - left_distance) / self.wheel_base
    alpha = sample.heading + turn / 2

    sample = copy.copy(sample)
    sample.x += math.cos(alpha) * forward
    sample.y += math.sin(alpha) * forward
    sample.heading += turn
    return sample
</code>```

Title: Particle Filter Sampling Step

Body:
I emphasize that my question is about sampling, not resampling.

I'm reading the Probabilistic Robotics book by Thrun et al, Chapter 4 on Non-Parametric Filters.  The section on Particle filters has an algorithm which states that for each particle index $m$ (see line 4):

sample $x_t^{[m]} \sim p(x_t|u_t,x_{t-1}^{[m]})$

The text's explanation of this step is quoted as:

Line 4. generates a hypothetical state $x_t^{[m]}$ for time t based on
  the particle $x_{t-1}$ and the control $u_t$.  The resulting sample is
  index by $m$, indicating that it is generated from the $m$-th particle
  in $\chi_{t-1}$.  This step involves sampling from the state
  transition distribution $p(x_t|u_t,x_{t-1})$.  To implement this step,
  one needs to be able to sample from this distribution.  The set of
  particles obtained after $M$ iterations is the filter's representation
  of $\bar{bel}(x_t)$.

If I understand correctly, this step says that the m-th sampled particle $x_t^{[m]}$ is obtained by advancing the previous m-th particle with control command $u_t$.  I assume that the motion is not deterministic, so the result of this motion is a conditional probability, based on the particle's previous position $u_t$.

However, I'm confused over how exactly to construct this conditional probability $p(x_t|u_t,x_{t-1}^{[m]})$.  Is this information usually given?  Or is it constructed from the distribution of the other particles?

Body:
The new particle should be created from your motion model, basically you select one random possible outcome of the data you measured.
This is an example for differential drive, the random.gauss calls are resoponsible for the sampling part:

def update_sample(self, sample, left_ticks, right_ticks):
    """ Returns a new sample updated according to measured movement."""
    left_distance = left_ticks * self.left_resolution * random.gauss(1, self.left_sigma)
    right_distance = right_ticks * self.right_resolution * random.gauss(1, self.right_sigma)
    forward = (left_distance + right_distance) / 2
    turn = (right_distance - left_distance) / self.wheel_base
    alpha = sample.heading + turn / 2

    sample = copy.copy(sample)
    sample.x += math.cos(alpha) * forward
    sample.y += math.sin(alpha) * forward
    sample.heading += turn
    return sample


答: I've had good experience with pololu motor drivers. They have a decently wide selection of brushed DC motor controllers here. And in Particular I think this one would suffice according to your specs. Its one of their light weight controllers and it is still capable of handling up to 3A peak current per motor channel or 1A continually. That seems plenty more than you'd need as your setup only demands 0.25A per motor. A single controller would handle two motor channels so you'd need a few of those.</p>

Title: Driver Board to Control 16 Brushed DC Motors

Body:
I am building a humanoid robot with DC motor actuated fingers. There are 16 brushed DC motors to be position controlled with help of hall effect sensors implanted at the joints of each fingers. I need a developed driver board to control these 16, 3 watt, 12 v,DC motors.
Also each motor is equipped with an incremental encoder for speed control.

thank you


答:
It has more to do with the rocker bogie suspension than anything else.

The system is designed to be used at slow speed of around 10 cm/s, so as to minimize dynamic shocks and consequential damage to the vehicle when surmounting sizable obstacles.

In exchange for moving slowly, the rover is able to climb rocks that are double the wheel diameter (normal suspension has trouble with anything over half the wheel diameter).  This is important when travelling in — literally — an alien landscape.

(image via http://en.smath.info/forum/yaf_postst995p2_Animation-of-mechanisms.aspx)

There are other benefits that come with slow speed: better correlation between successive frames captured by its navigation cameras, more time to plan its path, and power savings.  However, without the capabilities provided by the suspension system — surmounting the obstacles present on the martian surface without getting stuck or causing damage — the other benefits are moot.

Title: Why are Mars rovers so slow?


问:
Sending commands to Roomba from PC
I'm trying to send some commands to the Roomba. However is behaving strange.

This is the manual that I'm using.
http://www.irobot.com/~/media/MainSite/PDFs/About/STEM/Create/create_2_Open_Interface_Spec.pdf

First of all. I have consulted several manuals, some of them say that the default baudrate is 115200, however it works for me at 57200.

I'm trying to get a response from the Roomba sending the following comand

Examples:
• To turn on iRobot Create’s Play LED only:
128 132 139 2 0 0

However, the Roomba goes crazy and start going around. Any idea what's happening or what I'm not doing? Or what should I do first?

Thank you.

答:
iRobot Create and Rommba does not support the same functionality. A SCI manual for the Roomba could be found here: Roomba SCI spec.

It works for me by sending plain byte sequence's.

Could you add some more information to your question:

How do you connect to the Roomba physical?

How are you sending data to the Roomba logical?

Meta Remark: I would like to use the comment function but do not have enough reputation.

Title: Sending commands to Roomba from PC


问:
Basic general question about controllers
Suppose I have a mechanical system which is free to move on a given rail [-5m, 5m] like a motorized cart. The whole system can be mathematically expressed through a linear timeinvariant system equations.

If I need to control only the position (for example saying the controller: "move to +2.3") I can simply design a PID controller that, given a set point moves the cart to that position.

Now I need much more and I want to control the position and the velocity of the cart. So I need for example to say: "move to +2.3 with a specific velocity's profile". Of course the vel = 0 at the end position.

Question: how should I design such a controller? Do I need specifically a special type of controller? Or I have a huge choice?

Any help, graph, link and example is really appreciated.

Regards

答:
PID would work just fine. Your system can be easily modeled as a linear system and is relatively easy to control. When you want to choose a control method, you need to know the dynamics of your system, computation resources, and how much you wanna go deep into mathematical stuff(one reason why so many people choose PID).

To solve your control problem using PID, you need to define your X and Y as functions of time based on your desired velocity. So you will have:
$$ X(t), Y(t)$$

Or in case of moving on a rail, define travel distance as a function of time. Then in each iteration of your control loop you know where the cart was supposed to be and where it really is. The difference is the error that you should put in PID equation. It might not always be so straight forward. In most of multi-output control systems error is a mix of multiple state errors(such as path tracking in 2D with differential wheel robots).

The Matlab code below might help you better understand the process. In case you don't have access to Matlab, Octave should be able to run the code too(maybe with some small adjustments).

I've assumed that there is a rail that looks like this:

And you want to move on it with a velocity profile like this:

Then follow this example:

```<code>clc; clear all; close all

%% Path setup
path_step = transpose(0:.01:500);
x_path = path_step/17 + 2*sin(path_step/50);
y_path = sqrt(path_step) + 5*sin(path_step/10);

position_matrix = [x_path,y_path];
distance_between_points = diff(position_matrix,1);
dist_from_vertex_to_vertex = hypot(distance_between_points(:,1), distance_between_points(:,2));
cumulative_dist_along_path = [0; cumsum(dist_from_vertex_to_vertex,1)];

%% Cart setup
saturation_limit = 4;
motor_coef = .5;
motor_model = @(input_command) min(saturation_limit, max(-saturation_limit, input_command * motor_coef)) + .3 * randn(1);
k_p = 3;
k_i = 1;
k_d = .1;

%% Simulation and initial conditions setup and array initialization
time_step = .1;
sim_time = 100;
t = transpose(0:time_step:sim_time);
distance_actual = zeros(size(t));
err = zeros(size(t));

err_integrated = 0;
err_derivative = 0;
distance_actual(1) = 20; % actual starting point

%% Desired trajectory following pattern
velocity = .5 + 2*sin(t/13).^8;
velocity=[velocity(1:end-100); zeros(100,1)];
reference_starting_point = 40;
desired_travel_distances = cumsum(velocity .* time_step,1) + reference_starting_point;
desired_trajectory = interp1(cumulative_dist_along_path, position_matrix, desired_travel_distances);
x_pos = desired_trajectory(:,1);
y_pos = desired_trajectory(:,2);

%% Run simulation
for sim_step = 1:sim_time/time_step
    err(sim_step) = desired_travel_distances(sim_step) - distance_actual(sim_step); % calculate error
    err_integrated = err_integrated + err(sim_step) * time_step;
    if sim_step>1
        err_derivative = (err(sim_step) - err(sim_step-1)) / time_step;
    end
    u_motor = k_p * err(sim_step) + k_d * err_derivative + k_i * err_integrated; % apply PID magic and calculate control input
    actual_velocity(sim_step) = motor_model(u_motor); % Send the command to the motor and it will have a new velocity based on that
    distance_actual(sim_step+1) = actual_velocity(sim_step) * time_step + distance_actual(sim_step); % calculate traveled distance from new
end

%% How good it follows the desired velocity pattern
figure()
title('Velocity Profile')
xlabel('Simulation Step')
ylabel('Velocity')
plot(velocity,'LineWidth',3)
hold on
plot(actual_velocity, ':')
hold off
legend('Desired', 'Actual')

%% Error analysis
figure()
title('Error')
xlabel('Simulation Step')
ylabel('Error')
plot(err)

%% Make an animation
actual_position = interp1(cumulative_dist_along_path, position_matrix, distance_actual);
figure()
title('Simulation')
xlabel('X')
ylabel('Y')
plot(x_path, y_path)
hold on
h1 = plot(x_pos(1), y_pos(1), 'rx');
h2 = plot(actual_position(1, 1), actual_position(1, 2), 'ko');
legend('Path', 'Desired Position', 'Actual Position')
disp('Press key ...')
waitforbuttonpress()
for sim_step=1:sim_time/time_step
    delete(h1)
    delete(h2)
    clc
    disp('Time:')
    t = sprintf('%0.3f', sim_step * time_step);
    disp(t)
    h1 = plot(x_pos(sim_step), y_pos(sim_step), 'rx');
    h2 = plot(actual_position(sim_step, 1), actual_position(sim_step, 2), 'ko');
    drawnow
    pause(.05)
end
clc
disp('Finished!')
</code>```

Body:
PID would work just fine. Your system can be easily modeled as a linear system and is relatively easy to control. When you want to choose a control method, you need to know the dynamics of your system, computation resources, and how much you wanna go deep into mathematical stuff(one reason why so many people choose PID).

To solve your control problem using PID, you need to define your X and Y as functions of time based on your desired velocity. So you will have:
$$ X(t), Y(t)$$

Or in case of moving on a rail, define travel distance as a function of time. Then in each iteration of your control loop you know where the cart was supposed to be and where it really is. The difference is the error that you should put in PID equation. It might not always be so straight forward. In most of multi-output control systems error is a mix of multiple state errors(such as path tracking in 2D with differential wheel robots).

The Matlab code below might help you better understand the process. In case you don't have access to Matlab, Octave should be able to run the code too(maybe with some small adjustments).

I've assumed that there is a rail that looks like this:

And you want to move on it with a velocity profile like this:

Then follow this example:

clc; clear all; close all

%% Path setup
path_step = transpose(0:.01:500);
x_path = path_step/17 + 2*sin(path_step/50);
y_path = sqrt(path_step) + 5*sin(path_step/10);

position_matrix = [x_path,y_path];
distance_between_points = diff(position_matrix,1);
dist_from_vertex_to_vertex = hypot(distance_between_points(:,1), distance_between_points(:,2));
cumulative_dist_along_path = [0; cumsum(dist_from_vertex_to_vertex,1)];

%% Cart setup
saturation_limit = 4;
motor_coef = .5;
motor_model = @(input_command) min(saturation_limit, max(-saturation_limit, input_command * motor_coef)) + .3 * randn(1);
k_p = 3;
k_i = 1;
k_d = .1;

%% Simulation and initial conditions setup and array initialization
time_step = .1;
sim_time = 100;
t = transpose(0:time_step:sim_time);
distance_actual = zeros(size(t));
err = zeros(size(t));

err_integrated = 0;
err_derivative = 0;
distance_actual(1) = 20; % actual starting point

%% Desired trajectory following pattern
velocity = .5 + 2*sin(t/13).^8;
velocity=[velocity(1:end-100); zeros(100,1)];
reference_starting_point = 40;
desired_travel_distances = cumsum(velocity .* time_step,1) + reference_starting_point;
desired_trajectory = interp1(cumulative_dist_along_path, position_matrix, desired_travel_distances);
x_pos = desired_trajectory(:,1);
y_pos = desired_trajectory(:,2);

%% Run simulation
for sim_step = 1:sim_time/time_step
    err(sim_step) = desired_travel_distances(sim_step) - distance_actual(sim_step); % calculate error
    err_integrated = err_integrated + err(sim_step) * time_step;
    if sim_step>1
        err_derivative = (err(sim_step) - err(sim_step-1)) / time_step;
    end
    u_motor = k_p * err(sim_step) + k_d * err_derivative + k_i * err_integrated; % apply PID magic and calculate control input
    actual_velocity(sim_step) = motor_model(u_motor); % Send the command to the motor and it will have a new velocity based on that
    distance_actual(sim_step+1) = actual_velocity(sim_step) * time_step + distance_actual(sim_step); % calculate traveled distance from new
end

%% How good it follows the desired velocity pattern
figure()
title('Velocity Profile')
xlabel('Simulation Step')
ylabel('Velocity')
plot(velocity,'LineWidth',3)
hold on
plot(actual_velocity, ':')
hold off
legend('Desired', 'Actual')

%% Error analysis
figure()
title('Error')
xlabel('Simulation Step')
ylabel('Error')
plot(err)

%% Make an animation
actual_position = interp1(cumulative_dist_along_path, position_matrix, distance_actual);
figure()
title('Simulation')
xlabel('X')
ylabel('Y')
plot(x_path, y_path)
hold on
h1 = plot(x_pos(1), y_pos(1), 'rx');
h2 = plot(actual_position(1, 1), actual_position(1, 2), 'ko');
legend('Path', 'Desired Position', 'Actual Position')
disp('Press key ...')
waitforbuttonpress()
for sim_step=1:sim_time/time_step
    delete(h1)
    delete(h2)
    clc
    disp('Time:')
    t = sprintf('%0.3f', sim_step * time_step);
    disp(t)
    h1 = plot(x_pos(sim_step), y_pos(sim_step), 'rx');
    h2 = plot(actual_position(sim_step, 1), actual_position(sim_step, 2), 'ko');
    drawnow
    pause(.05)
end
clc
disp('Finished!')


问:
I want my stepper motor to switch speed while traveling (not acceleration wise)
I have this project I'm working on where I'll need the speed of the stepper motor to change set speed at a certain distance, I just can't figure out a way to do it. I'm using arduino and a stepper motor, this is the current code.

```<code>#include <AccelStepper.h>

AccelStepper stepper1(AccelStepper::FULL4WIRE, 0, 1, 2, 3);

void setup()
{
    stepper1.setMaxSpeed(200.0);
    stepper1.setAcceleration(400.0);
    stepper1.moveTo(5000);

}

void loop()
{
    // Change direction at the limits
    if (stepper1.distanceToGo() == 0)
    stepper1.moveTo(-stepper1.currentPosition());
    stepper1.run();
</code>```

What I want it to do basically is to first moveTo(2500)  at the current speed 200 then after 2500 I want it to increase speed to 400. After it has moved 5000 it turns and moves back to position but that's implemented already.

答:
```<code>#include <AccelStepper.h>

//AccelStepper Xaxis(1, 2, 5); // pin 2 = step, pin 5 = direction
AccelStepper Xaxis(1, 12, 6); // pin 3 = step, pin 6 = direction

void setup()
{
  Xaxis.setMaxSpeed(4000);

  //Xaxis.setSpeed(10);
  pinMode (3, INPUT);
}

void loop()
{
   //Xaxis.runSpeed();
   if (digitalRead (3) == HIGH)
   {
     //Xaxis.stop();
     Xaxis.setSpeed(20);

     Xaxis.runSpeed();
   }

   if (digitalRead (3) == LOW)
   {
     Xaxis.runSpeed();
     Xaxis.setSpeed(-10);  // - sign change direction !!!!!
   }
}
</code>```


问:
How to find the body jacobain, for each link in a robot manipulator?
The links twist could be obtained, and thus The spatial manipulator Jacobian could be done, but when it comes to the body Jacobian, it is becomes difficult. Moreover, the adjoint transformation relates both Jacobain, but however that is 4*4 while the Jacobian is 6*n; how does it works? as in the picture, he is getting a body jacobian for each link, not one jacobian matrix for the whole robot, I don't know.
Any help is highly regarded.
Like this example or here for
full details</p>

答:
Finally, I got it 'praise to Allah'.
Actually, I made a mistake on how to find the adjoint (Ad)of the matrix $ j$ .
I simply used the adjoint function in matlab, but that wasn't the right approach; the (Ad), has specific formula given by:
$ Adj = \begin{bmatrix} R(j)^T & -R(j)^Tp(j) \\ zeros(3) & R(j)^T] \end{bmatrix} $;
Where $ R(j)  $ and $p(j)$ are the rotational part and the position vector of the $ 4 \times 4$ matrix $j$.


答:
This seems like a softball question but is surprisingly subtle. There are some excellent answers here, but I can add some basic rigor.

The reason the rovers move so slow is essentially the need to be cautious with a multi-million-dollar piece of equipment. But there are some other design constraints worth mentioning.

Energy is simply the worst bottleneck for mobile, autonomous systems. The energy cost for a system to relocate across a surface can be typically modeled as
$$ \int^{T_{final}}_{T_{initial}} [ c_0 v(t)^2 + c_1 a(t)^2 + c_3v(t) + c_4a(t) + c_5v(t)*a(t) + C ]dt $$ where $c_0...c_6$ are constants representing the motor parameters (see here and here).
So the cost of travelling to a nearby crater is proportional to the square of the velocity and square of the acceleration. Thus, slower costs less power overall. There is usually a "tipping speed" at which the power consumption spikes, and this is usually a very slow speed. Thus, robots move slow to save power. Additionally, this means a robot cannot carry energy-intensive sensors like LIDAR. Note LIDAR is used extensively in autonomous, driverless vehicles like the Google Car. Which brings me to...

Computational Sensing. Note, we're not considering power. Now, we have to realize that the robot is autonomous (i.e., driver-less). Given the reduced sensors, a robot cannot model its whole environment, and plan a large route. Think of it this way, would you run through the forest in the dark? Not if you didn't need to. The robot is constantly "in the dark" since it cannot see very far ahead, so it moves slowly, carefully planning each step. The memory and cpu required to plan these things is $O(r^3)$ or worse, where $r$ is the radius of planning. see here and here

Communication Delays. As mentioned, the robot is i) autonomous, and ii), sensing-limited. The humans have to constantly "check-in" to make sure the robot isn't doing something stupid (despite its state of the art planning algorithms). This means the robot will wait for instructions a lot, thus slow average progress towards a goal. The previous references address this.

Stability. To achieve stability / robustness, the rovers use the rocker-bogie system. see this. This system is designed to be operated at slow speeds. If you go fast, and hit a rock, you break your rover. Try to imagine doing that sensor-based motion planning.  Now try to do so when all your relevant sensors are on a mast attached to the top of your robot, and you'll see that keeping the sensing payload stable is very important.

Title: Why are Mars rovers so slow?


问:
Robotics SLAM datasets - scaling factor
There are several robotics datasets for SLAM, like this one.

In this webpage you can see that the depth image is scaled by a factor of 5000, so that float depth images can be stored in 16 bit png files:

```<code>The depth images are scaled by a factor of 5000, i.e., a pixel value of 5000
in the depth image corresponds to a distance of 1 meter from the camera, 10000
to 2 meter distance, etc. A pixel value of 0 means missing value/no data.
</code>```

I do not understand why this value is chosen. Why not simply 1000, so that there is a conversion of meters to millimeters?

答: PNG does not support float numbers (afaik). Hence the depth value needs to be encoded as a fixed point value. The fixed point was chosen, I guess, to get a good trade-off between accuracy (0.2 mm) and range (13 m). </p>

Title: Robotics SLAM datasets - scaling factor


问:
What type of servos are used in industrial robot arms like Universal Robot UR5?
I've noticed that the industrial robot arms have very smooth, fast, and strong movement.  Does anyone know what type of servos they use.  I'm trying to build my own and don't want to have the jerky movement that is seen in a lot of DIY robot arms?  Thanks. </p>

答:
Universal states that they use brush-less DC motors with harmonic drives on their FAQ here http://cross-automation.com/blog/universal-robots-top-10-faqs

Bigger ones like the KUKA KR5 uses AC servo motors. From the conversation here https://support.industry.siemens.com/tf/ww/en/posts/kuka-servo-motor/87265/?page=0&pageSize=10#post344333 it looks it is a custom version of the Siemens IFK7 synchronous motor series. Many of these high end motors can have holding brakes, better quality bearings and drive mechanisms and very good control systems that prevent them from jerking like a DIY arm. In a DIY robot, joints are typically connected straight to the motor with no drive mechanism and the basic control system does not provide a lot of options for smooth motion.


问:
Internal Pullup Sufficient for i2c in beaglebone Black?
I plan to use P8.13 and P8.15 of the beaglebone in a i2c bitbang mode.
Do i need to use external pull up resistors in my circuit? or can i use the internal pull up which is available on the beaglebone black itself?</p>

答:
It depends on how big the pull-up resistor is and how fast you want to go with I2C. If Beaglebone designates those pins as usable for I2C, the internal pull-up resistor is most likely sufficient.

Generally, the smaller the pull-up resistor, the faster is the rise of the signal to 1, but when driving a 0, there is also higher consumption. To understand this better, think about the extremes; what would be the behavior if the pull-up resistor is 0? How about infinite?

To be perfectly sure, you need an oscilloscope. With the frequency at which you want to communicate over I2C, drive a square wave over the pin configured with pull-up and check to see if the signal rises "fast enough".


问:
Parameter $r$ of Denavit-Hartenberg
By watching this video which explains how to calculate the classic Denavit–Hartenberg parameters of a kinematic chain, I was left with the impression that the parameter $r_i$ (or $a_i$) will always be positive. </p>

<p>Is this true? If not, could you give examples where it could be negative? </p>

答: Parameter "r" or "a" is the link length of a robot's link which is a physical entity. And that can never be negative. </p>

Title: Parameter $r$ of Denavit-Hartenberg


问:
Implementation of wall and obstacle avoidance
I have a task of developing a simulation of an adaptive robot control system but I don't seem too have anyone to discuss my uncertainties with. I want to keep the simulation as simple as possible as I have a very tight deadline and it's only a one off project that most probably will never be used in my life again.

The minimal behaviour that the agent is supposed to exhibit is wall and obstacle avoidance. It can be extended to avoiding small objects and exploring large ones.

I've decided to go with a simple feedback control system.
To begin with I'm struggling to decide how to represent the map of agent's environment. What I mean is, what if I want a wall to be from coordinate [0,0] to [0.5]. I could hard code it, e.g. have a matrix with coordinates of all obstacles but how small units do I make... I.e. what if I have two neighbouring coordinates [0,0.01] and [0,0.02] but the agents gets a 'clear to go' to coordinate [0,0.05]. In this case it doesn't know that it actually is about to walk into a wall. I've heard of something called occupancy grid map but I don't exactly get how it works and how to implement it.

Another thing that I am struggling with is how do I distinct between a wall and an obstacle? And then, how do I let the agent know how big that obstacle is so that it can either avoid it or explore it.

Eh, I'm really puzzled with this project.
I would really appreciate any thoughts or directions. Thank you. :-)

答:
There's a lot of questions here, so I expect pushback from the peanut gallery, but I'll answer what I can.

First off, a wall is an obstacle, right? There's no difference there other than what words you use to describe "a place a robot cannot go".

So now, we just need a way to store the locations of obstacles so that we know where the robot can go. This is your map.  One way of storing this map, as you mentioned, is an occupancy grid.

An occupancy grid (for two dimensional environments, like a floor) is simply an N by M matrix of numbers. In each "cell" we store the probability that an object is present. Cells that contain a zero are known to be clear (unlikely objects). Cells with a 1 are obstacles.

Here, N and M are the dimensions of the area.  If your workspace is 10 meters by 10 meters, and your robot is small, then a reasonable choice of N and M is 10x10.   This gives you a resolution of one square meter per cell.  For higher resolution, 100x100 would give you a tenth of a meter resolution. Good enough for navigating an iRobot Create, in my experience.

How you fill these cells is up to you. If you know that a wall goes from [0,0] to [5,5], for example, you can fill each cell between those two points with ones.

Sidebar

So why wouldn't we use this representation? Well one reason is the space the map takes up. If you are navigating in a hallway, you really only need to know that it is bounded by two lines. So storing the length and position of these lines is enough. That's a small number of variables to represent any length or size of hallway. With an occupancy grid, we'd have to store all of the cells to understand the configuration of the hallway.

However, occupancy grids are probably the most modular, extensible, flexible, etc mapping techniques.

How to "fill" the cells

Great question. You'd want to fill all cells that the line touches. To see if a line goes through a certain cell, you can check if the line (ray) collides with the cell (box). Since the box is aligned with the X and Y axes, this is known as the Axis-Aligned Bounding Box intersection problem. see this question. This may not be the best way to "fill" the cells, as you may have to iterate over the whole map. here is a way to find all cells intersected by a line.


问:
How to convert vertical motion to horizontal?
I am interested in using this miniature motor Squiggle Micro Motor to create very tiny horizontal movements. However, due to very limited space, I can only place it vertically within my project.

Assuming this motor is placed as follows, how can one adapt it to simultaneous movement at a right angle? (Ideally with the X-axis movement matched to the Y-axis movement as well as possible.)

答: To make a 89 degree turn you need a miter gear.  Amazon has a plastic one that is approximately 2 inches (5 cm) across the face This is by Boston Gear GP1632Y Miter Gear, 0.500" Bore, 1:1 Ratio, 20 degree Pressure Angle, 16 Pitch, 32 Teeth, Molded Nylon.  there is another one shown with a 1 inch face and a 14 degree pressure angle and 14 teeth.  Miter gears always need to be purchased in pairs to mesh properly.  This can be used by attaching a small motor or a manual crank to activate the mechanism you are trying to move. </p>


问:
How can I power a wheel but let it spin freely when not under power?
How can I power a wheel but let it spin freely when not under power?

I saw the question How can I modify a low cost hobby servo to run 'freely'? but I'm more interested in knowing if there is some sort of gearbox that disengages ( moves to 'neutral' ) when no torque is being applied to it.

Two ideas that come to mind are:

A drive gear on a spring loaded arm with a nominal amount of resistance before engaging. Perhaps when under power it would first use power to move in one direction, then it would engage with another gear, but without power the spring would return it to a non-engaged position

A centrifugal clutch - although I'd like something that works at low RPMs as well

The idea is to create a small bot that can move up and down a track, but if someone interacts with it when not under power it will just roll and won't damage the gearbox.

答:
You can use a magnetic clutch. When the strain on the horn passes a particular mark, it overpowers the pairs of magnets holding the clutch plates causing it to slip without damaging the gears. You can easily make them, and here is a company selling them http://robosavvy.com/store/dagu-magnetic-servo-clutches-for-miniature-servos.html

If you want to use an off the shelf one there are clutches designed for r/c cars that you maybe able to use. There is a description of one here http://nitrorc.com/articles/clutch.html and here is a company that sells them http://www.bukupower.com/clutch.aspx .These are designed for use with gas vehicles so some modification to your design maybe required.

It may also not be too hard to make a gear train disengagement mechanism you can control using a servo.


问:
Recommendation for good source of Robotic Components
Im looking for a good source for robotic components like sheel/tracked robot chasis, motors, sensors, communication and mechanics. I thought about using raspberry and arduino as platforms for automation, is that an good idea? Im asking as i dont know yet much about the motors/drives uses for powering robots.

Thanks!

Uli

答:
Some reputable sources of getting robot parts are:

Adafruit

Robotshop

Robot Marketplace

Pololu

Jameco Robot Store

Trossen Robotics

HobbyKing

If you need to get specialized electronic parts (e.g. microcontrollers, transistors, etc.) then you might want to look into:

Digi-Key

Jameco

Newark Element 14

These are only to name a few to help you get started.


问:
Why does our LM2576 circuit suddenly cut down the power?
I have an LM2576 circuit plus an adjuster to adjust the output voltage, for controlling motor speed in a line follower robot. The circuit works great when adjusted to give out low voltages, but when I adjust it to higher voltages for my motors to go faster, it works great for 1-2 minutes, then suddenly cuts down the power and motors start to go extremely slow.

Even when I decrease or increase the output voltage, it won't respond until I turn off the power and turn it back on again. There is something mentioned in the LM2576 datasheet that if we overload the IC it will cut down the power until the load comes lower, so I think it might be a problem with that.

Since this problem has already caused us to lose the competitions with 5+ teams, I would like to solve it for our next competition, so why does our LM2576 circuit suddenly reduce the power?

答:
According to the datasheet, there are three possibilities: TTL shutdown, thermal shutdown and current limiting.

From what I looked up, TTL shutdown means simply that you have a pin you can use to cut-off the regulator output current. My guess is that it is pin 5 and you simply grounded it, as seen in the typical application circuit, so that possibility can be eliminated.

Since the circuit works great for 1-2 minutes and then shuts down, my guess is that you are not properly heatsinking and the regulator is going through thermal shutdown.

If the IC isn't feeling hot enough, however, then you can probably assume current limiting. In that case, you have to investigate why your circuit is demanding so much current (probably a flawed design).


问:
Sporadic sensing rates for hc-sr04 ultrasonic distance sensor
Been working on a robot recently which uses ultrasonic sensors for an integral part of the navigation.
While testing the sensors I noticed a strange behaviour, the sensors seem to frequently stop functioning and bring the entire Arduino Mega I'm working with to a stop. The strange part is that these stops seem to be entirely random, on some occasions the sensor will read values consistently (at maybe 20 vals per second) for 10+ seconds, then all of a sudden the sensor will slow to reading only 2-3 values per second with stalls between.

I have tested several sensors and different codes for pinging distances yet the problem has persisted.

This leads me to believe the issue is with the arduino mega itself, but I am unsure how to verify this. Any advice?
Thanks in advance!

PS: other pins on the Mega seem to be working fine, i.e. analog pins for IR reflectance sensors and PWM pins for driving 2 DC motors.

答:
Looking at the signal waveform in the datasheet of the HC-SR04 ultrasonic sensor, we can see that measuring the "echo back" pulse is proportional to the distance between the sensor and the object in front.

To be able to time this "echo back" pulse, this would require the use of an interrupt and a timer which is ubiquitously found in many microcontrollers.  That is an interrupt will be used to detect the rising edge of the signal to start the timer and the falling edge of the signal to stop the timer.

Assuming that you are using the Arduino Mega 2560 (the concepts can also apply to the Arduino Mega as well), browsing through the datasheet of the ATmega2560 microcontroller found on the board, the Input Capture Unit elaborated on page 140 will be able to achieve this task.

It is very critical that you time this pulse with an interrupt.  The microcontroller can only execute one instruction at a time, so using a regular input/output pin and polling the pins to time this pulse could introduce latency into the system.  For example the code could be executing at some other place in the program and at the same time there is a change in the pulse signal, thus effectively missing the measurement and producing an incorrect result.

What you need to do is figure out whether the code you are using is employing the Input Capture Unit.  If not,then see how the Input Capture Unit maps to the header pins of the Arduino Mega 2560 and how to enable the feature in the code (e.g. using an Arduino library, statements, etc.)


问:
I need the specifications for iRobot Create 2
I need the specifications for the Create 2. I need it for research purposes. So I think I'm going to need a high computational computer on board.

Please suggest some nice configuration.

答:
I'm not sure which specifications you're asking about, but the manual is here.

As far as "nice configuration," it really depends on what you're up to. A Raspberry Pi 2 can run ROS reasonably well, and is relatively inexpensive. As a bonus, there's a write-up on how to hook up a Pi here. You could also use a netbook with the supplied Create 2 to USB cable.

Please note that I am an iRobot employee, but the postings on this site are my own and don't necessarily represent iRobot's positions, strategies, or opinions.