Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Monday, September 17, 2018

how to subscribe from server (javascript, html, python, ajax)

EventSource, stream.onmessage, Response()

javascript side


    var stream = new EventSource('/api/stream');
    stream.onmessage = function(e) {
      console.info(e.data);
      $("#received").append(e.data+"\n");
      $("#received")[0].scrollTop = $("#received")[0].scrollHeight;
    };


python side

#from queue import Queue
#from flask import Response
queue = Queue()
def event_stream():
    while True:
     # Question: how to break out of this loop when the app is killed?
        message = queue.get(True)
        print("Sending {}".format(message))
        yield "data: {}\n\n".format(message)


@app.route('/api/stream')
def stream():
    return Response(event_stream(), mimetype="text/event-stream")


reference 
https://www.w3schools.com/html/html5_serversentevents.asp

Friday, September 14, 2018

How to modify cache control max age value in Flask Python

@app.after_request
def add_header(response):
    response.cache_control.max_age = 1
    return response

just add this code

Thursday, August 23, 2018

[Study] Flask url_for example

Why is this needed?

A YouTube video was the first time I encountered url_for feature. I couldn't understand what it was, for what it is. And today, I began to read the official manual

http://flask.pocoo.org/docs/0.12/quickstart/#url-building

And there are a lot of example code from opensource projects
https://www.programcreek.com/python/example/51519/flask.url_for


in short, url_for() function looks up app.route('/here')
if there are more than one app.route('/here'), the function looks up right above the function

test.py

from flask import Flask, url_for, render_template

app = Flask(__name__)

@app.route("/")
@app.route("/1st")
@app.route("/2nd")
@app.route("/3rd")
def lookAtMe():
    return render_template('index.html')

if __name__ == "__main__":
    app.run(debug=True)


index.html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    {{ url_for('lookAtMe') }}
  </body>
</html>

result


Tuesday, August 21, 2018

How to use render_template in Flask

Why template is needed?

Let's say we need to a number of dynamic html page. The page need to be changed based on data from outside. Without template, we need to make a static HTML page in manual way. "template" gives an easy way to replace page's content in a very simple way. it feels like a mail merge feature in a word processor.
As we want to make a dynamic page, we need to use this feature "template"

(I am following this Flask tutorial)

This instruction shows how to deal with template, url_for in Flask.

How to use "template"?

import class

in order to use "template", firstly we need to import a class named "render_template" in python file.


from flask import Flask, render_template

preparing a HTML file in "templates" folder

I prepared "hello.html" inside of templates folder.

templates/hello.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <h1>This is hello world</h1>
  </body>
</html>


code it (test.py)

from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
@app.route("/hello")
def hello():
    return render_template("hello.html")

if __name__ == "__main__":
    app.run(debug=True)


result 


Sending Data 


from flask import Flask, render_template
app = Flask(__name__)

varForPython = ["welcome", "to", "my", "channel!"]

@app.route("/")
@app.route("/hello")
def hello():
    return render_template("hello.html", varForHtml = varForPython)

if __name__ == "__main__":
    app.run(debug=True)

Receiving Data and Using it in the HTML file



<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    
    {% for line in varForHtml%}
    <h1> {{ line.name }} </h1>
    <p> {{ line.title }}</p>
    <p>{{ line.date }}</p>
    {% endfor %}

  </body>
</html>

Thursday, August 16, 2018

How to Read Multiple (or single) Dynamixel AX12 Position value using Dynamixel SDK (Python)

Why is reading status important?


Every Robotis Dynamixel servo motors has feedback feature. We can read its status data such as current angle, speed or temperature. When you make a robot and teach them how to move, we have to give them a number of sets of angle data for each motors. In order to make the motion set, we have to know current angle value for each. What if there is no way to read their angle? We may have to calculate or measure many times. It is not efficient.
On the other hand, Robotis Dynamixel returns when they are asked to return their status. All we have to do is to save all the angle values to a proper storage. In this way, we can capture the motion set. Normally, small humanoid robot moves based on the motions on the timely based. It is really similar to a way to make an animation. A lot of scenes are changed in a specific time period. Like this method, we can teach our robots how to move.

Let's Try!

Preparation

sample code

Download the file here "read_AX12.ph"
I modified the sample code for Dynamixel AX12.  put the file into the folder .\python\tests\protocol1_0\

part list 

2 * AX12 (ID: 1, 2 | Baudrate 1)
1 * USB2DYNAMIXEL
1 * SMPS2Dynamixel

ID Setting

You need to prepare 2 * AX12, Change their ID as '1' for one, '2' for the other. 
The simplest way to change ID is to use Dynamixel Wizard with USB2Dynamixel. 

How I did it (strategy)

Open a proper example

I opened SDK example named "read_write.py". The file was for MX series. In order to use AX series, I needed to change some detail. 

Change Serial Com Port Information

Of course I need to change Com Port number and the baudrate number. I already set up the AX12's baudrate as 1000000. My pc allocated the USB2Dynamixel to COM4.




Check the instruction table

Because I want to read "present position" of the motors, I checked which number is for the present position. The address is 36. So, I am going to request the AX12 to return value from address 36. If everything is good, the AX12 will dispatch value from its address 36 and return them to me. Ass you can see, the size of value is 2 byte. So, consequently, we need to request AX12 to dispatch 2 bytes from address 36. 



The request look like this.
"Hey AX12 ID number 1, read 2 bytes of data from your address table 36. "
Then AX12 ID number 1 will return present position. When the packet received well, I will request the other AX12 (ID number 2) to dispatch the data in the same way.
"Hey AX12 ID number 2, read 2 bytes of data from your address table 36."
The, the AX12 will return present position value.

In this way, there must be time difference between motors because the reading moment time must be different. Robotis gives a synchronized method named Bulk Read. Unfortunately, AX12 doesn't have Bulk Read feature.

Result 

I am able to read motor's position more than 2 motors at the same time (actually, there is time difference though). 



Faced a problem

I faced a big problem. There are so big time delay. It takes at least 15 ms for reading. Because I will make a robot with 21 motors, it will take 15 * 21 = 315 ms for every single frame which means 3 fps (frames per second). That is too low. I need at least 24 fps. I tried to figure out and found a solution at last. I will post it later.
https://eunchanpark.blogspot.com/2018/08/how-to-reduce-serial-communication.html

Wednesday, August 15, 2018

How to run multiple Dynamixel (AX12 / Windows / Python / Dynamixel SDK) at the same time

Why is This important?

Because a robot need to move their motors all the same time especially for a joint robot. Let's think about that you want to push a door. You will reach out your hand by unfolding your arm and shoulder at the same time. If there is time gap between shoulder and arm, you cannot push the door properly. A normal RC servo motor is connected main controller in parallel way which means you can control them together at the same time. But, Dynamixel, on the other hand, shares their data line. There must be time gap between each other because every instruction is carried by communication. Some motors get data packet earlier than others. If the motors move as soon as they get data packet, we may have serious problem. We can say this as asynchronized.
How can make them synchronized? Robotis gives two ways to fix this problem.

Features we will use

1. Reg Write and Action - keeping instruction and waiting for Action instruction. 

Let's say there are 3 bus drivers and a boss. The boss just give them their destination. They will wait until boss say "Action"
Boss: Here is your destinations. A goes a city, B goes b city and C goes c city. Wait until I say "Action"
Bus Divers: Okay.
(waiting...)
Boss : Action!
Bus Drivers: (go now at the same time)
http://emanual.robotis.com/docs/en/dxl/protocol1/#reg-write

2. Sync Write - keeping instruction, waiting until the packet finished

Boss : I am going to give you destinations. Everyone has to wait for I finish this announcement. As soon as I finish this statement, go yours immediately. A driver goes a, B driver goes b and C driver goes c. Let's go!
Drivers : (go now at the same time)
http://emanual.robotis.com/docs/en/dxl/protocol1/#sync-write


Let's Try!

In this post, we are going to use "Sync Write". Because it is more intuitive in my opinion.

Preparation 

sample code

I modified the sample code for Dynamixel AX12.  put the file into the folder .\python\tests\protocol1_0\

part list 

1 * USB2DYNAMIXEL
1 * SMPS2Dynamixel

ID Setting

You need to prepare 2 * AX12, Change their ID as '1' for one, '2' for the other. 
The simplest way to change ID is to use Dynamixel Wizard with USB2Dynamixel. 

Let's Try!

if you don't know how to run these examples, please refer to the previous post http://eunchanpark.blogspot.com/2018/08/how-to-use-ax12-robotis-dynamixel-with.html

I changed some code for AX12. The original code was for MX series. I somehow don't understand why Robotis gives the example as Protocol_2.0 version. Anyway, if you read the code, you will understand it. Sync write only set the start address of the instruction table. You can write parameters from the starting address. It is somehow tricky but efficent. I think that is one of why the goal position address and the goal speed address is adjacent to each other.






reference
http://emanual.robotis.com/docs/en/dxl/protocol1/
http://emanual.robotis.com/docs/en/dxl/ax/ax-12a/






Tuesday, August 14, 2018

How to use AX12 (Robotis Dynamixel) with Python by using Dynamixel SDK (in Windows)

Robotis Dynamixel is not a normal servo motor. In order to control them, we need to send proper packet through serial communication. This is a kind of barrier for the beginners to make a code because there is something to study. You will need to calculate a checksum byte, find instruction code in the manual and so on. But, don't worry, there is a well-made SDK which is given by Robotis. The only one problem is that the documentation is written by professional. So, I am going to share the way as detailed as possible. If you just follow a few steps, Dynamixel would say "hello world"

1. Install Python



installation is very straightforward. 

2. Download SDK files 



Click "Clone or Donwload"  and "Download ZIP"

3. Install SDK 

Extract the zip file we downloaded




open the python folder




Copy (Control + C) the path  (the path may different to yours)



Open "Command Prompt" (in start menu, type 'cmd' and this icon will be appeared)

 


type cd and paste the path, press enter



type  "python setup.py install" and done!






4. Check Your Com Port


Plug your "USB2Dynamixel" to your PC



Open "Device Manager" to check your Com Port





In my case, it was COM4

5. Modify Com Port in the source code (.\python\tests\protocol1_0\ping.py)


# Default setting
DXL_ID                  = 1
BAUDRATE                = 1000000
DEVICENAME              = 'COM4'




6. Test (ping.py)




7. Run motor "read_write.py"


As the drawing, if you get ping Succeeded, then everything is ready to use. Let's move the AX12. In order to run AX12, we need to use read_write.py file. I just changed Com Port and Baud rate but there was some problem. The motor didn't react at all. I fount the problem in the instruction table. we need to change code like this


We also need to change here because AX12 returns only 2 Bytes.



Because the control table address was different. So, we need to change address.
Let's play with this code!




Conclusion

Personally, I hope there is more detailed information for the series. Robotis has a lot of Dynamixel series. I have to make a instruction table for AX12 in order to use every features of AX12. Next time, I will share you some more code for AX12.

URDF Link origin test