cfry / dde Goto Github PK
View Code? Open in Web Editor NEWDexter Development Environment
License: Other
Dexter Development Environment
License: Other
Those of us who are in the habit of quickly saving our code as we type by pressing Alt-F and S or Ctrl+S will be shocked to find that neither of those actually save anything.
Suggestion: Adding keyboard accelerators for File / Save would Save programmers a lot of lost time when DDE gets into a mode that prevents us from saving.
Getting started on some of the chores we discussed previously, First up, fixing DDE's CI system.
Appveyor + electron builder seems to be having some issues, so rather than fix those, I proposed we switch to GitHub actions, a CI system native to GitHub. Also, since GitHub is Microsoft now, it supports very decent windows build environments (unlike Travis last we checked).
Here is the plan:
dde/src/job_engine/core/dde_file.js
Line 280 in 2c78cd2
The line above affects the running of the job engine. This line uses fetch, which is provided by Node v18. We could prevent the server from building/running if node isn't version 18, or we could use NVM to cause node to be version 18.
If there is a long instruction running,
(such as in calibrate with a slow speed, move_all_joints can
take 5 minutes)
then clicking the stop button sends an "empty instruction queue now (E oplet )
cmd to dexter but that doesn't stop an ongoing instruction.
It may be the case the "E" doesn't empty the queue as it is
intended to.
Targeted platforms:
It would be wonderful to have a way to set the font size on startup.
On the Doc panel search box, type in "move to" (no _) and press Find
Drill down to Reference manual, Robot, Dexter, Dexter Instruction.
Notice that move_to is NOT highlighted. Multiple other instructions starting with move_to like move_to_relative /are/ highlighted.
With some, but not all, sets of points, when processing a DXF file or text_to_lines string, the last several lines or part of a letter are simply not drawn, and the end effector stops while in contact with the drawing plane. To compensate, an "e" or other letter with a curved segment was added for the demo. Other point sets, which wrote at right angles to the original, processed all the data and the end effector was raised above the plane at the end.
The specific point sets which causes this problem were, sadly, lost. I will try to re-create the issue if that will help.
If you get this error you might follow these directions to get around it
https://support.apple.com/guide/mac-help/apple-cant-check-app-for-malicious-software-mchleab3a043/mac
Is there a forum for this project? I ask since this comment is more appropriate for a forum than an issue report.
In the DDE documentation for MIDI setup on Windows one can find this request "Please tell us if you've had success here and what you did to achieve it." This is what worked for me:
I installed http://coolsoft.altervista.org/en/virtualmidisynth#soundfonts
Then downoaded and extracted "FluidR3 GM Bank" from:
http://www.synthfont.com/soundfonts.html
From VirtualMIDISynth I imported the "FuidR3 GM Bank" sound fonts.
Restarted DDE load a MIDI example code and eval it.
When trying to run a DDE Job that
sends instructions to a robot right after
turning the robot on, a bad error happens
that's hard to recover from.
James H didn't recall this happening in the
robot's that have "the dance", maybe simply because
when the robot is dancing, the operator
knows not to attempt to send something to
the robot.
In any case, waiting a while after turning
dexter on (a minute? not sure)
it seems to be ok.
So that's the workaround.
But this is just a workaround, we can't
expect our users to do this.
We need some kind of a signal from
Dexter to DDE, or for DDE to do some
kind of polling , or simply having
Dexter handling gracefully instructions
when its not quite ready to.
the exec function returns instantly and continues to run espeak in the background, so that it's possible to call speak again. If speak is called multiple times, all the message appear on top of each other.
We fixed this once,
HaddingtonDynamics/Dexter#72 (comment)
but the fix wasn't incorporated and the code in DDE has changed enough that it needed to be re-implemented. I know the code below is working on my robot using job engine version 3.5.2, and I /think/ this will not cause problems going forward.
var to_speak = []
function speak({speak_data = "hello", volume = 1.0, rate = 1.0, pitch = 1.0, lang = "en_US", voice = 0, callback = null} = {}$
if (arguments.length > 0 && speak_data != null) {
var speak_data = arguments[0] //, volume = 1.0, rate = 1.0, pitch = 1.0, lang = "en_US", voice = 0, callback = null
//out("speak_data:"+speak_data);
}
var text = stringify_for_speak(speak_data)
if(window.platform == "node"){
if (speak_data != null) { //new speech text
let speak_cmd = "espeak \"" + text + "\" -a "+ (volume*200) + " -p " + (pitch * 50) + " -s " + (rate * 37 + 130)
to_speak.push(speak_cmd)
//out("saylater:"+speak_cmd)
}
else { //finished speaking prior text
if (to_speak.length > 0) { //say what's on the stack, dump, and call again with null
//out("saying: "+to_speak[0])
exec(to_speak[0], function(){ to_speak.shift(); speak({speak_data:null}); })
}
else {
//out("done saying");
if (callback) callback();
}
}
if (to_speak.length == 1) { //last one
//out("lastword:"+to_speak[0])
exec(to_speak[0], function(){ to_speak.shift(); speak({speak_data:null}); })
}
}
else {
var msg = new SpeechSynthesisUtterance();
//.... same from here down.
In a call with Fry, we mentioned distribution channels. This kind of thing is discussed here as a starting point:
https://www.electron.build/tutorials/release-using-channels
A prerequisite for this is an electron auto-update implementation, which takes a fair amount of work to get right.
Didn't change anything, it just suddenly stopped working. It's a real problem because the IP address and all the settings are in there.
Pulling down the current release of DDE, version 3.6.3, and installing it as a new job engine fails during install. See the console output below, and attached log file. The issue this time appears to be
https://github.com/tessel/node-usb
which may be a require from serialport (because that was the prior item) or might be something else.
It's trying to find a pre-built binary for the given version of node, arm processor, and linux, but those aren't available, so it tries to build from source, and fails while building libusb/os/linux_udev.o without finding a file called libudev.h
Console messages:
root@localhost:~/Documents/dde# npm install
npm WARN deprecated [email protected]: three-js exposes real modules now via three/examples/jsm/...
npm WARN deprecated for example to import Orbit, do
npm WARN deprecated import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
npm WARN deprecated
npm WARN deprecated [email protected]: Starting with three.js r103, GLTFLoader is included in the three package itself and installing three-gltf-loader is no longer necessary. It can be imported from 'three/examples/jsm/loaders/GLTFLoader'
> @serialport/[email protected] install /root/Documents/dde/node_modules/@serialport/bindings
> prebuild-install --tag-prefix @serialport/bindings@ || node-gyp rebuild
prebuild-install WARN install No prebuilt binaries found (target=11.6.0 runtime=node arch=arm libc= platform=linux)
make: Entering directory '/root/Documents/dde/node_modules/@serialport/bindings/build'
CXX(target) Release/obj.target/bindings/src/serialport.o
CXX(target) Release/obj.target/bindings/src/serialport_unix.o
CXX(target) Release/obj.target/bindings/src/poller.o
CXX(target) Release/obj.target/bindings/src/serialport_linux.o
SOLINK_MODULE(target) Release/obj.target/bindings.node
COPY Release/bindings.node
make: Leaving directory '/root/Documents/dde/node_modules/@serialport/bindings/build'
> [email protected] install /root/Documents/dde/node_modules/usb
> prebuild-install --verbose || node-gyp rebuild
prebuild-install info begin Prebuild-install version 5.3.6
prebuild-install info looking for cached prebuild @ /root/.npm/_prebuilds/2b648a-usb-v1.6.3-node-v67-linux-arm.tar.gz
prebuild-install http request GET https://github.com/tessel/node-usb/releases/download/v1.6.3/usb-v1.6.3-node-v67-linux-arm.tar.gz
prebuild-install http 404 https://github.com/tessel/node-usb/releases/download/v1.6.3/usb-v1.6.3-node-v67-linux-arm.tar.gz
prebuild-install WARN install No prebuilt binaries found (target=11.6.0 runtime=node arch=arm libc= platform=linux)
make: Entering directory '/root/Documents/dde/node_modules/usb/build'
CC(target) Release/obj.target/libusb/libusb/libusb/core.o
CC(target) Release/obj.target/libusb/libusb/libusb/descriptor.o
CC(target) Release/obj.target/libusb/libusb/libusb/hotplug.o
CC(target) Release/obj.target/libusb/libusb/libusb/io.o
CC(target) Release/obj.target/libusb/libusb/libusb/strerror.o
CC(target) Release/obj.target/libusb/libusb/libusb/sync.o
CC(target) Release/obj.target/libusb/libusb/libusb/os/poll_posix.o
CC(target) Release/obj.target/libusb/libusb/libusb/os/threads_posix.o
CC(target) Release/obj.target/libusb/libusb/libusb/os/linux_usbfs.o
CC(target) Release/obj.target/libusb/libusb/libusb/os/linux_udev.o
../libusb/libusb/os/linux_udev.c:40:21: fatal error: libudev.h: No such file or directory
compilation terminated.
libusb.target.mk:138: recipe for target 'Release/obj.target/libusb/libusb/libusb/os/linux_udev.o' failed
make: *** [Release/obj.target/libusb/libusb/libusb/os/linux_udev.o] Error 1
make: Leaving directory '/root/Documents/dde/node_modules/usb/build'
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/usr/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:262:23)
gyp ERR! stack at ChildProcess.emit (events.js:188:13)
gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:254:12)
gyp ERR! System Linux 4.4.30-xillinux-2.0
gyp ERR! command "/usr/bin/node" "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /root/Documents/dde/node_modules/usb
gyp ERR! node -v v11.6.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
npm WARN [email protected] requires a peer of @types/three@* but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] No repository field.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: `prebuild-install --verbose || node-gyp rebuild`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2020-11-03T23_41_34_149Z-debug.log
root@localhost:~/Documents/dde# node -v
v11.6.0
DDE version since the new simulator was added cause the CPU's to run near 100% on this one computer. On a very simular machine, running Ubuntu 16.04, there is no issue. The GPU cards (and so drivers) are different, so that might be an issue. The versions of node were different but that has been tested and made no difference. (e.g. the problem machine was changed to v10.11.0 which was used on the working machine).
Workaround: Don't start the simulator.
Just ever opening the simulator allows DDE to work on 18.04 without excessive CPU / GPU work.
This is a very minor issue and shouldn't be a worry unless Ubuntu 20.04 has the same problem. That needs to be tested.
When opening the simulator panel on a freshly installed version of DDE, the robot may not show up at all, or just the top of it may be visible upside down in the window.
To work around this problem, pull down the File menu and select New:
paste this code into the main editor panel:
persistent_set("dde_window_width",outerWidth);
persistent_set("dde_window_height",outerHeight);
location.reload();
click the Eval button below the editor window.
That should fix the window sizing and then reload the window
This bug should be fixed by
#72
if that is accepted in the next release.
It would be wonderful to have the size and position of the window on startup.
This will avoid the user driving the robot into the floor when leaving the donut and running the resulting job. Ask the Jameses.
When calibrating a dexter that is NOT dexter0,
and there's no dexter0 connected to DDE,
there's an error, that's at the very least confusing,
because dde is attempting to contact
dexter0 for no good reason. (and it shouldn't
be doing that!)
To diagnose this, I searched though all
of DDE's uses of dexter0,
and didn't find anything particularly suspicious.
Then I read by hand the 5 files under the
low_level_dexter folder.
My guess is the problem comes when there
is a job created for calibration who's
robot defaults to dexter0 when it shouldn't.
Below are my notes of code that looks
suspicious, especially the last one:
find_home_for_DDE_2.js line 38
ezTeach.js line 160 calling init.
ezTeachBase.js line 66
calibrate_optical.js defines job Calencoders defaulting robot to dexter0
but calibrate_ui.js line 275: is Job.CalEncoders.start({robot: cal_get_robot()})
If this is the only place Caelncoders is started, ok,
but if user starts it from the jobs bar, it will use dexter0.
However, this code is in a TRY so ought to protect against bad ip_address
ViewEyeRealTime, line 214 defines job CalSensors whose robot
default to dexter0
right after the def is
let ip_address = Job.CalSensors.robot.ip_address
let path = "//" + ip_address + "/share/AdcCenters.txt"
so its really trying to use that ip_address of dexter0
even without running the job. Looks bad.
JamesW, I hope you can look at these
code snippets and image what will happen
if there is no dexter0.
Maybe just try running Caibrate
without a physical dexter0, see what breaks
and think about better error messages
or whatever. I'm happy to consult.
The following code, adapted from:
https://docs.opencv.org/3.4.1/js_face_detection_camera.html
and the webcam DDE example:
https://github.com/cfry/dde/blob/master/examples/opencv_process_webcam.js
Generates the following error:
While calling the show_window handler function of: handle_webcam_video,
undefined
Error at dde_error (file:///C:/Program%20Files/dexter_dev_env/resources/app.asar/utils.js:29:15) at HTMLInputElement.window.submit_window (C:\Program Files\dexter_dev_env\resources\app.asar\output.js:641:9)
After staring at it for rather a long time, I've found I have no clue how to debug that. I'd like to learn how to debug as much as I'd like to see this fixed.
//inspired by https://davidwalsh.name/browser-camera
var cv = require("opencv.js")
let faces = new cv.RectVector();
let classifier = new cv.CascadeClassifier();
function handle_webcam_video(vals){ //vals contains name-value pairs for each
//html elt in show_window's content with a name.
if(vals.clicked_button_value == "init"){
// Clicked button value holds the name of the clicked button.
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
video_id.src = window.URL.createObjectURL(stream);
video_id.play();
})
}
}
else if (vals.clicked_button_value == "Snap Photo"){
let context = canvas_id.getContext('2d')
context.drawImage(video_id, 0, 0, 320, 240)
let mat = cv.imread(canvas_id)
let grey_mat = new cv.Mat(700, 700, cv.CV_8UC1)
cv.cvtColor(mat, grey_mat, cv.COLOR_RGBA2GRAY)
let dst = new cv.Mat(700, 700, cv.CV_8UC1)
cv.cvtColor(mat, dst, cv.COLOR_RGBA2GRAY)
cv.imshow("out1_canvas_id", grey_mat)
classifier.detectMultiScale(grey_mat, faces, 1.1, 3, 0);
for (let i = 0; i < faces.size(); ++i) {
let face = faces.get(i);
let point1 = new cv.Point(face.x, face.y);
let point2 = new cv.Point(face.x + face.width, face.y + face.height);
cv.rectangle(dst, point1, point2, [255, 0, 0, 255]);
}
cv.imshow('out2_canvas_id', dst);
mat.delete()
mod_mat.delete()
}
}
show_window({content:
`<input type="button" value="init" style="margin-left:4px;"/>
webcam video display.
<input type="button" value="Snap Photo" style="margin-left:115px;"/>
from webcam video.<br/>
<video id="video_id" width="320" height="240" style="border-style:solid; border-width:1; margin:3px;" autoplay></video>
<canvas id="canvas_id" width="320" height="240" style="border-style:solid; border-width:1; margin:3px;""></canvas><br/>
Photo processed to Black and White.
</span><br/>
<canvas id="out1_canvas_id" width="320" height="240" style="border-style:solid; border-width:1; margin:3px;""></canvas>
<canvas id="out2_canvas_id" width="320" height="240" style="border-style:solid; border-width:1; margin:3px;""></canvas>
`,
title: "Processing Webcam video with DDE and OpenCV",
width: 700, height: 600, x: 300, y:25,
callback: handle_webcam_video})
At least on my Dexter, the max positive angle is 152 (vs 153 default) on Joint 3. If it's just mine, the workaround is easy: Just edit the value. If' other people find the same thing, the default should probably be changed.
Joint 3 default range is backwards
instead of 153 to -153 it should be
-153 to 153
Suggestion: In the block language, when a move_all_joints block is selected, if Dexter is calibrated and able to return positions, allow Dexter to be in follow mode and update the angles in the block from arm position.
The low level serial connect code adds the serial port object into the serial_path_to_info_map
entry when it opens a port, and so when the low level close is called, the port can be closed.
The high level serial code does NOT save the port object, but then tries to use it to close the port when the serial robot is closed. This fails, and now no other robot can use that port because it is lost.
(writing this to remind myself to fix it tomorrow am. It's late and I just found this bug, too tired to fix it)
If Cal can't read the AxisCal.txt AdcCenters.txt file from the robot but can still write to it, the file it creates will have all 0's in it except the center for the current joint.
Also a "save as" button should be added for the option to save the file somewhere besides on the robot.
Select an object in a program in the editor. Copy it with Ctrl+C, then try to use the arrow keys to move to the location you wish to paste that value. Instead, the selection is changed to the next or prior value that it might have.
e.g. In the line:
var len = my_array.length
select "length", Ctrl+C, and press left arrow. The selected text changes to "lastIndexOf"
Workaround: Press Ctrl+V to paste the copied text back in and remove the selection.
Suggested fix: If the text has just been copied to the clipboard, disable the changing of the text.
load_files evals the file where file_content gets the file but doesn't eval it.
The name of the function load_files doesn't indicate what the function actually does. Perhaps eval_file would be better? or load_eval_file?
Dexter firmware has been updated (on it's own branch, ready to pull) to accept 2 additional values on the "a" (move all joints) instruction and send those out to set gripper roll and span. This integrates the 2 new servo joints into the move all joints system, bringing it from 5 joints to 7 joints.
However, DDE may not correctly send these values as of 2.5.3. This may happen even when only 5 values are sent in the DDE Dexter.move_all_joints
command as it will try to guess where Joints 6 and 7 were before. There are two problems:
Also, because the SetParam EERoll and EESpan commands also set the End Effector positions (which are Joints 6 and 7), DDE may not correctly track the commanded position, and if a 5 axes Dexter.move_all_joints command is issued, it will assume the user wants Joint 6 and 7 at their last known position, which may be different from where they are now due to the EERoll and EESpan SetParm commands. Either:
See also:
When starting the calibration window it tries to do a read_from_robot to get the Eye Centers.
This fails in the current version of DDE (3.1.0) and hangs up on
"Attempting to read AdcCenters.txt from robot with IP: 192.168.1.142..."
This is done again with the same image and with DDE 2.5.13 (LTS) and it works.
The following is where windows-latest
was changed to windows-2019
, so that the build would pass:
59a4852#diff-5c3fa597431eda03ac3339ae6bf7f05e1a50d6fc7333679ec38e21b337cb6721R62
commit 59a48522bd4b70fdf9dadd2c6f0476d0c49339c1
Date: Tue Feb 8 13:29:47 2022 -0800
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -62 +62 @@ jobs:
- runs-on: windows-latest
+ runs-on: windows-2019
One reason why it might be necessary to get the build to work with windows-latest
, as opposed to windows-2019
, is that it might be possible that there could be some security issue with using windows-2019
instead of windows-latest
.
When I upgraded and try to run my version of forcePlay.js, all I got after pressing any button was
"Warning: Dextersim.send doesn't know what to do with the legal oplet: w"
It apparently modified my dde_init.js file to the following:
`persistent_set("ROS_URL", "localhost:9090") //required property, but you can edit the value.
persistent_set("default_dexter_ip_address", "192.168.1.142") //required property, but you can edit the value.
persistent_set("default_dexter_port", "50000") //required property, but you can edit the value.
//This file is loaded when you launch DDE.
//Add whatever JavaScript you like to the end
//just before the call to "out" in the last line.
//To change DDE colors,
// 1. Uncomment the below line(s).
// 2. Select the first arg.
// 3. Choose Insert menu "Color" item.
// 4. After inserting the new color, eval the "set_" call.
// 5. To get the default color, just comment out the line and relaunch DDE.
// set_window_frame_background_color("#ff8c96")
// set_pane_header_background_color("#e39f5a")
// set_menu_background_color("#ff8c96")
// set_button_background_color("#ff8c96")
persistent_set("default_dexter_ip_address", "192.168.0.142") //required property but you can edit the value.
persistent_set("default_dexter_port", "50000") //required property, but you can edit the value.
new Dexter({name: "dexter0"}) //dexter0 must be defined.
new Dexter({name: "dexter0"}) //dexter0 must be defined.
`
adding the three new lines at the top:
persistent_set("ROS_URL", "localhost:9090") //required property, but you can edit the value.
persistent_set("default_dexter_ip_address", "192.168.1.142") //required property, but you can edit the value.
persistent_set("default_dexter_port", "50000") //required property, but you can edit the value.
and the extra
new Dexter({name: "dexter0"}) //dexter0 must be defined.
to the bottom.
This contradicts the following statement in the documentation under "Updating to the latest DDE": "Follow the directions under First Install above. This will not change any files in your dde_apps folder."
DDE uses the NPM package "SerialPort" to communicate via serial devices. It is currently using version 8:
https://serialport.io/docs/8.x.x
Carefully reading and following the documentation for that object is critical. Especially:
https://serialport.io/docs/8.x.x/api-stream
One problem we have had in the past is that we close the port, and then delete the reference to the serial port object from the map. If the close fails, or isn't a complete close, then we have lost the ability to access that port object. Why the port doesn't close and release the object is the question.
It MAY be that this describes the issue:
https://stackoverflow.com/questions/46307803/nodejs-serialport-re-establish-connection-to-port-after-closed
see this microscopic bit of cryptic documentation:
https://serialport.io/docs/8.x.x/api-stream#serialportresume
Another possibility is that the issue comes from the "port" and the "stream" being two different things. The SerialPort library documents these separately:
https://serialport.io/docs/8.x.x/api-serialport
https://serialport.io/docs/8.x.x/api-stream
Only the stream API has a close method, but maybe that doesn't close the serial port?
But our solution has just been to /never/ close the port once it's open. So the logic is:
SerialPort.update
method to change baudrates, etc... ). If not, open the port and wait for the call back indicating it's open, or for the open event to fire.This comment on this issue (scroll down to the bottom) may be helpful:
HaddingtonDynamics/Dexter#60 (comment)
WinOS Installation Bug
Symptom: While installing DDE on WinOS 7, 10, and maybe others,
you get a dialog box that says "Installing, please wait..."
whose progress bar stops progressing and you have to wait for more than 1 minute.
WorkAround:
Win7: choose Start menu/Control Panel/Programs and Features
Win10: choose Start menu/Windows System/Control Panel/Programs and Features
Click right on "dexter_dev_env".
Choose "uninstall"
You may get a dialog that says:
"An error occurred while trying to uninstall...
Would you like to remove ..."
Click the "Yes" button.
Double click on Downloads/dexter_dev_env-setup-(version number).exe to reinstall.
DDE Should install in 1 minute or less.
Why this happens: If you rename or remove C:\Program Files\dexter_dev_env
it screws up the windows registry, and the DDE installer program can't handle it.
Electron Apps (like DDE) use a program called NSIS for installation, and it has this, ahem, feature.
The current definition of persistent_get appears to completely ignore the second parameter (callback) instead simply returning the retrieved value, but the docs clearly indicate this the callback should be used to access the returned data.
Docs out of date?
Xing out of DDE does not warn that files have been changed and not saved.
Suggestion: Add a popup for stupid people like me who forget to save code before Xing out of a program.
When communicating with a serial device which needs to receive or which will send, binary data, meaning character values over 127, you may find that those values get converted to 'fd' for some unknown reason.
The reason is the bane of my existence: UTF-8.
UTF-8 came from the Unicode effort which was designed to support character sets for languages other than English. English uses only 26 letters, a-z, but there are upper and lower case versions of those so 52 characters. Of course we also need to be able to present the Arabic numerals 0-9 so 62. And then spaces, punctuation marks, etc... perhaps 90 total printable symbols. But don't forget control characters, and then there are latin symbols, accent marks (one for each letter that might need one). We end up pretty much filling up 128 characters. That will fit in 7 bits and ASCII (American Standard Code for Information Interchange) was born. This almost uses up the basic 8 bits available computers work on, so there are actually another 128 characters available from 128-255, which were used for all sort of tricky things; line drawing, graphics, and so on. And for many years, that was good enough.
But there are other countries and other languages and they should be supported. Many other language have a large number of characters, so more than 8 bits are needed. When Javascript was written, it settled on 16 bits, and the UTF-16 set.
https://developer.mozilla.org/en-US/docs/Web/API/DOMString/Binary
"In JavaScript strings are represented using the UTF-16 character encoding: in this encoding, strings are represented as a sequence of 16-bit (2 byte) units. Every ASCII character fits into the first byte of one of these units, but many other characters don't."
So when you set e.g. var myStr = "ABC"
what is actually stored in memory is (in hex) 00 40 00 41 00 42
where 40 is the ASCII code for A (again, in hex). In other words, every byte in the string is a 16 bit word where the bottom 8 bits are actually the value you expected and the top 8 bits are zero. If you need to encode a line of Kangi, or CCCII (Chinese version of ASCII), no problem, you have those extra 65536 - 256 characters to do it in.
But now, think about this: You write that string to a file. Then you open that file in a standard text editor. And it has nulls between every letter. Oops. They could just write out only the low byte, and that would work perfectly for ASCII strings. But what about UTF-16 character sets? Hmmm... They could write those out in UTF-16 just as stored in RAM, but then how would it know which format was used to write the file when you wanted to read the file back in?
So someone had the brilliant idea of creating UTF-8. This uses the same ASCII characters for all values between 0 and 127. But then if you want to write a 16 bit character, it writes out 3 bytes: A "flag" byte which would be C2 (in hex) and then the two bytes of the 16 bit value. When reading the file, that C2 will tell the program that this is not a standard ASCII file and it will decode the next two characters as a 16 bit value. If you want to write an atual C2 in the file, it will write a C1 then C2; the C1 meaning "flag the next byte as a single binary value" and the C2 being the value. In this way, every possible 16 bit value would always make the round trip from RAM to file and back correctly, and ASCII data would still look like ASCII... as long as it didn't use the top bit. And really, ASCII isn't supposed to use that top bit.
Win, win and dusted right?
Well... no. Because what about binary data? e.g. straight 8 bit data which isn't ASCII, but is still stored in a string? Well, first, you aren't supposed to use Strings for binary data, that's what buffers are for. But learning to do things with a new datatype? Pffft. DDE sends and receives data over the serial port as Strings like god intended. And that is probably the best design because most users will send and receive ASCII data and expect to work with Strings.
But when you need to send / receive binary data? Well the npm SerialPort library sets the encoding to UTF-8 by default. Not sure why... for files, yeah... for serial data? Lucky us, we can change that:
https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings
var port_path = "/dev/ttyUSB0" // "COM4" //last(serial_devices()).comName
var acc_data="" //a variable to accumulate data into. Actually need one for each port.
var data_pause //the setTimeout ID
function myOnReceiveCallback_low_level(data, port) {
acc_data += data
clearTimeout(data_pause)
data_pause = setTimeout(
function() {
out(acc_data.split('').reduce((s,i) => s+("0"+i.charCodeAt(0).toString(16)).slice(-2)+" ", ''))
acc_data=''
}
, 100
)
}
serial_connect_low_level(port_path
, {baudRate: 115200}
, capture_n_items=0
, item_delimiter=""
, trim_whitespace = false
, parse_items=false
, capture_extras=false
, callback=myOnReceiveCallback_low_level
//, error_callback=onReceiveErrorCallback_low_level
//, open_callback=onOpenCallback_low_level
//, close_callback=onCloseCallback_low_level
)
var port_info = serial_port_path_to_info_map[port_path]
//need binary encoding.
port_info.port.setEncoding("binary")
//Make a "binary" string from HEX data
var dmi820get = ""
"68 04 00 04 08".split(" ").forEach(str => {
dmi820get += String.fromCharCode(parseInt(str,16))
})
//If we use the built in send it dumps binary data to the Output panel
//serial_send_low_level(ard_path, dmi820get)
//but we can replace it:
function dmi820_get_data(port_info) {
if (port_info){
let arr =
port_info.port.write(dmi820get,
function(error){ //can't rely on this getting called before onReceived so mostly pretend like its not called, except in error cases
if (error){
dde_error("In serial_send callback to port_path: " + port_path +
" got the error: " + error.message)
}
else {
//out("serial write just sent: " + dmi820get)
}
}
)
}
}
dmi820_get_data(port_info)
Long story only slightly longer. This cost me a day. I see absolutely no reason for the encoding in a serial data transfer to be UTF-8. I would propose that in DDE, every serial port opened be set to "binary" encoding via .setEncoding("binary") as shown in the sample. It shouldn't mess up standard ASCII data (that should be tested), and it will allow us to communicate with binary devices.
If you have a Control.loop or Robot.loop in the do_list, and you click on it, it does not lead to the entry in the Doc for Control.loop.
For Robot.loop, it shows the function, for Control.loop, it shows something about an HTML attribute?
The .joint_angles(), and .robot_status[Dexter.J1_ANGLE], etc... do NOT feedback the
actual angle of the joint from the robot.
.robot_status[Dexter.J1_FORCE_CALC_ANGLE] etc... appears to return the joint angles.
I'm not sure if that is a DDE operational error or a documentation error.
speak({speak_data: "Level.", voice: 0} through speak({speak_data: "Level.", voice: 3} all appear to be the same female voice.
(documenting this here because I don't see it, although I know we are aware of it)
The suggestion has been made to move to an HTTP socket based file data exchange. This requires the DexRun.c program be updated to support commands for the transfer of file and directory data. E.g. a letter needs to be assigned to a command, and the block of data transferred would be a path or file name as well as a block number since data blocks are of limited size.
Suggested operations
Get folder item count: If the command is for a directory, and block 0, the returned data would be the number of files and folders under that dir.
Get folder item data: Then each would be iterated by repeating the directory and using block 1, 2, 3... for each folder/file in the dir. In that case, the return data would be the file name, size, and any other important properties.
Get item size: To access a file, first the file path/name would be sent and then block 0 would return the size of the file in blocks
Get item data: To get the actual file data, the block numbers 1,2,3... are sent and each returns that block of data from the file. On the Dexter side, it can be assumed that the file will be read out in block order, so the standard sequential fgets should be fine. Dexter just needs to track the block expected vs the block it's on (by count of calls to fgets with block size buffer) and then send back an error with the current block number if there is an issue. A lost block would, however, require reseeking... I think that can be done with lseek... might be better to close the file after each block and when reading block X, open the file, lseek to that position (block size * block number) and then gets a block.
Put item data: Same as before, but it's writing that block of data to the file. Because the data is now flowing from DDE to Dexter, sending the path each time wastes block space, so maybe Dexter just writes to whatever the last file that was read? So we only send the block number and the rest of the buffer is file data. Block size is buffer size less the size of the block number.
C functions (I think this works in Linux) to get info on a directory:
http://techref.massmind.org/techref/language/ccpp/cref/FUNCTIONS/directory.html
Open a file:
http://techref.massmind.org/techref/language/ccpp/cref/FUNCTIONS/fopen.html
Read data from a file:
http://techref.massmind.org/techref/language/ccpp/cref/FUNCTIONS/fgets.html
Move to a location in a file:
http://www.massmind.org/Techref/language/ccpp/cref/man/lseek.htm
(it may be fseek is right... I haven't done this is a long time)
Write data to a file:
http://www.massmind.org/techref/language/ccpp/cref/man/fputs.htm
If I can get my Dexter setup for development, and this seems good, I'll be happy to try to work on the c code.
On the Job Engine, the callback is called by "exec" and has error, stdout, and stderror paramters, on the PC it's called by the built in speech synth, and provides an "event" object.
Combining those seems impossible. You suggested providing two different callbacks.
"." and "," need to be added
Version 3.8.0
Issue:
open DDE -> input characters into any file using Editor -> switch open files -> cannot add characters but cannot delete characters in any file, also cannot input text into any other text boxes in DDE
Mitigation:
clicking outside of DDE i.e. on taskbar, selecting a new app etc. allows editing of any file once again until you try to edit a different file, the issue occurs again ad infinitum
When Robot.loop() has a first arg of a number it will work the first time the Job is run.
After the job completes and is run again without re-evaling it Robot.loop() does not run the instructions in its second arg.
Selecting Job / Cal and then selecting at least joint 4 (and I think all joints?) does not actually process the entire rotation of the joint. As a result, errors in the encoder disk, or its alignment, are not seen. Also, changes in the "eye" opening as a result of even minor alignment changes from one end of the rotation to the other are not detected.
This was the cause of the "freak out" in my Dexter arm, which is now resolved.
The desktop file is lacking a Categories=
entry in the *.desktop
file.
According to the menu spec,
By including one of the Main Categories in an application's desktop entry file, the application will be ensured that it will show up in a section of the application menu dedicated to this category. If multiple Main Categories are included in a single desktop entry file, the entry may appear more than once in the menu.
Hence, please add at least one of the following in the Categories=
key.
Main Category | Description | Notes |
---|---|---|
AudioVideo | Application for presenting, creating, or processing multimedia (audio/video) | |
Audio | An audio application | Desktop entry must include AudioVideo as well |
Video | A video application | Desktop entry must include AudioVideo as well |
Development | An application for development | |
Education | Educational software | |
Game | A game | |
Graphics | Application for viewing, creating, or processing graphics | |
Network | Network application such as a web browser | |
Office | An office type application | |
Science | Scientific software | |
Settings | Settings applications | Entries may appear in a separate menu or as part of a "Control Center" |
System | System application, "System Tools" such as say a log viewer or network monitor | |
Utility | Small utility application, "Accessories" |
In addition, you could specify one or more from the longer list of Additional Categories.
Please test the result with desktop-file-validate
and make sure it passes.
electron-builder offers native support for this since v19.22.1.
Reference: AppImage/appimage.github.io#2
Workaround: NEVER fail to save your code constantly. Duh.
Suggested fix: Open links in a new browser window.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.