Skip to content

Commit

Permalink
release
Browse files Browse the repository at this point in the history
  • Loading branch information
cfry committed Apr 7, 2021
1 parent 569fe9f commit 7004a9e
Show file tree
Hide file tree
Showing 19 changed files with 291 additions and 103 deletions.
3 changes: 2 additions & 1 deletion core/dextersim.js
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,8 @@ DexterSim = class DexterSim{
}
return 0 //dur
}

//The corresponding fn for Dexter causes DexRun to crash, so we've commented out all calls to it.
//When FPGA is updated to support it, we can re_instate it as a regular function.
static empty_instruction_queue_now(robot_name){
if(DexterSim.robot_name_to_dextersim_instance_map) {
let sim_inst = DexterSim.robot_name_to_dextersim_instance_map[robot_name]
Expand Down
4 changes: 2 additions & 2 deletions core/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
global.dde_version = require("../package.json").version
global.dde_release_date = require("../package.json").release_date
global.dde_version = "3.7.9" //require("../package.json").version
global.dde_release_date = "Apr 7, 2021" //require("../package.json").release_date

console.log("dde_version: " + global.dde_version + " dde_release_date: " + global.dde_release_date +
"\nRead electron_dde/core/job_engine_doc.txt for how to use the Job Engine.\n")
Expand Down
16 changes: 9 additions & 7 deletions core/job.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class Job{
}
if (Job[name] && Job[name].is_active()) { //we're redefining the job so we want to make sure the
//previous version is stopped.
if (Job[name].robot instanceof Dexter) {Job[name].robot.empty_instruction_queue_now() }
//if (Job[name].robot instanceof Dexter) {Job[name].robot.empty_instruction_queue_now() }
Job[name].stop_for_reason("interrupted", "User is redefining this job.")
let orig_args = arguments[0]
setTimeout(function(){ new Job (orig_args) }, 200)
Expand Down Expand Up @@ -728,6 +728,7 @@ class Job{
//not focused, pressing the space or ENTER key doesn't do something strange
//like an extra button click.
const job_instance = Job[job_name]
console.log("Job button clicked when status was: " + job_instance.status_code)
if (job_instance.status_code == "suspended"){
if(but_elt.title.includes("Make Instruction")) { job_instance.stop_for_reason("interrupted", "User stopped job.") }
else { job_instance.unsuspend() }
Expand All @@ -738,7 +739,7 @@ class Job{
job_instance.color_job_button() //keep this call
}
else if(job_instance.is_active()){
if (job_instance.robot instanceof Dexter) { job_instance.robot.empty_instruction_queue_now() }
//if (job_instance.robot instanceof Dexter) { job_instance.robot.empty_instruction_queue_now() }
job_instance.stop_for_reason("interrupted", "User stopped job", false)
}
else { //restart this job on Dexter
Expand All @@ -747,7 +748,9 @@ class Job{
}
}
else if(job_instance.is_active()){
if (job_instance.robot instanceof Dexter) { job_instance.robot.empty_instruction_queue_now() }
if (job_instance.robot instanceof Dexter) {
//job_instance.robot.empty_instruction_queue_now() //causes DexRun to error.
}
job_instance.stop_for_reason("interrupted", "User stopped job", false)
}
else {
Expand Down Expand Up @@ -792,7 +795,7 @@ class Job{
job_instance.unsuspend()
}
else if(job_instance.is_active()){
if (job_instance.robot instanceof Dexter) { job_instance.robot.empty_instruction_queue_now() }
//if (job_instance.robot instanceof Dexter) { job_instance.robot.empty_instruction_queue_now() }
job_instance.stop_for_reason("interrupted", "User stopped job", false)
}
else {
Expand Down Expand Up @@ -1258,8 +1261,8 @@ Job.last_job = null
Job.stop_all_jobs = function(){
var stopped_job_names = []
for(var j of Job.all_jobs()){
if (j.robot instanceof Dexter) { j.robot.empty_instruction_queue_now() }
if ((j.stop_reason == null) && (j.status_code != "not_started")){
//if (j.robot instanceof Dexter) { j.robot.empty_instruction_queue_now() }
if ((j.stop_reason == null) && (j.status_code !== "not_started")){
j.stop_for_reason("interrupted_by_stop_button", "User stopped all jobs.", false)
stopped_job_names.push(j.name)
}
Expand Down Expand Up @@ -2052,7 +2055,6 @@ Job.prototype.do_next_item = function(){ //user calls this when they want the jo
}
}
}
//this.color_job_button() //todo needs to work for Dexter.sleep (z) instruction and to undo its yellow.

///also called by Make Instruction for creating string to save.
Job.prototype.transform_data_array = function(data_array){
Expand Down
5 changes: 3 additions & 2 deletions core/main_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import traceback
import json

dde_py_globals = {'sys': sys}
def main():
print("Python eval process started.\n", flush=True)
while True:
Expand All @@ -24,7 +25,7 @@ def main():
is_py_evalable = True
if is_py_evalable:
try:
result = eval(src)
result = eval(src, dde_py_globals)
if str(type(result)) == "<class 'numpy.ndarray'>":
result = result.tolist()
except Exception as err :
Expand All @@ -35,7 +36,7 @@ def main():
is_error = False
else:
try:
exec(src)
exec(src, dde_py_globals)
except Exception as err:
is_error = True
result = traceback.format_exc()
Expand Down
1 change: 1 addition & 0 deletions core/py.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class Py{
});
this.callbacks = [this.default_callback] //clear out old callbacks, and add back the default.
this.eval('sys.path.append("' + dde_apps_folder + '")')
this.eval("dde_apps_folder = '" + dde_apps_folder + "'")
}

//callback takes 1 arg, a json_object with is_error, source, result properties
Expand Down
7 changes: 6 additions & 1 deletion core/robot.js
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,9 @@ Dexter = class Dexter extends Robot {
}

close_robot(){
out("top of Dexter.close_robot")
//setTimeout(function(){
//out("top of timeout fn Dexter.close_robot")
clearTimeout(this.heartbeat_timeout_obj) //looks like not working
this.waiting_for_heartbeat = false
this.heartbeat_timeout_obj = null
Expand All @@ -1280,11 +1283,13 @@ Dexter = class Dexter extends Robot {
// delete Dexter[this.name] //don't do this. If the robot is still part of a Job,
//and that job is inactive, then we can still "restart" the job,
//and as such we want that binding of Robot.this_name to still be around.
//}, 5000)
}

/* causes DexRun to crash. re-inswtate when FPGA code rewriten to support this
empty_instruction_queue_now(){
Socket.empty_instruction_queue_now(this.name)
}
}*/

//ins_array can be an oplet array or a raw string
send(oplet_array_or_string){
Expand Down
54 changes: 37 additions & 17 deletions core/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var Socket = class Socket{
out("socket for Robot." + robot_name + ". is_connected? " + Robot[robot_name].is_connected)
}
else if ((sim_actual === false) || (sim_actual == "both")) {
if(!Socket.robot_name_to_ws_instance_map[robot_name]){
if(!Socket.robot_name_to_soc_instance_map[robot_name]){
try {
let ws_inst = new net.Socket()
ws_inst.on("data", function(data) {
Expand All @@ -32,7 +32,7 @@ var Socket = class Socket{
let st_inst = setTimeout(function(){
if(ws_inst.connecting) { //still trying to connect after 1 sec, so presume it never will. kill it
out("Socket timeout while connecting to Dexter." + robot_name)
delete Socket.robot_name_to_ws_instance_map[robot_name]
delete Socket.robot_name_to_soc_instance_map[robot_name]
ws_inst.destroy() //todo destroy
if(connect_error_cb) {
connect_error_cb() //stop the job that started this.
Expand All @@ -42,7 +42,7 @@ var Socket = class Socket{
ws_inst.on("error", function(err){
out("Socket error while connecting to Dexter." + robot_name)
clearTimeout(st_inst)
delete Socket.robot_name_to_ws_instance_map[robot_name]
delete Socket.robot_name_to_soc_instance_map[robot_name]
ws_inst.destroy()
if(connect_error_cb) {
connect_error_cb()
Expand All @@ -51,7 +51,7 @@ var Socket = class Socket{
out("Now attempting to connect to Dexter." + robot_name + " at ip_address: " + rob.ip_address + " port: " + rob.port + " ...", "brown")
ws_inst.connect(rob.port, rob.ip_address, function(){
clearTimeout(st_inst)
Socket.robot_name_to_ws_instance_map[robot_name] = ws_inst
Socket.robot_name_to_soc_instance_map[robot_name] = ws_inst
Socket.new_socket_callback(robot_name, connect_success_cb)
})
}
Expand Down Expand Up @@ -374,6 +374,10 @@ var Socket = class Socket{
static send(robot_name, oplet_array_or_string){ //can't name a class method and instance method the same thing
//onsole.log("Socket.send passed oplet_array_or_string: " + oplet_array_or_string)
let rob = Robot[robot_name]
if(rob.waiting_for_instruction_ack) {
dde_error("In Socket.send, attempt to send instruction: " + oplet_array_or_string +
" but still waiting for previous instruction: " + rob.waiting_for_instruction_ack)
}
if(oplet_array_or_string !== Socket.resend_instruction){ //we don't want to convert an array more than once as that would have degreees * 3600 * 3600 ...
//so only to the convert on the first attempt.
oplet_array_or_string = Socket.instruction_array_degrees_to_arcseconds_maybe(oplet_array_or_string, rob)
Expand All @@ -387,13 +391,17 @@ var Socket = class Socket{
const arr_buff = Socket.string_to_array_buffer(str)
const sim_actual = Robot.get_simulate_actual(rob.simulate)
if((sim_actual === true) || (sim_actual === "both")){
rob.waiting_for_instruction_ack = oplet_array_or_string
DexterSim.send(robot_name, arr_buff)
}
if ((sim_actual === false) || (sim_actual === "both")) {
let ws_inst = Socket.robot_name_to_ws_instance_map[robot_name]
let ws_inst = Socket.robot_name_to_soc_instance_map[robot_name]
if(ws_inst) {
try {
rob.waiting_for_instruction_ack = oplet_array_or_string
//console.log("Socket.send about to send: " + str)
ws_inst.write(arr_buff) //if doesn't error, success and we're done with send
//console.log("Socket.send just sent: " + str)
Socket.resend_instruction = null
Socket.resend_count = null
//this.stop_job_if_socket_dead(job_id, robot_name)
Expand Down Expand Up @@ -458,7 +466,13 @@ var Socket = class Socket{
//
static on_receive(data, robot_name, payload_string_maybe){
//data.length == 240 data is of type: Uint8Array, all values between 0 and 255 inclusive
//onsole.log("Socket.on_receive passed data: " + data)
//console.log("Socket.on_receive passed data: " + data)
let rob = Dexter[robot_name]
if(rob.waiting_for_instruction_ack){ } //ok todo check that data has in it the instruction ack that we are expecting.
else {
dde_error("Socket.on_receive is not expecting data from Dexter.")
}
rob.waiting_for_instruction_ack = false
let robot_status
let oplet
if(Array.isArray(data)) { //todo return from sim same data type as Dexter returns. //a status array passed in from the simulator
Expand All @@ -475,6 +489,7 @@ var Socket = class Socket{
let opcode = robot_status[Dexter.INSTRUCTION_TYPE]
oplet = String.fromCharCode(opcode)
}
//console.log("Socket.on_receive passed robot status: " + robot_status)
//the simulator automatically does this so we have to do it here in non-simulation
//out("on_receive got back oplet of " + oplet)
robot_status[Dexter.INSTRUCTION_TYPE] = oplet
Expand All @@ -500,7 +515,7 @@ var Socket = class Socket{
else {
Socket.convert_robot_status_to_degrees(robot_status)
}
let rob = Dexter[robot_name]

//Socket.robot_is_waiting_for_reply[robot_name] = false
rob.robot_done_with_instruction(robot_status) //robot_status ERROR_CODE *might* be 1
}
Expand Down Expand Up @@ -624,28 +639,33 @@ var Socket = class Socket{
}
if ((sim_actual === false) || (sim_actual == "both")){
if((rob.active_jobs_using_this_robot().length == 0) || force_close){
const ws_inst = Socket.robot_name_to_ws_instance_map[robot_name]
if(ws_inst){
ws_inst.removeAllListeners()
ws_inst.destroy()
delete Socket.robot_name_to_ws_instance_map[robot_name]
const soc_instance = Socket.robot_name_to_soc_instance_map[robot_name]
if(soc_instance){
//out("about to destroy socket")
//setTimeout(function(){
soc_instance.removeAllListeners()
soc_instance.destroy()
delete Socket.robot_name_to_soc_instance_map[robot_name]
//out("destroyed socket")
//}, 5000)
}
}
}
}

/*this causes DexRun to crash. Ultimately we need to rewrite FPGA code to get this functionality.
static empty_instruction_queue_now(robot_name){
let rob = Robot[robot_name]
const sim_actual = Robot.get_simulate_actual(rob.simulate)
if ((sim_actual === true) || (sim_actual === "both")){ //simulation
DexterSim.empty_instruction_queue_now(robot_name)
}
if ((sim_actual === false) || (sim_actual == "both")){
const ws_inst = Socket.robot_name_to_ws_instance_map[robot_name]
if(ws_inst && !ws_inst.destroyed){
const soc_inst = Socket.robot_name_to_soc_instance_map[robot_name]
if(soc_inst && !soc_inst.destroyed){
const oplet_array = make_ins("E") //don't expect to hear anything back from this.
const arr_buff = this.oplet_array_or_string_to_array_buffer(oplet_array)
try { ws_inst.write(arr_buff) } //band-aid for not knowing what's in Dexter's queue.
try { soc_inst.write(arr_buff) } //band-aid for not knowing what's in Dexter's queue.
//if the queue is empty we shouldn't do.
//we should empty the queue whenever DDE detects an error,
//but before closing the socket.
Expand All @@ -655,7 +675,7 @@ var Socket = class Socket{
}
}
}
}
}*/
}

//Socket.robot_is_waiting_for_reply = {} //robot_name to boolean map.
Expand All @@ -668,7 +688,7 @@ Socket.PAYLOAD_LENGTH = 6 //6th integer array index
Socket.resend_instruction = null
Socket.resend_count = null

Socket.robot_name_to_ws_instance_map = {}
Socket.robot_name_to_soc_instance_map = {}
Socket.DEGREES_PER_DYNAMIXEL_320_UNIT = 0.29 //range of motion sent is 0 to 1023
Socket.DEGREES_PER_DYNAMIXEL_430_UNIT = 360 / 4096
Socket.J6_OFFSET_SERVO_UNITS = 512
Expand Down
12 changes: 7 additions & 5 deletions core/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -442,12 +442,14 @@ module.exports.pad_integer = pad_integer

//used in computing numbers to display in the robot_status dialog
function to_fixed_smart(num, digits=0){
if((num == "no status") || (num === undefined)) { return num }
try{ return num.toFixed(digits)}
catch(err){
warning("to_fixed_smart called with non_number: " + num)
return "" + num
if(typeof(num) === "number") {
try{ return num.toFixed(digits)}
catch(err){
warning("to_fixed_smart called with non_number: " + num)
return "" + num
}
}
else { return num } //presume its a string like "N/A" and leave it alone.
}
module.exports.to_fixed_smart = to_fixed_smart

Expand Down
6 changes: 3 additions & 3 deletions doc/guide.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

<details class="doc_details"><summary>About</summary>
This is <a href="http://hdrobotic.com/" target="_blank">Dexter</a> Development Environment<br/>
version: <span id="dde_version_id">3.7.8</span><br/>
released: <span id="dde_release_date_id">Apr 2, 2021</span>
version: <span id="dde_version_id">3.7.9</span><br/>
released: <span id="dde_release_date_id">Apr 7, 2021</span>
<p></p>
DDE helps you create, debug, and send software to a Dexter robot.
You can use any JavaScript augmented with DDE-specific functions to help find out about,
Expand Down Expand Up @@ -1311,7 +1311,7 @@ <h5>Step 3</h5>

</details> <!-- end user interface -->

<details class="doc_details"><summary>JavaScript</summary>
<details id="JavaScript_guide_id" class="doc_details"><summary>JavaScript</summary>
DDE let's you control a Dexter robot with Javascript. You can execute all of JS.
DDE extends JavaScript with libraries of functions that control Dexter, allow access to Unix commands
on Dexter's computer, allows access to HTML and the DOM, has a convenient window system
Expand Down
2 changes: 0 additions & 2 deletions doc/known_issues.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
with this DDE release. All of them are on our "do list".
<p></p>
<ul>
<li><code>Py.eval</code> does not work for Python code containing
both expressions and statements</li>
<li> The simulator <b>both</b> setting does not work.</li>
<li> The simulator does not work for ANGLE, DELTA, PID_DELTA, A2D_SIN, A2D_COS.</li>
<li>The Messaging software is not yet intended for public use. We're still testing.</li>
Expand Down
Loading

0 comments on commit 7004a9e

Please sign in to comment.