问:
Suggestion for relevant non-complex simulator
I've recently started working on some localization algorithms like probabilistic road map and SLAM algorithms. What I'm looking for is a software that would help me in simulation for such algorithms. I started with pythons graphics.py and have now started working with Gazebo and ROS, but I've found it complex to use.

Is there any similar freeware simulation software that is easy to setup and work with, thus allowing me to reduce my time stressing over the simulation part and working more on the algorithms?

答:
ZeroSim is built with Unity.  It's not necessarily "easy" but arguably easier then Gazebo.  Definitely creating and iterating environments in ZeroSim is much easier then Gazebo.

Disclosure:  I am a ZeroSim developer.


问:
Having Issues Importing and Using RLGlue locally with Python For Reinforcement Learning
I'm going through an online course on Coursera for Reinforcement Learning that makes use of RLGlue. I want to try to run and adapt the code locally, but am having issues using RLGlue, and not sure why.

I was going through an Reinforcement Learning Course and wanted to try running the code locally. I installed RLGlue with pip install rlglue from here

But then when trying to run the code:

```<code>from rlglue.rl_glue import RLGlue
import main_agent
import ten_arm_env
import test_env
</code>```

Received this error message: ModuleNotFoundError: No module named 'rlglue.rl_glue'

I also attempted to install it from here that supports the course, and with
pip install git+https://github.com/andnp/coursera-rl-glue.git@0.1
but that didn't work either.

Any idea on how to fix that to import the module and run the code?

答:
This worked for me:
from RLGlue.rl_glue import RLGlue
This is only with the Coursera version of RLGlue</p>

ContentLicense: CC BY-SA 4.0


问:
I need to make something that can slam something into something else really fast in both directions
I'm fairly new to robotics, but I have this idea for a machine. I've done a bit of research but can't find exactly what I'm looking for. I need something that can either move back and forth at at least a 90 degree angle (like swinging a bat), changing direction on-the-fly, or something that can push an object into a wall really fast, moving back and forth with little-to-no lag time between switching directions (like a fast piston). The object being moved will be 3 to 5 pounds and it needs to be slammed against a solid surface with roughly the force of a punch.

I spent all day yesterday researching it and haven't found much. I was thinking a piston would be good, but I can't find one that moves in and out quickly enough to generate the force I need. I then thought servos sounded good, but I could only find tiny ones for little robots. A motor now seems like the best bet, but I haven't been able to find a way to make one change direction on-the-fly. I have one from an old bandsaw, but it seems like I need to rewire it any time I want to make it change direction. I know motor controllers exist for tiny robots that accomplish this but am not sure if there's something like that for a bigger motor.

答: A scotch yolk will do what I'm trying to accomplish.</p>


问:
Tuning PID controller for sharp turns in line follower robot
I'm working on a TWDD line-following robot using qtr-8a reflectance sensor array.
The sensors are connected to BeagleBone Black, and BBB is sending the speed serially to an arduino Due.
My approach is using a PID controller for the sensor so the error equals to zero when the robot is centred on the line and a positive/negative error depending on the robot's position. Applying Trial and error method I finally reached a Kp value that tracks straight lines perfectly. However, I'm still unable to turn and stay on the line even on a similarly smooth turns. I guess this is related to the Kd value. I'm not using the integral part Ki since the error is keep increasing. I tried to set conditions when the robots is drifting away from the line but it's not working probably (even without the conditions it is somehow turning smoother but then losing the line)
I'm using the following draft code:

```<code>from bbio import *
import time

integral = 0
last_prop = 0
Kp = 20
Ki= 0
Kd = 150
amax = list(0 for i in range(0,8))
amin = list(1024 for i in range(0,8))
timeout = time.time() + 10

# Read ADC data from MCP3008
# ch: 0-7, ADC channel
# cs: 0-1, SPI chip select
# See MCP3008 datasheet p.21
def adc_read(cs, ch):
    spidata = SPI1.transfer(cs, [1,(8+ch)<<4, 0])
    data = ((spidata[1] & 3) << 8) + spidata[2]

    return data

def setup():
# SPI1 setup
    Serial2.begin(9600)
    Serial5.begin(9600)
    pinMode(GPIO1_7, OUTPUT)
    digitalWrite(GPIO1_7, LOW)
    SPI1.begin()
    SPI1.setMaxFrequency(0,50000)  # => ~47kHz, higher gives occasional false readings
  #  SPI1.setMaxFrequency(1,50000)
    calibrate()

# reading the IR sensor data
def read_sensors():
    sensors = []
    for i in range(8):
        sensors.append(adc_read(0,i))

    return sensors
# calculating the error from PID controller
def calc_pid(x,sp):
    global  integral, last_prop , Kp, Ki ,Kd
    set_point = sp
    pos = sensor_average(x)/sensor_sum(x)
    prop = pos - set_point
    integral = integral + prop
    deriv = prop - last_prop
    last_prop = prop
    error = (prop*Kp + integral*Ki + deriv*Kd)/100

    return error

def get_position(s):
    return sensor_average(s)/sensor_sum(s)

def sensor_average(x):
    avg = 0
    for i in range(8):
        avg += x[i]*i*100

    return avg

def sensor_sum(x):
    sum = 0
    for i in range(8):
        sum += x[i]
    return sum

def get_sensor(x):
    j= read_sensors()[x]
    return j

def calc_setpoint(x,y):
    avg = 0
    sum = 0
    for i in range(8):
        avg += (x[i]-y[i])*i*100
        sum += x[i]-y[i]
    return avg/sum
# calibrate the sensors reading to fit any given line
def calibrate():
    global amin
    global amax

    while(time.time() < timeout):
        for i in range(0,8):
            amin[i] = min(amin[i],read_sensors()[i])
            amax[i] = max(amax[i],read_sensors()[i])
            digitalWrite(GPIO1_7, HIGH)
    digitalWrite(GPIO1_7,LOW)

# calculating the correspondent speed
def calc_speed(error):
    avg_speed = 150
    min = 100
    pos = get_position(read_sensors())
    speed = []
    if(error < -35):
        right = avg_speed -(2*error)
        left = avg_speed + (2*error)
    elif(error > 35):
        right =avg_speed - (2*error)
        left = avg_speed + (2*error)
    else:
        right = avg_speed - (error)
        left = avg_speed + (error)
    speed.append(right)
    speed.append(left)
    return speed

def loop():

    s = read_sensors()
    setpoint = calc_setpoint(amax,amin)
    position = get_position(s)
    err = calc_pid(s,setpoint)

    print err

    #print "divided by 100:"
    speeds = calc_speed(err)
    print speeds
    right_motor = speeds[0]
    left_motor = speeds[1]

    Serial2.write(right_motor)

    Serial5.write(left_motor)
    delay(10)

run(setup,loop)
</code>```

PS: the sent speed over serial is limited to 255 and I'm multiplying it by a factor from the Arduino side.

答:
I believe what you observe with the integral part is windup. You might fix that by limiting the overall value of the I part, or resetting it once the error is small or zeroes out or changes sign (zero crossing). All are known approaches dealing with windup (basically the integral keeps collecting until it saturates and then the system becomes unstable).

Gil

ContentLicense: CC BY-SA 3.0


问:
How to manage interrupts on an AVR?
I have a number of interrupt service routines on an AVR. These include interrupts for USART serial communication, timers, and SPI communication.

For all of these, I use circular queues (using a start and end pointer, without boundary checking).

Some problems start to occur if the AVR starts to get overloaded. The circular queues will lose chunks of data. To solve this, I can reduce the load on the AVR (for example, by skipping some cycles in the timer). However, this is a manual process, where it is reduced if the AVR appears to have problems. This is partly because I do want relatively consistent timer periods.

However, even at 70% average processor load, the queues can fill up randomly by chance.

In case of spurious overloading at times, how can I make this more adaptive to avoid queue overflows?

答:
It sounds like you're observing the symptom of "lost bytes". There are several different things that can cause an AVR to lose bytes.

It sounds like you are guessing that it's losing bytes when new bytes are coming in while the buffer is full. While there are several remedies to fix or at least ameliorate that particular problem, those approaches are useless and counter-productive if the real cause of the "lost bytes" is something else.

The first thing I would do in your shoes is to set up some sort of "status debug" port that gives me a clue of why exactly bytes have been lost -- at least a status LED. Once you know why bytes are being lost, you can apply the appropriate remedy.

Most modern protocols have some sort of check value at the end of each packet.
It's nice if your status debug system can report on the packet goodput rate and the packet error rate -- at least blink a green LED for each validated packet and a red LED for each failed packet check.

Since (especially with radio connections) the occasional corrupted byte is pretty much inevitable, most modern protocols are carefully designed such that if any byte is corrupted or lost, the system will eventually discard that packet, and eventually re-sync and correctly handle future packets.

Bytes lost because the interrupt handler somehow never put them into the buffer

Often bytes are lost because the interrupt handler somehow never put them into the buffer. There are several causes, each with a different remedy: external problems, and internal interrupts turned off too long.

External problems:

Line noise causing errors

Physical wired connections accidentally getting temporarily unplugged

Loss of signal on radio connections

Typically we clip an oscilloscope to the input pin and -- if we're lucky -- we can see the problem and try various techniques to see if that cleans up the signal.

Even when the signal at the input pin looks perfect, we can still have data loss issues.

Immediately after the last bit of a byte comes in a USART or SPI port,
normally the interrupt handler for that port is triggered, and that interrupt handler pulls that byte and sticks it into a circular buffer. However, if the interrupts are turned off too long, the next byte to come in that port will inevitably overwriting and losing the first byte -- the interrupt handler for that port never sees that first byte. The four "ways an interrupt handler can be turned off too long" are listed at "What can be the cause of an exceptionally large latency for the UART receive interrupt?".

To fix this problem, you need to get the longest time an interrupt handler is ever turned off to be less than the time to transfer one character. So you must either

Reduce the amount of time interrupts are turned off; or

Slow down the communication bit rate to increase the time to transfer one character;

Or both.

It's very tempting to write the interrupt routine such that, immediately after it puts a byte into the circular buffer, the same interrupt routine then checks to see if it's a complete packet and, if so, completely parse and handle it. Alas, parsing usually takes so long that any further bytes coming in the same or any other port are lost.

We typically fix this by reducing each interrupt handler (and therefore the time interrupts are disabled while processing this handler) to the minimum possible to grab a byte and stick it in the circular buffer and return from interrupt.
All the packet-parsing and packet-handling stuff executes with interrupts enabled.

The simplest way is for the main loop (AKA the "background task") to periodically
call a function that checks if there is a complete packet in the circular buffer,
and if so parse and handle it. Other more complex approaches involve second-level interrupt handlers, nested interrupts, etc.

However, even when the interrupt handler perfectly receives every byte and correctly puts it into the buffer, sometimes a system can still lose bytes from buffer overflow:

Bytes lost from buffer overflow

Many people write packet handlers that don't do anything until the handler sees a complete packet in the buffer -- then the handler processes the entire packet as a whole. That approach overflows the buffer and data is lost if any incoming packet is larger than you are expecting, too big to fit in the buffer -- single-packet overflow.

Even if your buffer is plenty big enough to hold the largest possible packet, sometimes during the time you're processing that packet, the next packet is so large that it overflows the circular queue before your packet-handler gets around to removing the first packet from the queue to make room for future packets -- two-packet overflow.

Is there some way your status debug system could detect and signal if a byte comes in and it has to be thrown away because there's no more room in the queue?
The simple solution to both these problems is to increase the size of the buffer to hold at least two maximum-size packets, or somehow change the thing that's sending the packets to send smaller packets -- so two packets will fit in the space you have now.

Sometimes incoming data fills the buffers faster than the packet handler can pull data out of the buffer. Increasing the size of the buffer only briefly delays the problem, and sending smaller packets (but more of them) will probably only make things worse. A real-time system must process incoming data at least as fast as that data can come in; otherwise the processor overload will only make the processor get further and further behind. Is there some way your status debug system could detect and signal this sort of overflow?

If this overflow only happens rarely, perhaps the simplest "solution" (arguably merely a hack) is to handle it in more-or-less the same way you would handle a (hopefully rare) power glitch or loss-of-signal on a radio connection: when an overflow is detected, have the AVR erase the entire buffer and pretend it never received those bytes. Most modern protocols are carefully designed such that, if any packet is lost, the system will eventually re-sync and correctly handle future packets.

To really fix this problem requires somehow making the "time to process a packet" less than "time from the end of one packet to the end of the next packet".
so you must either

Reduce the bit rate.

Modify the sender to give the AVR more time to process a packet -- perhaps unconditionally send 50 additional "dummy bytes" in the packet preamble -- or however many is needed to give the AVR more than enough time to completely process the last packet and get ready for the next packet.

Decrease the time to process a packet

Or some combination.

The wall-clock time to process a packet involves both the time the AVR spends in actually processing the packet, and also the time the AVR spends doing "other stuff" such as dealing with all the other I/O ports and interrupt handlers.

Some methods of decreasing the time to actually process a packet are:

Sometimes it's faster to copy the packet out of the queue into some other buffer for further processing, removing it from the circular queue. It makes the packet-handler simpler if the packet starts at the beginning of that other buffer, so key parts of the packet are a fixed constant offset from the beginning of that buffer. (This has the advantage of making it impossible for the serial interrupt handler, which only writes into the circular queue, to accidentally corrupt that packet after it's been copied to that other buffer.) (This approach lets you use tested and "optimized" and known-good functions that handle numbers represented as ASCII strings of hex digits or decimal digits in consecutive order, which may run faster operating on that linear buffer than "equivalent" functions that also have to deal with the wrap-around split of a circular buffer). This requires both the queue and the other buffer to each be at least the size of the maximum possible packet.

Sometimes it's faster to leave the packet in the queue while parsing it and remove it from the queue only after the packet handler is completely done with it.

Sometimes a pair of "ping-pong" buffers is faster than a circular queue.

Many systems use only a single buffer large enough for the largest possible valid packet, and completely disable interrupts from that port until the interrupt handler has finished with the last packet and is ready for the next packet.

Somehow actually do less work per packet.

More general approaches to dealing with situations where "other stuff" is eating so much time that there's not enough time to deal with the packet in the buffer (and may also help reduce the time to actually process the packet):

If you're lucky, you can find some algorithmic tweaks to effectively do the same work in fewer cycles.

Load-shedding: do less important stuff less often; or perhaps don't do them at all in times of heavy load. (As implemented in the Apollo 11 AGC).

yield() more often: if your main loop does fair round-robin cycling between "if we have a complete packet from port 1, handle it" and "if we have a complete packet from port 2, handle it", and the packet parser for either one takes so long that the buffer for the other port overflows, it may help to break the packet parser up into shorter pieces and do only a little processing each time through the main loop, giving the other packet parser a chance to deal with packets before its buffer overflows. Perhaps even consider switching to a pre-emptive task scheduler or a full-up RTOS.

yield() less often: sometimes a processor spends more time in "task switching" or "multitasking overhead" than actually doing anything productive.

Reduce the time spent processing interrupt handlers. (Preventing Interrupt Overload ). High-frequency pulses on one interrupt line can pause main loop tasks indefinitely. It may be necessary to program each low-priority interrupt handler to recognize high-load situations and completely disable its own particular interrupt before re-enabling global interrupts at its return-from-interrupt instruction, and have the main loop recognize low-load situations and re-enable those interrupts.

Increase the clock rate of the processor.

Switch to a more powerful processor. A "more powerful" processor is not the same as "a processor with a faster clock rate". You might be able to find a processor that does the same work in fewer cycles than your particular 8-bit AVR -- perhaps some other AVR with specialized peripherals that do work in hardware that you're currently doing in software, freeing up software cycles for other things; or perhaps a 32-bit processor that can do certain tasks in software in fewer cycles than any 8-bit processor.

Occasionally in robotics "one big fast processor" is better than lots of little processors: the amount of code and the communication latency to copy a message from one task to another task on the same processor is always much less than to copy that same message from one task to another task on some other processor.

Often in robotics it makes things simpler and more "provably correct" to add more processors, perhaps one processor per leg or even one processor per servo. If you have one task per processor, then many of the above potential problems can't ever happen.

Title: How to manage interrupts on an AVR?


问:
ComputerCraft (Minecraft mod) navigation: Collision avoidance and path planning/finding in 2D/3D space
I'm programming Lua for controlling computers and robots in-game in the Minecraft mod ComputerCraft.

ComputerCraft has these robots called Turtles, that are able to move around in the grid based(?) world of Minecraft. They are also equipped with sensors making them able to detect blocks (obstacles) adjacent to them. Turtles execute Lua programs written by a player.

As a hobby project I would like to program a goto(x, y, z) function for my Turtles. Some Turtles actually have equipment to remove obstacles, but I would like to make them avoid obstacles and thus prevent the destruction of the in-game environment.

I have no prior experience in robotics, but I have a B.Sc. in Computer Science and am now a lead web developer.

I did some research and found some basic strategies, namely grid based and quadtree based. As I have no experience in this area, these strategies might be old school.

Note that Turtles are able to move in three dimensions (even hover in any height). I could share the obstacles as well as obstacle free coordinates in a common database as they are discovered if that would help me out, as most obstacles are stationary once they are placed.

What are my best options in this matter? Are there any easy fixes? Where do I look for additional resources?

Thank you very much in advance! :-)

EDIT: Thank you for your feedback!

I started reading the book Artificial Intelligence: A Modern Approach, 3rd Edition to get up to speed on basic theory as suggested by Ian. Pointers to other educational resources are appreciated.

Also, I started developing a basic navigation algorithm for moving in unexplored areas, similar to what Cube suggested.

The priority for me is as few moves as possible, as it costs time and fuel cells for each additional move (approx. 0.8 seconds and 1 fuel cell per move in either direction). I plan on using the Euclidean heuristics function in a Greedy Best-First Search for computing a path that is expected to be quite optimal in reducing the number of moves to reach the goal, if enough data is available from the shared database from previous exploration.

Each time an obstacle is reached, I plan to use the following very basic algorithm, exploiting the fact that Turtles are able to move vertically:

```<code>1. Calculate direct horizontal path to the goal.
2. Turn to the direction of the next step of the path.
3. If an obstacle is detected in front of the Turtle go to 5. If this is the 4th time that an obstacle is detected in front of the Turtle after moving up, go to 6.
4. Move forward, go to 2.
5. If no obstacle is detected above the Turtle, move up and go to 3, else go to 7.
6. Backtrack to the coordinates the Turtle was in before moving upwards.
7. Turn left, go to 3.
</code>```

When using this algorithm, records are kept of the explored coordinates and uploaded to a shared database. However, there are some cases, that I did not consider:

```<code>- When should it move down?
- What if the goal is not reachable from a coordinate directly above it?
- If no horizontal move in any direction is possible, how long should it backtrack?
- How to detect unreachable goals (obstacles can then be removed if requested)
</code>```

Maybe if enough exploration data of the area is available, a Jump Point Search is performed to calculate an optimal path. However this assumes a 2D map. How can I take the 3rd dimension into account?

Also, what would be a good data structure to store the exploration data?

答:
What comes to my mind first is some sort of bug algorithm. That is a path finding algorithm that has only small constant amount of memory and only sees (small) local parts of the world.

You can imagine this as

Go directly to the goal

If there is an obstacle in a way, pick a direction and start going around it

Once there is a free path again, goto 1

Of cause there are some problems with this, I'm not entirely sure that this will work in 3D. Selecting a way around an obstacle will be a little trickier than just saying "always go right".
Other than that, this algorithm can select a wrong direction and spend a long time going around the obstacle which it could avoid easily by going other way around it.

These slides might help you with some of the details.


问:
How to program a continuous servo motor? (Arduino)
I need to use continuously rotating servo for a camera stabilization system. My professor bought servos that have already been modified for continuous motion--there's no stop in the gears, and the potentiometer allows it to spin 360+ degrees.

I am currently using PWM with an Arduino Uno. The servo does spin continuously, but not in a stable way. I've also taken out the potentiometer in another one of the servo, and on a third servo I used a voltage divider in place of the potentiometer.

I've tried static values and a "sweep" from 0% duty cycle to 100% to get a feeling for how they work, but I just cannot figure it out. I greatly would appreciate any tips on this.

Here is my code:

```<code> //PWM test for continious motion Servo

 int servoPin = 9; // connect servo to pin 10
 int pwmVal = 0; // declare pulse width modulation value

void setup(void) {
  pinMode(servoPin, OUTPUT); //set up the servoPin as an output pin
  Serial.begin(9600); // begin serial monitor
}

void loop(void) {

  //for loop that sweeps values from 0 to 255
  for (pwmVal = 0; pwmVal <= 253; pwmVal += 1) {
    analogWrite(servoPin, pwmVal);
    Serial.println(pwmVal);
    delay(100);
  }
  for (pwmVal = 253; pwmVal >= 0; pwmVal -= 1) {
    analogWrite(servoPin, pwmVal);
    Serial.println(pwmVal);
    delay(100);
  }

  //assign a static pwm value
  pwmVal = 0;
  analogWrite(servoPin, pwmVal);
}
</code>```

答:
I can control a normal servo by the esp8266 module. Where I can rotate servo continuously and stop any time by Blynk application. As you mentioned Arduino board to control the servo you may modify my code to run by Arduino. Here I am giving my code below.</p>
```<code>#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Servo.h>
int pwmVal;

Servo servo;

char auth[] = "UjMplBC1-vDSgd79iL53O_p5f-3YngaA";
char ssid[] = "...";
char pass[] = ".......";

void setup()
{
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  servo.attach(15); // NodeMCU D8 pin
 }

void loop()
{
  Blynk.run();
}

 void cradle() {

  //for loop that sweeps values from 0 to 255
    pwmVal=8;
    analogWrite(15, pwmVal);
    Serial.println(pwmVal);
    delay(100);

  pwmVal = 0;
  analogWrite(15, pwmVal);
 }

BLYNK_WRITE(V1)
{
  int Value = param.asInt();
  if (Value == 1) {    // if Button sends 1
    cradle();             // start the function cradle
    int Value = 0;  // Set V1 status to 0 to quit, unless button is still pushed (as per below)

    Blynk.syncVirtual(V1); // ...Then force BLYNK_WRITE(V1) function check of button status to determine if repeating or done.
  }
</code>```

Body:
I can control a normal servo by the esp8266 module. Where I can rotate servo continuously and stop any time by Blynk application. As you mentioned Arduino board to control the servo you may modify my code to run by Arduino. Here I am giving my code below.

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Servo.h>
int pwmVal;

Servo servo;

char auth[] = "UjMplBC1-vDSgd79iL53O_p5f-3YngaA";
char ssid[] = "...";
char pass[] = ".......";

void setup()
{
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  servo.attach(15); // NodeMCU D8 pin
 }

void loop()
{
  Blynk.run();
}

 void cradle() {

  //for loop that sweeps values from 0 to 255
    pwmVal=8;
    analogWrite(15, pwmVal);
    Serial.println(pwmVal);
    delay(100);

  pwmVal = 0;
  analogWrite(15, pwmVal);
 }

BLYNK_WRITE(V1)
{
  int Value = param.asInt();
  if (Value == 1) {    // if Button sends 1
    cradle();             // start the function cradle
    int Value = 0;  // Set V1 status to 0 to quit, unless button is still pushed (as per below)

    Blynk.syncVirtual(V1); // ...Then force BLYNK_WRITE(V1) function check of button status to determine if repeating or done.
  }


问:
Which part handles the acceleration of stepper motors?
I am learning about stepper motors. I am especially interested in them in CNC machines and 3D printers but also in general.

I learned already that stepper motors need signals to accelerate and decelerate them correctly.
What I like to find out is which "part" handles the smooth acceleration and deceleration.

I think at least the following parts are involved when stepper motors are used in CNC machines: CAM software, postprocessor, controller, stepper motor driver (sometimes they are part of the controller board, sometimes separate), stepper motor.

When the CNC machine positions the spindle to machine something, which software or hardware manages the acceleration and deceleration?

答:
On my experience working with stepper motor and CNC shield V3 with DRV8255 motor driver, acceleration and decelaration happen on software side.

So I have simple trajectory planner and PD controller to handle the error which produce control signal in form of acceleration, then I simply integral and get the velocity at that time. The acquired velocity then send to microcontroller.

On microcontroller side, I use motor stepper controller library in here. The code on microcontroller would be something like this

```<code>#include <AccelStepper.h>
AccelStepper mtr(AccelStepper::DRIVER, stepPin[0], dirPin[0]); //Class creation
// After receiving data from computer
mtr.setSpeed(data)
mtr.runSpeed()
</code>```

Body:
On my experience working with stepper motor and CNC shield V3 with DRV8255 motor driver, acceleration and decelaration happen on software side.

So I have simple trajectory planner and PD controller to handle the error which produce control signal in form of acceleration, then I simply integral and get the velocity at that time. The acquired velocity then send to microcontroller.

On microcontroller side, I use motor stepper controller library in here. The code on microcontroller would be something like this

#include <AccelStepper.h>
AccelStepper mtr(AccelStepper::DRIVER, stepPin[0], dirPin[0]); //Class creation
// After receiving data from computer
mtr.setSpeed(data)
mtr.runSpeed()


答:
The short answer is all components in the chain you described have some effect on the acceleration.

The CAM software defines the waypoint through which the tool center point passes. (Let us ignore the setting when it outputs the contact trajectory). When the waypoints are defined and the feeds and speed for the segments are set this already imposes some limits on the accelerations. One such limitation comes from segments with different speeds, obviously there is an acceleration needed between these. A second limitation comes from the curvature on which the waypoints are situated. Even if the feedrate is constant, the curve will determine the acceleration of the different axes.

The CNC gets the waypoints and feed from the GCode. The CNC rounds sharp corners, adds in between waypoints based on a linear/circular/spline interpolation. Furthermore, and most importantly, the CNC adds the „time component“, it plans the velocity and acceleration profiles. The waypoints together with the velocity and acceleration profiles form the trajectory.

The trajectory is then sent each cycle (interpolation cycles can be as low as 2 ms)  to the axis controllers. Each controller is responsible for executing the trajectory as precisely as they can. Usually the trajectory planner in the CNC is aware of the dynamical limits of the system and plans only executable trajectories. A stepper motor driver is  a simplistic case, which has its inherent limitations in terms of smoothness (the first/second/third order continuity of the trajectory). High end CNC machines use PMSM motors.

In modern (probably since the `90s) CNC machine there are no HW components actively participating in the acceleration profile planning or execution (if we disregard the inherent limitations of stepper motors).

The main element responsible for the planning of the acceleration profile is the trajectory planner in the CNC. However this planner is limited by the waypoints it gets from the CAM tool and by the dynamical limits of the machine.

Title: Which part handles the acceleration of stepper motors?

Body:
I am learning about stepper motors. I am especially interested in them in CNC machines and 3D printers but also in general.

I learned already that stepper motors need signals to accelerate and decelerate them correctly.
What I like to find out is which "part" handles the smooth acceleration and deceleration.

I think at least the following parts are involved when stepper motors are used in CNC machines: CAM software, postprocessor, controller, stepper motor driver (sometimes they are part of the controller board, sometimes separate), stepper motor.

When the CNC machine positions the spindle to machine something, which software or hardware manages the acceleration and deceleration?


问:
Omron Viper 850 Orientation out of range error
Good morning folks

We have a Omron Viper 850 robot

It is in inverted mount, i.e mounted upside down as you can see in the photo.

We are using the ACE 4.3 Software to program the robot.
I don't have the code to paste here, but is something like:

```<code>SPEED 20 ALWAYS
DURATION 0.5 ALWAYS
MOVE safe.pos
MOVES pos2
MOVEC pos3,pos4
</code>```

The properly code are much bigger than it. But this fit as an example, because we are using basically these five instructions.

When we ran the code, the robot sometimes make the course, sometimes not. When not, we receive the error message "Orientation Out of Range".

We suspect that we have to include some instruction to says to the robot that it are working in upside down orientation.

The manual said something about this error, but we not realize how it works

The manual ev+ programming pdf is here.

I appreciate any idea to workaround this error.

答:
It has been a while since I worked in V+, the predecessor to EV+, but I think I can answer some questions.

The base instruction allows you shift the robot world frame in X, Y, Z, and rotate about Z, but it does not allow you to rotate about X or Y so it cannot invert the arm.

The Frame instruction allows you to very accurately define the orientation of a transformation. You could use this create an inverted transformation and set your locations relative to it, but I don't think that is the issue you are seeing.

If you are only getting errors during MOVES instructions, you are almost certainly running into a singularity. The most common singularity is when joint 5 passes through 0 degrees. This changes the configuration of wrist between flip and noflip. You can also get a singularity when joint 3 passes through 0 and when the arms wrist passes directly over top of the base. The latter is very common when working below an inverted arm.

If possibly do a MOVE instead of MOVES, possibly breaking the trajectory up into a MOVES, a MOVE through the singularity, then a MOVES. You might also want to specify a precision point for the MOVE to force the arm into the correct joint positions.

Sometimes changing your end of arm tooling design, putting ii at an angle to mount flange can help. This moves the singularity somewhere else.


问:
Quadcopter configuration
I'm building a quadcopter. It will be controlled by a Beaglebone black with several Sensors and a cam.

I new to the quadcopter stuff, therefore it would be nice if someone could have a look at my setup before I buy the parts.

Frame: X650F - 550mm

Battery: Turnigy nano-tech 5000mah 4S 25~50C Lipo Pack

Motor: NTM Prop Drive 28-30S 800KV / 300W Brushless Motor

ESC: Skywalker 4x 25A Brushless

This sums up to ~ 2kg. Giving me still some room for about 700g payload.

What do you think? Did I miss something important? Better ideas for some parts?

答: You should have a prop balancer like this which will ensure that propellers are well balanced. Also you should have a Lipo alarm like this which can warn you when you are low on battery during fight.</p>

Title: Quadcopter configuration


问:
how to calculate the accuracy of data received from RTK-GPS?
I have received data from an RTK-GPS, in an environment free from buildings and other GPS obstructions. the covariance of these data is 0.01. now I do not know this is good or not? How can I find out what is the accuracy of my GPS data? is there any solution?

latitude  longitude altitude position_covariance0 ... position_covariance4 ... position_covariance8 52.06669  -0.626525   156.98        0.0121                    0.0121                  0.1936

Thanks a lot

答:
How "good" the data is depends on how useful the results are for you.

The only way that you can check accuracy is to compare your measured results to a true result - this would require you to measure from a known location.


问:
Significance of fixed_frame parameter in lookupTransform function
I was going through the implementation of the lookupTransform function defined inside the base_local_planner::getGoalPose() function.

What is the significance of the fixed_frame parameter in tf2_ros::Buffer::lookupTransform (target_frame, target_time, source_frame, source_time, fixed_frame, timeout)  function ?

The documentation mentions the following - Get the transform between two frames by frame ID assuming fixed frame.

What's preventing us to always go for the other implementation of the lookupTransform function -   tf2_ros::Buffer::lookupTransform (target_frame, source_frame, time, timeout) ?

答:
From what I understand, the fixed frame is one where objects are assumed to be stationary with time. Maybe an example will make this clear:

Assume a robot with a lidar sensor moving in your world. It spits out a laserscan in the /lidar frame. The goal pose might be in an /odom frame. Now, if you encounter objects in the /lidar frame, your navigation stack has to transform them into the /odom frame (using lookuptransform). Maybe you are also mapping the environment in a /map frame (which could be your fixed frame in this case). If an object is staitonary (like a rock), you could transform it using the fixed frame (/map) since it is not going to change its position in the world.

Such transforms can help estimate the location of objects around the robot into the future.


问:
Where do I start learning from for motion planning underactuated robotics?
I am an undergraduate student approaching my final year. I have a final year project which involves planning a trajectory for an underactuated robot that also avoids obstacles.

So far I have come up with the differential equations that govern the robot as well learned about the iLQR which is an unconstrained optimisation technique. Is there a way to add constraints to the control inputs as well as add bounds to the different states?

答:
This website was really helpful for me when learning all about robotics: https://robotacademy.net.au

It has lots of info on motion planning / path planning too.

I guess this isn't a direct answer to your question but for anyone coming here looking for educational resources, this is a good one.


答:
It looks like your research here is a little too specific -- you're working on the practical level before being up to speed on the theory.  Take a look at more of the higher-level concepts of motion planning and obstacle avoidance.

The extremely simplified process is:

Expressing a high-level objective for the robot

Based on data describing the current environment, creating a set of planned movements that meet the objective (using path planning algorithms like A* search)

As time passes, collecting new data about the environment (e.g. current position, new obstacles) and re-planning the path

Quadtrees and grids are just 2 ways of representing the environment itself; one of the practical problems involved in robotics is the sheer volume of data that can come in, and quadtrees offer a more memory-space-efficient representation of that data (see also, octrees for 3D spaces) in return for some extra CPU time and complexity.  There are many such optimizations that you could make, but it sounds like you're considering them a little too early in the design process.

Title: ComputerCraft (Minecraft mod) navigation: Collision avoidance and path planning/finding in 2D/3D space

Body:
I'm programming Lua for controlling computers and robots in-game in the Minecraft mod ComputerCraft.

ComputerCraft has these robots called Turtles, that are able to move around in the grid based(?) world of Minecraft. They are also equipped with sensors making them able to detect blocks (obstacles) adjacent to them. Turtles execute Lua programs written by a player.

As a hobby project I would like to program a goto(x, y, z) function for my Turtles. Some Turtles actually have equipment to remove obstacles, but I would like to make them avoid obstacles and thus prevent the destruction of the in-game environment.

I have no prior experience in robotics, but I have a B.Sc. in Computer Science and am now a lead web developer.

I did some research and found some basic strategies, namely grid based and quadtree based. As I have no experience in this area, these strategies might be old school.

Note that Turtles are able to move in three dimensions (even hover in any height). I could share the obstacles as well as obstacle free coordinates in a common database as they are discovered if that would help me out, as most obstacles are stationary once they are placed.

What are my best options in this matter? Are there any easy fixes? Where do I look for additional resources?

Thank you very much in advance! :-)

EDIT: Thank you for your feedback!

I started reading the book Artificial Intelligence: A Modern Approach, 3rd Edition to get up to speed on basic theory as suggested by Ian. Pointers to other educational resources are appreciated.

Also, I started developing a basic navigation algorithm for moving in unexplored areas, similar to what Cube suggested.

The priority for me is as few moves as possible, as it costs time and fuel cells for each additional move (approx. 0.8 seconds and 1 fuel cell per move in either direction). I plan on using the Euclidean heuristics function in a Greedy Best-First Search for computing a path that is expected to be quite optimal in reducing the number of moves to reach the goal, if enough data is available from the shared database from previous exploration.

Each time an obstacle is reached, I plan to use the following very basic algorithm, exploiting the fact that Turtles are able to move vertically:

```<code>1. Calculate direct horizontal path to the goal.
2. Turn to the direction of the next step of the path.
3. If an obstacle is detected in front of the Turtle go to 5. If this is the 4th time that an obstacle is detected in front of the Turtle after moving up, go to 6.
4. Move forward, go to 2.
5. If no obstacle is detected above the Turtle, move up and go to 3, else go to 7.
6. Backtrack to the coordinates the Turtle was in before moving upwards.
7. Turn left, go to 3.
</code>```

When using this algorithm, records are kept of the explored coordinates and uploaded to a shared database. However, there are some cases, that I did not consider:

```<code>- When should it move down?
- What if the goal is not reachable from a coordinate directly above it?
- If no horizontal move in any direction is possible, how long should it backtrack?
- How to detect unreachable goals (obstacles can then be removed if requested)
</code>```

Maybe if enough exploration data of the area is available, a Jump Point Search is performed to calculate an optimal path. However this assumes a 2D map. How can I take the 3rd dimension into account?

Also, what would be a good data structure to store the exploration data?


问:
Does anyone believe a high voltage battery say 100kV is possible? If so do you have a schematic or know a seller?
In the interest of soft robotics I need a high power programmable battery power supply. I also found this.

https://aip.scitation.org/doi/pdf/10.1063/1.2362721

答:
They do not have 100kV batteries. They use 12-volt batteries to power a fancy dc-dc converter, which steps up the voltage to 100kV with a Cockroft-Walton voltage multiplier. Ref: the abstract of the article you cite.

EDIT (response to comment): I read the material at artimusrobotics.com and read two of their papers in Science. Those Colorado guys are clever, but they're fighting the classic battle of high-voltage electrostatics vs high-current electromagnetics. From this I conclude that HASEL is not practical for operating a human-size bipedal robot, at least not this decade.

Use ordinary electric motors instead. Read about the actuators developed for the MIT Mini Cheetah.


问:
doubt regarding the base_local_planner::transformGlobalPlan() function
I am trying to understand the base_local_planner::transformGlobalPlan() function.

As per my understanding, the function takes in the global_plan (generated by the global planner) as an input and updates the transformedPlan variable. It does so by transforming the points in the global_plan to the global_frame (of the local costmap) and then removing the points that lie outside the bounds of the local costmap.

In particular, I am trying to understand the section inside the first while loop - marked by the comments - 'we need to loop to a point on the plan that is within a certain distance of the robot'.

In this section, we are looping over the points in the global_plan until sq_dist <= sq_dist_threshold. Shouldn't this cause the first while loop to break immediately because the first point in the global_plan would be the one that is closest to the bot?

```<code>bool transformGlobalPlan(
      const tf2_ros::Buffer& tf,
      const std::vector<geometry_msgs::PoseStamped>& global_plan,
      const geometry_msgs::PoseStamped& global_pose,
      const costmap_2d::Costmap2D& costmap,
      const std::string& global_frame,
      std::vector<geometry_msgs::PoseStamped>& transformed_plan){
    transformed_plan.clear();

    if (global_plan.empty()) {
      ROS_ERROR("Received plan with zero length");
      return false;
    }

    const geometry_msgs::PoseStamped& plan_pose = global_plan[0];
    try {
      // get plan_to_global_transform from plan frame to global_frame
      geometry_msgs::TransformStamped plan_to_global_transform = tf.lookupTransform(global_frame, ros::Time(),
          plan_pose.header.frame_id, plan_pose.header.stamp, plan_pose.header.frame_id, ros::Duration(0.5));

      //let's get the pose of the robot in the frame of the plan
      geometry_msgs::PoseStamped robot_pose;
      tf.transform(global_pose, robot_pose, plan_pose.header.frame_id);

      //we'll discard points on the plan that are outside the local costmap
      double dist_threshold = std::max(costmap.getSizeInCellsX() * costmap.getResolution() / 2.0,
                                       costmap.getSizeInCellsY() * costmap.getResolution() / 2.0);

      unsigned int i = 0;
      double sq_dist_threshold = dist_threshold * dist_threshold;
      double sq_dist = 0;

      //we need to loop to a point on the plan that is within a certain distance of the robot
      while(i < (unsigned int)global_plan.size()) {
        double x_diff = robot_pose.pose.position.x - global_plan[i].pose.position.x;
        double y_diff = robot_pose.pose.position.y - global_plan[i].pose.position.y;
        sq_dist = x_diff * x_diff + y_diff * y_diff;
        if (sq_dist <= sq_dist_threshold) {
          break;
        }
        ++i;
      }

      geometry_msgs::PoseStamped newer_pose;

      //now we'll transform until points are outside of our distance threshold
      while(i < (unsigned int)global_plan.size() && sq_dist <= sq_dist_threshold) {
        const geometry_msgs::PoseStamped& pose = global_plan[i];
        tf2::doTransform(pose, newer_pose, plan_to_global_transform);

        transformed_plan.push_back(newer_pose);

        double x_diff = robot_pose.pose.position.x - global_plan[i].pose.position.x;
        double y_diff = robot_pose.pose.position.y - global_plan[i].pose.position.y;
        sq_dist = x_diff * x_diff + y_diff * y_diff;

        ++i;
      }
    }
    catch(tf2::LookupException& ex) {
      ROS_ERROR("No Transform available Error: %s\n", ex.what());
      return false;
    }
    catch(tf2::ConnectivityException& ex) {
      ROS_ERROR("Connectivity Error: %s\n", ex.what());
      return false;
    }
    catch(tf2::ExtrapolationException& ex) {
      ROS_ERROR("Extrapolation Error: %s\n", ex.what());
      if (!global_plan.empty())
        ROS_ERROR("Global Frame: %s Plan Frame size %d: %s\n", global_frame.c_str(), (unsigned int)global_plan.size(), global_plan[0].header.frame_id.c_str());

      return false;
    }

    return true;
  }
</code>```

答:
Shouldn't this cause the first while loop to break immediately because the first point in the global_plan would be the one that is closest to the bot?

That looks like the intent to me, but I can't tell where global_plan is coming from or if it's guaranteed to be sorted by distance. Not quite sure what the point is here, but if you had something like a figure 8 track the position that's closest to you may not necessarily be the one that's next in order if the points are populated along a path.

If that's the case then you could wind up at the crossroads and find yourself basically looping one end or the other of the figure 8 and never actually completing the entire 8.

So, assuming a kind of use case like that, you may expect the next point to be suitable, but if it's not then you'll check all the other points too, just to be sure, and that's what the while loop is doing for you - it's trying the first point, but then continuing to iterate through all of them "just to be sure" none of the other points meet your criteria.


问:
How to program to generate robot URDF(Serial manipulator) when having stl file of each link with Python
I've tried :

to use obj2udf library(PyPI)  then It can generate 1 URDF per 1 STL(it doesn't work because I can't find how to program to change link name or add link and can't combine STL)
so now I have URDF of each link instead of a robot URDF.

to combine each urdf in pybullet and think it won't work when use as simulation.
additional :

after I have URDF I will try to work with pybullet.

I am working on window 10 with Visual studio code.

use miniconda.

so is there a way or some function of python that can generate robot URDF

reference code:

```<code>import os
import sys
from object2urdf import ObjectUrdfBuilder

# Build single URDFs
object_folder = "Base"

builder = ObjectUrdfBuilder(object_folder, urdf_prototype='_prototype_Base.urdf')
builder.build_urdf(filename="Base\Base.stl", force_overwrite=True, decompose_concave=True, force_decompose=False, center = 'mass')
</code>```

答: Thank you,Now I have found odio_urdf library that can generate urdf by programming in python like you code in  urdf file.</p>


问:
Multivariable PID controller
I'm making a robot that uses two DC motors to move, and has two distance sensors on its right side. I want to make a PID controller to control the angle of the robot (using a wall as reference) and also its distance to the wall.

I made a PID controller that can minimize the difference between both sensors' measurements, making the robot go always parallel to the wall. I also made a controller for controlling the distance one sensor measures, for the robot to go always at the same distance to the wall.

What I want to do is combine those two controllers into one. I know there's something called MISO PID controller (multiple inputs single output) but I don't know how to use it or even design it. I thought of adding those two variables (the difference and one sensor's measurement) and using that as the controller's input. Is that right? How can I achieve this?

PS: I also thought of adding the difference between each sensor's measurement and the distance I want, or using those two differences as the variables of my MISO controller.

答: The angle of the wall can be measured using only one sensor but with two readings over a short time period. One PID could then be used to keep the distance to the wall the same over time.</p>

Title: Multivariable PID controller


问:
Orientation Problem of a 4-DOF manipulator
As shown in figure, I have a 4-DOF manipulator.

I want to control the robot such that the end-effector should always be pointing down no matter where the robot is in the end space. For the orientation problem, I derived the Jacobian matrix, then derived the path equations parameterized with time t, but I am still not sure on how to keep the end-effector pointing downwards all the time. $w_{x}$ and $w_{y}$ control the end-effector orientation but how can this be implemented? Any help will be greatly appreciated.

答:
If you have derived the 6x4 Jacobian, then using the same approach you should derive the 4x4 Jacobian. In the 4x4 Jacobian you will have the X Y and Z positions, and the only orientation you care about.

The only change you need to do in the kinematic equations, based on which you derive the Jacobian, is to make sure the express the orientation of the end-effector relative to a local Z axis, which rotates with the first motor, and not a fixed global axis. This way you will not have to deal with angle projections and the 4x4 Jacobian will suffice.


问:
Did I buy the wrong SBR rails?
I have bought some SBR12 rails and bearing blocks in an attempt to make a fancy flattening jig for my router.

I haven't been able to see 100 % everything that other people have done on the YouTubes due to camera angles etc., but I went ahead and bought some to fit the table I currently have.

The idea is to have two rails attached atop another two rails perpendicularly as to act as an X and a Y axis to move the router across the workpiece easily.

The issue I have found now the rails have arrived is that the holes in the rails, designed for fixing them to a tabletop, etc., don't align fully with the threaded holes in the tops of the bearing blocks...

Is this something that is normal, or was I just naive to the idea that they would fit perfectly? Also, is there something you can suggest I do to attach these securely?

答: That doesn’t sound very unusual to me unless you purchased materials that specifically purported to be predrilled and compatible. Sounds like you may need to manually mark out, drill and possibly tap or countersink the holes you need.</p>

Title: Did I buy the wrong SBR rails?


问:
How to use knowledge of sensor noise
Reasoning about the meaning of uncertainty of sensor measurement I ran into a doubt:

(1) When we talk about sensor uncertainty, we often model it as a Gaussian distribution $\mathcal{N}(\boldsymbol{z}, \Sigma)$, where $\boldsymbol{z}$ is the value measured by the sensor and the covariance matrix $\Sigma$ gives us information about the uncertainty. In particular, $\Sigma$ represents the uncertainty on "how" far the true value $\boldsymbol{x}$ is from $\boldsymbol{z}$. The distribution is centered on $\boldsymbol{z}$ as we do not have access to the true value $\boldsymbol{x}$.

(2) Now, assume that we have access to the ground truth, and we learn the distribution of the error, such that $\boldsymbol{z} = \boldsymbol{x} + \boldsymbol{\epsilon}$ where $\boldsymbol{\epsilon} \sim \mathcal{N}(0, \hat{\Sigma})$.

The two situations might look the same, but in (1) the distribution $\mathcal{N}(\boldsymbol{z}, \Sigma)$ is centered on the measured value, while in (2) $\hat{\Sigma}$ is the covariance of a Gaussian centered on the true value. Is my interpretation of (1) correct? Can we set $\Sigma = \hat{\Sigma}$, i.e. can we use the covariance learned in (2) in the setting described in (1)?

答:
You are correct. It's just a matter of interpretation.

(1) is the guess on the location of the true value whereas (2) is simulating your sensor behavior.

Your equation in (1) can be converted to N(z,sigma) = z + N(0,sigma) witch is eventually same as your second equation.

Can we set Σ=Σ^, i.e. can we use the covariance learned in (2) in the setting described in (1)?

-> This depends on your system definition. In many cases, Σ^ is not available. So sometimes we just use the manufacture's sensor noise model or we just manually calculate them which might be different from the real true ground truth. But if you are running a simulation they will be identical.

Title: How to use knowledge of sensor noise


问:
Can you plug a CMOS camera (like the iPhone 8 back camera) into an mPCIe in a laptop?
I read that 12 megapixel iPhone cameras don’t record video in 12 megapixels because the processors are not able to keep up. It seems though, that if I could plug the CMOS sensor to the CPU of a laptop, I could process all 12 megapixels at 60 fps.

The only other problem would be that plugging the camera in through USB would be too slow since USB 3.0 is only 600 MBps. Instead, I want to use the mPCIe slot the wireless module goes into.

Is this possible?

答:
Yes, it's possible as long as you are willing to spend a couple of million dollars to develop a MIPI to PCI-E interface board.

If you are just trying to use the camera on your broken iPhone, forget about it.

If you really need high speed 12M pixel camera, use machine vision cameras. Ethernet version is faster than USB.

Anyway, you need an "interface board", to connect a cmos to your computer. Machine vision cameras already have it inside either for pcie or ethernet.


问:
Equations of motion in matrix form and energy consumption
I am working on Lagrangian derived high-dimensional motion equations for a robot in matrix form. The structure of such an equation is known:

$M(q)\ddot{q}+C(q,\dot{q})\dot{q}+G(q)=0$

In here, $M(q)$, $C(q,\dot{q})$ are matrices, and  $G(q)$ are vector.

Are there any properties of $M(q)$, $C(q,\dot{q})$, $G(q)$ related to the power consumption of the robot and is it possible to optimize power consumption by operating with these very properties?

Remark: I mean they are matrices, vectors, etc., i.e. is it possible to somehow use their traces, determinant, norm and other to use for the study of energy consumption?

答:
Can you set up the problem so that the quantities you care about (e.g. power) are more explicitly represented? Reasoning physically, where could the power go?

Accelerating masses, including rotation

Pushing against gravity, electromagnetics, other potentials

Stretching springs and whatever

Dissipation through friction

You say "optimize power consumption". One could minimize

peak instantaneous power over some cycle of operation

total energy (average power) over cycle

RMS power over cycle

heat dissipation (tight thermal constraints?)

I would choose one of those to optimize, and express it in terms of your system's M, C and G. I would expect properties of the resulting matrix equation(s) to be easier to reason about than the original M, C and G. I know just enough about multidimensional functional minimization of (potentially) nonlinear matrix equations to know I don't want to go there right now (if ever!)

Good luck!


问:
Why is a joint space trajectory unable to deal with operational space obstacles?
I have found several sources that state that a Joint space trajectory model is not capable of dealing with obstacles in the manipulator workspace. These sources include:

slide 10 of "Manipulator Trajectory Planning":

URL: https://cw.fel.cvut.cz/old/_media/courses/a3m33iro/080manipulatortrajectoryplanning.pdf

and also Mathworks in their presentation on Trajectory Planning for Robot Manipulators on Youtube at timestamp 3:16.

URL: https://www.youtube.com/watch?v=Fd7wjZDoh7g&ab_channel=MATLAB.

The problem I am facing is that these sources do not explain why joint space models can not deal with obstacles.

Is there somebody here that can shed some light on this?

答:
The main difference between task space control and joint space control are :

Joint space : You know start and last position of joint configuration from IK(Inverse kinematic), and interpolate it

Task space : You know start and last position of end-effector, then interpolate it and IK every point in path to get joint configuration for every point in path.

Obstacle are known in cartesian space (x,y,z, and orientation). The other component we know in cartesian space is end-effector. Obstacle avoidance only able to be performed on task space control because on task space control we have information position and orientation of end-effector which may collide with obstacle, thus we can plan the path of end-effector. While in joint space we didnt have that information because we didnt plan the path of end-effector(only take the first and last position and orientation of end-effector).


问:
When reading serial data between Arduino and a node, it hangs. How can I properly send and read data?
I'm using ROS2 foxy with no libraries installed. It runs on an Ubuntu 21.04 x64 machine with kernel 5.8.0-59-generic.

I created a project with the goal of controlling an Arduino using python serial in a workspace with the following structure:

```<code>- workspace
    - src
        - arduino_comm
             - serial_server.py
             - serial_client.py
        - motor_interface
        - other_interface
</code>```

the motor interface provides the action that is used by the arduino_comm package to send serial data. I have an old Arduino Nano that I've had for like 7 years ago that uses the old legacy bootloader. Still operational but sadly seems incompatible with the rosserial and I've checked the Micro-Ros packages and they also seem incompatible with my old arduino. Also I wanted to understand the code I'm working with at its bare basics before adding more complexity with an external library.

So I created the following code.

Arduino code

```<code>//Variable to store the bot command.
String botCommand;

void setup() {
  //Initialize Serial port.
  Serial.begin(9600);
  //Initialize BUILTIN LED to light up for feedback.
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  if(Serial.available()){
    botCommand = Serial.readString();
    if(botCommand == "forward"){
      //Light up the led.
      digitalWrite(LED_BUILTIN, HIGH);
      delay(10);
    }
    Serial.println(botCommand);
  }
  //Shut down the LED.
  digitalWrite(LED_BUILTIN, LOW);
  delay(10);
}
</code>```

The Server and Client use the following action, which is based on the tutorial

```<code>##################################################
#Action that sends robot towards a specific spatial position.
##################################################
#Goal of achieving a specific position.
int32 botgoalposition
---
#Resulting position that we're aiming to attain.
int32[] botendposition
---
#Feedback message about current position.
int32[] botcurrposition
</code>```

The arduino_comm serial_server.py dedicated to sending commands to the Arduino to follow.

```<code>import time
#Import the Serial library to send commands to Arduino.
import serial

#Elements required to generate an ActionServer.
import rclpy
from rclpy.action import ActionServer

#Library required to generate a ROS2 Node.
from rclpy.node import Node

##################################################
#                   ACTIONS
##################################################
#Action to calculate Fibonacci code. FOR DEBUGGING.
from code_interfaces.action import Fibonacci

#Action to send commands to the Arduino until it reaches the desired coordinates.
from bot_move.action import BotMove

#Class that encapsulates the Action Server.
class SerialCommServer(Node):
    def __init__(self):
        #Declare the Node with the name "serial server".
        super().__init__('serial_server')
        #Declare it'll be an ActionServer that publishes to the topic 'botmove'.
        self._action_server = ActionServer(
                self,
                BotMove,
                #Action name.
                'botmove',
                #Callback for executing accepted goals.
                self.executeCallback
                )

    #When it has been initialized, it'll start executing the following callback.
    def executeCallback(self, goalHandle):
        #Set the logger to indicate we're starting to execute our goal.
        self.get_logger().info('Executing goal...')

        #Get feedback to see if we're close to our goal.
        feedbackMsg = BotMove.Feedback()
        feedbackMsg.botcurrposition = [0,1]

        goalHandle.publish_feedback(feedbackMsg)

        #Send a small Hello to Arduino.
        arduino = serial.Serial(port="/dev/ttyUSB0")
        for i in range(1, 10):
            arduino.write(bytes(str("forward"), 'utf-8'))
            feedbackMsg.botcurrposition.append(i)
            self.get_logger().info('Feedback: {0}'.format(i))

            #Read back response from the Arduino.
            #TODO: THIS SECTION HANGS, NEED TO FIGURE HOW TO FIX IT.
#            response = arduino.readline()
#            print("Response: " + str(response))
            time.sleep(1)

#        for i in range(1, goalHandle.request.botgoalposition):
#            feedbackMsg.botcurrposition.append(
#                    feedbackMsg.botcurrposition[i] + feedbackMsg.botcurrposition[i-1])
#            #Show the position that has been achieved so far.
#            self.get_logger().info('Feedback: {0}'.format(feedbackMsg.botcurrposition))
#            goalHandle.publish_feedback(feedbackMsg)

        goalHandle.succeed()
        result = BotMove.Result()
        result.botendposition = feedbackMsg.botcurrposition

        #Returns result of the run. All Actions MUST return a result.
        return result

def main(args=None):
    rclpy.init(args=args)
    serialCommServer = SerialCommServer()

    try:
        print("Initializing Serial Communication Server.")
        rclpy.spin(serialCommServer)
    except KeyboardInterrupt:
        print("Keyboard interrupt command received")

if __name__ == '__main__':
    main()
</code>```

And finally the client serial_client.py that doesn't do much of interest, later I want to send commands from another node but still need to fix this first.

```<code>import rclpy
from rclpy.action import ActionClient

#Library needed to generate a ROS2 Node.
from rclpy.node import Node

#Imports Action to solve a Fibonacci sequence. FOR DEBUGGING.
from code_interfaces.action import Fibonacci

#Action to manage position of the robot using Serial.
from bot_move.action import BotMove

#This is the Class that makes serial requests to the server.
class SerialCommClient(Node):
    def __init__(self):
        super().__init__('serial_client')

    #Declare a new Action Client.
    self._action_client = ActionClient(self, BotMove, 'botmove')

#This function waits for the action server to be available, then sends the new goal position the robot must occupy.
def sendGoal(self, botgoalposition):
    #Declare the BoMove action so we can start requesting a new robot position.
    goalMsg = BotMove.Goal()

    #Set a new goal for the action.
    goalMsg.botgoalposition = botgoalposition
    #Wait for the server to respond to the request.
    self._action_client.wait_for_server()
    self._send_goal_future = self._action_client.send_goal_async(
            goalMsg,
            feedback_callback=self.feedbackCallback
            )
    #When the goal has been set, execute this callback.
    self._send_goal_future.add_done_callback(self.goalResponseCallback)

#Goal Handle - Does different things depending on whether the server has accepted or rejected the goal.
def goalResponseCallback(self, future):
    goalHandle = future.result()

    if not goalHandle.accepted:
        #Log that the goal has been rejected.
        self.get_logger().info('Goal rejected :/')
        return
    #Otherwise, log that it has been accepted.
    self.get_logger().info('Goal accepted')

    self._get_result_future = goalHandle.get_result_async()
    #Callback to do something with the results we get after the server is done executing code.
    self._get_result_future.add_done_callback(self.getResultCallback)

#This callback function does things with the result.
def getResultCallback(self, future):
    result = future.result().result
    #Print the final position achieved.
    self.get_logger().info('Result: {0}'.format(result.botendposition))
    #Shutdown the Client.
    rclpy.shutdown()

#Gets the partial feedback portion of the message and prints it.
def feedbackCallback(self, feedbackMsg):
    feedback = feedbackMsg.feedback
    self.get_logger().info('Received feedback: {0}'.format(feedback.botcurrposition))

def main(args=None):
    rclpy.init(args=args)
    actionClient = SerialCommClient()
    #Establish the goal that will be reached by the server. In this case to reach some specific coordinates.
    actionClient.sendGoal(50)

    rclpy.spin(actionClient)

if __name__ == '__main__':
    main()
</code>```

So far it works and properly sends the serial data to the Arduino which makes it blink. But when I try to read back the response it hangs. What could be a proper way to modify the code so the server can read serial data back? And is there a more proper way to build this? Thanks a lot for your help!

答:
I found what I believe is a relevant answer here, and I think it's relevant because of the following lines in your serial_server.py file:

```<code>#When it has been initialized, it'll start executing the following callback.
def executeCallback(self, goalHandle):

    # <other code>

    #Send a small Hello to Arduino.
    arduino = serial.Serial(port="/dev/ttyUSB0")
</code>```

The way I read this makes it look like you're starting a serial connection repeatedly. The post I linked states,

Establishing a serial connection to an arduino causes it to reset, so it was never online at the moment the pi was sending data, and so never replied.

There's a longer explanation about the behavior over at Arduino.SE that says, in part,

The Arduino uses the RTS (Request To Send) (and I think DTR (Data Terminal Ready)) signals to auto-reset.

The answer there also links here for instructions on disabling the auto-reset-on-serial-connection feature. Links can rot, so in the interest of future visitors I'll quote a subset of the page here, describing how to use a pull-up resistor on the reset pin to disable the auto-reset:

The simple way that doesn't require any permanent modifying of your hardware or software configuration changes:

Stick a 120 ohm resistor in the headers between 5v and reset (you can find these on the isp connector too). 120 is hard to find so just combine resistors. Don't go below 110 ohms or above 124 ohms, and don't do this with an isp programmer attached. You can just pull out the resistor when you want auto-reset back.

In summary, it looks like you're restarting your serial connection in every execute callback. Establishing the serial connection is resetting your arduino, and then it's resetting while you perform the serial write so it doesn't realize you're expecting a response when you get to the serial read.

You can avoid this by either starting the serial connection and storing the handle to the connection as a member variable or taking it as a callback parameter (preferred) or by disabling the auto-restart function.

Body:
I found what I believe is a relevant answer here, and I think it's relevant because of the following lines in your serial_server.py file:

#When it has been initialized, it'll start executing the following callback.
def executeCallback(self, goalHandle):

    # <other code>

    #Send a small Hello to Arduino.
    arduino = serial.Serial(port="/dev/ttyUSB0")

The way I read this makes it look like you're starting a serial connection repeatedly. The post I linked states,

Establishing a serial connection to an arduino causes it to reset, so it was never online at the moment the pi was sending data, and so never replied.

There's a longer explanation about the behavior over at Arduino.SE that says, in part,

The Arduino uses the RTS (Request To Send) (and I think DTR (Data Terminal Ready)) signals to auto-reset.

The answer there also links here for instructions on disabling the auto-reset-on-serial-connection feature. Links can rot, so in the interest of future visitors I'll quote a subset of the page here, describing how to use a pull-up resistor on the reset pin to disable the auto-reset:

The simple way that doesn't require any permanent modifying of your hardware or software configuration changes:

Stick a 120 ohm resistor in the headers between 5v and reset (you can find these on the isp connector too). 120 is hard to find so just combine resistors. Don't go below 110 ohms or above 124 ohms, and don't do this with an isp programmer attached. You can just pull out the resistor when you want auto-reset back.

In summary, it looks like you're restarting your serial connection in every execute callback. Establishing the serial connection is resetting your arduino, and then it's resetting while you perform the serial write so it doesn't realize you're expecting a response when you get to the serial read.

You can avoid this by either starting the serial connection and storing the handle to the connection as a member variable or taking it as a callback parameter (preferred) or by disabling the auto-restart function.


问:
Making a human set path following robot
I want to make a robot that uses The Arduino IDE controlled by an esp32 that uses a KY-033 tracking module, that a person presses a button on the controller with an esp32 there will be a button that will be a button that tells the controller to start tracking your position to create a virtual path that the robot will follow and once you are done making the path you press the same button to save the path and you have another button to press to start having robot start following the path. How would I do this?</p>

答:
KY-033 it is not somekind of sensor that able to detect human and perceive the depth of enviroment. It just a normal line detecting sensor work based on reflection of infrared. You need to look about it more to understand what it actually does. If you wanna make what you want to create, you need at least a camera preferably stereo camera. If using stereo camera, you can detect human being using some simple machine learning algorithm and compare the position of human on both side of camera to get the position in 3 dimensional space. And then you can start make your robot.

How to implement following path robot :

Recording Stage

So when u press record button, robot would start to detect human on each side of camera and measure the position of it respect to the robot. You can set the time between position record (sampling time) maybe 0.2s-1s. System then would store the position in array. And after the button stop pressed, it stop recording the position.

Following virtual path stage

This stage pretty simple, just set the goal position from array storing position and make robot follow it. If it reach the 1st point then go to next until it finished. And when it reach final position it simply stop

That is the approach you could use.

Additional note :

To detect object using camera, u need to use mini computer such Raspberry Pi. Then you communicate with arduino to control it. Read more about object detection and computer-microcontroler communication.

To make your project easier, instead of human you maybe detect marker. For example AprilTag. Read more : AprilTag

Title: Making a human set path following robot


问:
Pose difference estimation in cartesian impedance control
I am trying to implement a cartesian impedance controller in simulation (gazebo + KDL). The method which I am using is the following:

Compute the EE pose from KDL's forward kinematics for the position

Compute the EE twist from KDL's forward kinematics for the velocity

Compute the Jacobian (which I am not sure how to figure out if it's the correct one - see later the comment about the rotation error) from the base frame to the EE frame

Compute the difference betweent the EE's pose and the desired pose

Multiply the difference with the Cartesian stiffness matrix

Muttiply the velocity of the EE with the Cartesian damping matrix

Sum the stiffness, damping

Multiply the sum with the transpose of the Jacobian to go from Cartesian to joint space

Add gravity compensation terms (computed by KDL)

Apply the computed torque on the joints

This whole method is summarized here:

Note, for my use case (contactless, stable target position) the impedance controller reduces to PD + gravity compensation control.

The whole method seems to work, but I am running into the following issues:

The target position takes a lot of time to reach and in the meantime there are some weird oscillations (see video here https://drive.google.com/file/d/1tC20Jf24BbdLCqRbOItIvdZIkqAq1Gfn/view?usp=sharing)

I am very unsure of how to find the difference between the rotational part of the EE pose and target pose. For now I am using quaternions but I am not sure that the way that I am computing the difference is correct. To compute the rotation error I multiply the inverse of the EE pose quaternion with the target pose quaternion. Does that sound right? How can I make sure that the Jacobian uses the same representation for the rotational part? In general, any advice on how to properly compute the error between two poses?

Thanks a lot for the help!

答:
Weird motion

I'm pretty sure it happen because you make wrong implementation on orientation control.

Orientation of end-effector

There are 4 main representation of end-effector orientation which is axis angle, rpy (expanded into 6 types), euler angle (expanded into 6 types) and unit quarternion. Normal jacobian derived freshly from forward kinematic matrix is for axis angle representation, a basic 3x3 matrix representation of orientation located on top left of forward kinematic matrix.

$$FK(\theta)=\begin{bmatrix}R_{3\times3} & D_{3\times1}\\ 0_{1\times3} & 1\end{bmatrix}$$

For axis angle representation error computation, with

Robot orientation (each letter represent column) : $$R_e = \begin{bmatrix}n_e & s_e & a_e\end{bmatrix} $$

Desired orientation : $$R_d = \begin{bmatrix}n_d & s_d & a_d\end{bmatrix} $$

Error would be :

$$e = \frac{1}{2}(n_e \times n_d +s_e\times s_d+o_e\times o_d)$$

If you wanna use other representation such as quarternion the error computation would be different and you would need analytical jacobian Ja.

$$J_a = T\times J$$

where T is transformation matrix. For more detail you can look at "Robotics motion, planning and control" by B. Siciliano sect 3.7.3 for orientation error and sect 3.6 for analytical jacobian. Or code implementation by Peter Corke on his github here

Quarternion error

Your method error computation already correct,

$$e=Q_d * Q_e^{-1}$$


问:
ROS Publish Stereo Image From 2 USB Cameras
I have two monocular USB cameras and I want to use ROS to make it a stereo camera. I am having a hard time finding a ROS package that consumes 2 monocular camera image streams and publishes a depth map or point cloud. These are the ROS topics available for the 2 ROS cameras:

```<code>/my_stereo/left/camera_info
/my_stereo/left/image_raw
/my_stereo/right/camera_info
/my_stereo/right/image_raw
/my_stereo_both/parameter_descriptions
/my_stereo_both/parameter_updates
/my_stereo_l/parameter_descriptions
/my_stereo_l/parameter_updates
/my_stereo_r/parameter_descriptions
</code>```

How can I do this? Any help is truly appreciated!

答:
You can write a simple node which subscribes to the 2 RGB feeds, uses blob matching (look up Stereo matching in OpenCV or Stereo Binary SGBM) to create the stereo image, and publishes it.

Alternately, I think OpenCV contains the functionality for image_to_pointcloud conversion.


答:
1. What you ask

Ok you already know jacobian is need to map end-effector cartesian velocity into joint angular velocity.

$$\dot\theta=J^{-1}\dot x$$

And I assume, you know how to control the position. For orientation control it similiar to position control but the computation of error it bit tricky. First you need to define what is representation of your end-effector orientation. There are 4 main representation of end-effector orientation which is axis angle, rpy (expanded into 6 types), euler angle (expanded into 6 types) and unit quarternion. Normal jacobian is for axis angle representation. You can take a look example of axis angle orientation error computation on my other answer here.

If you wanna use other representation such euler angle, you need analytical jacobian Ja.

$$ J_a = T*J$$
where T is transformation matrix.For more detail you can look at "Robotics motion, planning and control" by B. Siciliano sect 3.7.3 for orientation error and sect 3.6 for analytical jacobian. Or code implementation by Peter Corke on his github here

2. The simple approach

You can see that joint 4 value which control orientation are affected by joint 2 and 3.If you wanna make your system simpler, you can set that joint 4 is not there on forward kinematic & jacobian computation( so you make joint 4 as end-effector not as joint).

In this graph, with A are joint 2 value, B joint 3 value, C joint 4 value and brown line is imaginary line, then

$$360^o = 90^o + A + B + C$$
$$ C = 270^o - A - B $$

with that you could avoid orientation computation while still control the position of end-effector and keep end-effector point down (or anywhere, you just need to redraw and recompute my graph for your desired orientation)

Title: Orientation Problem of a 4-DOF manipulator

Body:
As shown in figure, I have a 4-DOF manipulator.

I want to control the robot such that the end-effector should always be pointing down no matter where the robot is in the end space. For the orientation problem, I derived the Jacobian matrix, then derived the path equations parameterized with time t, but I am still not sure on how to keep the end-effector pointing downwards all the time. $w_{x}$ and $w_{y}$ control the end-effector orientation but how can this be implemented? Any help will be greatly appreciated.


答: First, you need to get rid of the damping matrix C as it transforms kinetic energy into heat. Second, you should make the mass matrix as small as possible. (lightweight construction). After that you can think about the best way to distribute the mass that you cant get rid off by taking the desired movements into account.</p>

Title: Equations of motion in matrix form and energy consumption

Body:
I am working on Lagrangian derived high-dimensional motion equations for a robot in matrix form. The structure of such an equation is known:

$M(q)\ddot{q}+C(q,\dot{q})\dot{q}+G(q)=0$

In here, $M(q)$, $C(q,\dot{q})$ are matrices, and  $G(q)$ are vector.

Are there any properties of $M(q)$, $C(q,\dot{q})$, $G(q)$ related to the power consumption of the robot and is it possible to optimize power consumption by operating with these very properties?

Remark: I mean they are matrices, vectors, etc., i.e. is it possible to somehow use their traces, determinant, norm and other to use for the study of energy consumption?


问:
Calculate information matrix for graph slam
0

I am new to SLAM. I am working on graph slam where I need to do pose graph optimisation. For this requirement information matrix is required between two edges for which the transformation has already computed using iterative closest point. I used Open3D library to compute this as well as information matrix. However I don’t know what is information matrix and how it is calculated given the transformation between two nodes. I would also appreciate the mathematical derivation.

答:
The information matrix is just the inverse of the covariance matrix.

I recommend you read the page I linked, or just google covariance matrix. Essentially it contains how certain you are in your measurements. (The lower the number the less uncertain you are).

As an example:

The translation matrix between nodes(ignoring rotation for now). Your covariance matrix should look something like this

$$\begin{bmatrix}
\sigma_{xx}^2 & \sigma_{xy}^2 & \sigma_{xz}^2\\
\sigma_{yx}^2 & \sigma_{yy}^2 & \sigma_{yz}^2 \\
\sigma_{zx}^2 & \sigma_{zy}^2 & \sigma_{zz}^2
\end{bmatrix}$$

Where the $\sigma_{aa}$ is the standard deviation of your $a$ measurement, and $\sigma_{ab}$ is the correlation between $a$ and $b$(In many situations people just set this to 0).

Ideally these values should be determined experimentally, but in most cases people just put values that intuitively feel right. E.g for a translation edge we might set it to

$$\begin{bmatrix}
0.1^2 & 0 & 0\\
0 & 0.1^2 & 0 \\
0 & 0 & 0.1^2
\end{bmatrix}$$

because we believe our translation measurement is accurate to about 0.1 meter. We have also decided to ignore the correlation terms.

The information matrix is equal to the inverse of this matrix so in our case it would be

$$\begin{bmatrix}
\sigma_{xx}^2 & \sigma_{xy}^2 & \sigma_{xz}^2\\
\sigma_{yx}^2 & \sigma_{yy}^2 & \sigma_{yz}^2 \\
\sigma_{zx}^2 & \sigma_{zy}^2 & \sigma_{zz}^2
\end{bmatrix}^{-1} =\begin{bmatrix}
0.1^2 & 0 & 0\\
0 & 0.1^2 & 0 \\
0 & 0 & 0.1^2
\end{bmatrix}^{-1} = \begin{bmatrix}
100 & 0 & 0\\
0 & 100 & 0 \\
0 & 0 & 100
\end{bmatrix}$$

Note that since the information matrix is the inverse of the covariance it has the opposite property that the higher the number the better the measurement. Essentially a bigger number means that we have more information about it.

I mentioned that you can set the values intuitively or determine them experimentally, another approach that you can use since you are using ICP is the "Hessian matrix" of the optimization problem. In Open3D this is the JTJ matrix computed here. Essentially the "Hessian" describes how well your problem is constrained, and thus can serve as your information matrix.

All 3 methods I described for computing it are viable, and there are also a bunch more complicated algorithms. Generally for pose graph SLAM I would say people just intuitively set some values.

Note that in your case since you have the full transform your covariance/information matrix should be 6x6.


问:
How to attach plate to stepper motor?
Total noob here (never touched Arduino before today), & have pretty much no hands-on technical experience (although with lack of experience, I make up in enthusiasm to learn!)

Question: How do you attach a plate (material of plate yet to be decided, likely stiff cardboard) to a stepper motor? See image demonstration below:

Do I punch a hole in the middle of my plate and super glue the hole to the motor shaft?

The end goal is to have a rotating plate like a microwave (the plate will hold some items).

Summary; How do you securely attach a plate to a stepper motor without it collapsing from the weight of the plate? Should I even be putting a plate onto a stepper motor? Or should I use a servomotor?

Thank you!

答:
Have a Google at double flat drive couplers, sometimes called oval, or dual drive flat.

Something like this might do the trick:

Also see How can I attach an arm to a double-flat drive stepper motor?

Title: How to attach plate to stepper motor?


问:
Number of pixels required to identify something
When using an RGB camera, what is the minimum number of pixels of an object that you need to identify something (theoretical or rule of thumb)?

The image would be taken out in the wild with a complex scene and the objects would not be known to be there but they will be in a list of known candidates.

By identify I mean, from an unknown object can you detect it and discern whether it is a tree, a monkey or a sheep as opposed to just seeing a blob and only being able to tell it is a blob.

答:
There is no really precise answer on your question. There are a lot of parameter would affect number of required pixel, what kind of detection method you use, how do you preprocess the image, noise of image and etc.

Say you perform color based detection. You wanna if there is object colored red somewhere on your image. Then how many pixel needed? One.

If you perform marker based detection, then depends on the marker itself and algorithm to detect it. You make marker sized 3x3, then needed pixel is 9 pixel minimum probably.

If you perform detection using any kind of machine learning, then it depend to machine learning you use. The best way to get answer of your question is by testing.


答:
As @jsotola has implied in the comments, context is everything. I think there will be many answers to your question in its general form. You may need to expand on your question to generate more meaningful answers.

Resources I found that might help you progress - -

Information about image processing in robotics. https://link.springer.com/chapter/10.1007/978-3-319-62533-1_12

Research from fields where they are forced to use limited resolution. “Image recognition with a limited number of pixels for visual prostheses design”
(Sheng Li et al. Artif Organs. 2012 Mar) https://pubmed.ncbi.nlm.nih.gov/21954832/

The question seems related to your previous question Number of pixels on an object. Is that correct? Do they share context?

Title: Number of pixels required to identify something

Body:
When using an RGB camera, what is the minimum number of pixels of an object that you need to identify something (theoretical or rule of thumb)?

The image would be taken out in the wild with a complex scene and the objects would not be known to be there but they will be in a list of known candidates.

By identify I mean, from an unknown object can you detect it and discern whether it is a tree, a monkey or a sheep as opposed to just seeing a blob and only being able to tell it is a blob.


问:
How can I receive Genicam packets from a device in a docker container?
I installed a command line tool which accepts genicam packets from a device as input into a docker image. If I use the option --network host in the run command for the container the packets are received. If I use -p 3956:3956/udp to expose the Genicam default port 3956 (e.g. stated here: RoboRealm - GenICam - Instructions) in the run command of the container I don't get packets. What did I wrong? Could the port be different from the default? How could I get the changed port then?

答:
Here is a plug and play solution in docker compose for it, however please check your container for vulnerabilities. If you do not use docker networks you can use network mode host instead.

version: '3.7'

services:
  your_container:
    image: your_image
    container_name: your_container
    #network_mode: host
    networks:
     - camera_vlan

networks:
  camera_vlan:
    driver: macvlan
    driver_opts:
      parent: enp2s0 # your adapter name goes here
    ipam:
      driver: default
      config:
        - subnet: "your.device.ip.goes/here"
```</span>
</code>```


问:
Epson RC+ line numbers
I am programming an EPSON SCARA robot using RC+ 7.4.8. Any error in compiling the program shows in red in the bottom status bar with the error message, program and line number.

This would be wonderful if the program files had line numbers. I have found no mention of this anywhere on the internet or within EPSON's manual etc.

Does anyone know if it is possible to get line numbers in program files on RC+?

答:
I tried looking around online and found a manual for RC+ 4.x that mentioned a "renumber" and "strip line number" command, but the manual for the 7.x version makes no mention of the same, so I downloaded a trial version of the software, looking for those buttons.

I didn't find any way to turn on line numbers in the file, but I did see that it's indicated on the bottom-right corner of the screen. Hope this helps!

Title: Epson RC+ line numbers


问:
Forward/inverse kinematics and transformation matrices
I have found the homogeneous transformation matrix that can be used to determine the relation between the parent and child links of a robot. This matrix is shown below.

$T_i =
\left[\begin{array}{ c c c c }
\cos \theta_{i} & -\sin \theta_{i} & 0 & a_{i-1} \\
\sin \theta_{i} \cos \alpha_{i-1} & \cos \theta_{i} \cos \alpha_{i-1} & -\sin \alpha_{i-1} & -\sin \alpha_{i-1} d_{i} \\
\sin \theta_{i} \sin \alpha_{i-1} & \cos \theta_{i} \sin \alpha_{i-1} & \cos \alpha_{i-1} & \cos \alpha_{i-1} d_{i} \\
0 & 0 & 0 & 1
\end{array}\right]$

I have used this matrix together with the Denavit Hartenberg parameters to make a Matlab Rigidbody Tree model. All the joints of the robot are behaving correctly. Does this mean that these matrices solve the forward kinematics? And what steps would I have to take to get the inverse kinematics in a Simulink block for example?

答:
For each joint relation you model, you would get one homogeneous transformation matrix (HTM) T
$$T^{i-1}_i$$
If you multiply all HTM from base to end-effector, you would get what is called forward kinematic matrix FK
$$FK(\theta) = T^0_N= T^0_1*T^1_2*...*T^{N-1}_N$$
which map joint configuration into cartesian space (represent pose of end-effector). Then for inverse kinematic there are two main method, graphical method and analytical method. For low number DOF (degree of freedom) (DOF<3), you can perform graphical method, by calculating end-effector and joint relation using simple trigonometry function. For high number DOF (DOF>3) , you should perform analytical method. This method really complex, but luckily there are several library available for MatLab which you can use such as RTB or MatLab official library.

There is one indirect method of inverse kinematic, that is by using Jacobian matrix.


问:
Affordable pi like computer for robot
I have raspberry pi in a robot but it seems sdcard is not reliable at all.

What are affordable options that could be considered reliable? Pi+USB Flash, Pi+USB SSD, Pi compute module with eMMC, BeegleBoard with eMMC?

May be there is some reliable SD card brand or USB_Flash?

I would say my budget is up to $350 and I need linux computer with performance of Pi3 and 2-4 USB ports + IO

It seems to me right now that Pi+USB_Good_Brand_SSD is most reliable option. But may be I miss something.

答:
The Argon One case has a USB 3.0 M.2 adapter for the raspberry pi 4. So, you could use an SSD instead of an SD card, if that is where you're having issues.

https://www.argon40.com/argon-one-m-2-case-for-raspberry-pi-4.html

Title: Affordable pi like computer for robot


问:
Facial Detection combined with Path Planning using Kinect Sensor
I am planning to use a Kinect Sensor on a mobile robot for path planning based on facial detection.

Assuming I am able to detect the faces of 5 individuals in a room (both the environment and the people are static), can I somehow get the coordinates of said faces, and use those as reference points to draw a path the robot should follow (using a Nearest Neighbor algorithm for example) while stopping at those individual points for 5 seconds? Can you indicate me to any resources, papers, or GitHub repositories explaining it? Also, would I need any odometry or can it all be done through Computer Vision?

Note: once detected, the faces' coordinates need to be memorized as there is no guarantee that they will remain visible throughout the entire process.

答:
Assuming I am able to detect the faces of 5 individuals in a room (both the environment and the people are static), can I somehow get the coordinates of said faces

Yes, since the Kinect has a depth sensor embedded.
See https://pterneas.com/2016/08/11/measuring-distances-kinect/ as a vague intro.
I would suggest you get the Kinect SDK working on your machine. There must be several resources online with tutorials on how to get this to work.

and use those as reference points to draw a path the robot should follow (using a Nearest Neighbor algorithm for example) while stopping at those individual points for 5 seconds?

Yes. But here you should decide on whether you are happy re-planning once you reach each of the points or you want to save the reference path, and resume with the next waypoint once you waited for 5 seconds.
Moreover, since you have a non-flying robot, remember to project the xyz point into the 2D plane (i.e. just take xy coords).
Also take into account that unless you use an optimization-based algorithm (accurately fed with your robot kinematic model) which can plan a drivable path throughout the set of points, you might end up with the wrong orientation at each stop.

Also, would I need any odometry or can it all be done through Computer Vision?

Having odometry data is essential in order to track where is your robot. Typically this is provided by sensors on the actuators. If you do not have such sensors, another option is to get "visual odometry" from the Kinect directly, but that is probably an advanced problem to tackle at your stage.

Note: once detected, the faces' coordinates need to be memorized as there is no guarantee that they will remain visible throughout the entire process.

That is something that affects your particular implementation. A simple C++ vector can do the job of saving the coordinates.